Viewing file: periodic.php (16.84 KB) -rwxr-xr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#!/usr/bin/php5
<?php include("config.php");
$group_data = array(); $group_stats = array(); $group_stats_old = array(); $timemark = 0; $new_timemark = time(0);
if (file_exists($tmp_file) && $uptime > 300) { $group_stats_old = unserialize(file_get_contents($tmp_file)); $timemark = $group_stats_old[0]->timemark; }
$file_array = file($group_file); foreach ($file_array as $line_number => $line) { $a = explode(":",$line); $group = trim($a[0]); $gid = trim($a[2]); if ($group != "") $group_data[$gid]->group = $group; } ksort($group_data);
/* 1 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 owner GID match 1035 multiport dports 25,465
2 0 0 ACCEPT tcp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035 limit: avg 10000/sec burst 5 3 0 0 DROP tcp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035
4 0 0 ACCEPT udp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035 limit: avg 1000/sec burst 5 5 0 0 DROP udp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035
6 0 0 ACCEPT icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035 limit: avg 100/sec burst 5 7 0 0 DROP icmp -- * eth0 0.0.0.0/0 0.0.0.0/0 owner GID match 1035
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 */
exec("iptables --line-numbers -xvnL | grep '0.0.0.0'", $rules); foreach ($rules as $r) { $a = preg_split("/[\ ]+/", $r); $id = $a[0]; $pkts = $a[1]; $bytes = $a[2]; $chain = $a[3]; $proto = $a[4]; $gid = $a[13]; $type = $a[14]; // "limit:" or "multiport" $limit = explode("/", $a[16]); // 1000/sec $limit = $limit[0]; $group_stats[$gid]->group = $group_data[$gid]->group;
if ($gid == "1000-2147483648" || $chain == "ISPMGR") { continue; } //ispmgr stuff, we'll skip it
if ($proto == "all" && $chain == "DROP") { // other stuff to skip $group_data[0]->drop_all = true; continue; } if ($proto == "tcp" && $type == "multiport" && $chain == "DROP") { $group_data[$gid]->drop_multiport = true; $group_stats[$gid]->drop_smtp_bytes = $bytes; $group_stats[$gid]->drop_smtp_pkts = $pkts; continue; } if ($proto == "tcp" && $type != "multiport") { if ($chain == "ACCEPT") { $group_data[$gid]->accept_tcp = true; $group_stats[$gid]->accept_tcp_bytes = $bytes; $group_stats[$gid]->accept_tcp_pkts = $pkts; continue; } if ($chain == "DROP") { $group_data[$gid]->drop_tcp = true; $group_stats[$gid]->drop_tcp_bytes = $bytes; $group_stats[$gid]->drop_tcp_pkts = $pkts; continue; } if ($chain == "COUNT".$gid) { $group_data[$gid]->count_tcp = true; $group_stats[$gid]->count_tcp_bytes = $bytes; $group_stats[$gid]->count_tcp_pkts = $pkts; } } if ($proto == "udp") { if ($chain == "ACCEPT") { $group_data[$gid]->accept_udp = true; $group_stats[$gid]->accept_udp_bytes = $bytes; $group_stats[$gid]->accept_udp_pkts = $pkts; continue; } if ($chain == "DROP") { $group_data[$gid]->drop_udp = true; $group_stats[$gid]->drop_udp_bytes = $bytes; $group_stats[$gid]->drop_udp_pkts = $pkts; continue; } if ($chain == "COUNT".$gid) { $group_data[$gid]->count_udp = true; $group_stats[$gid]->count_udp_bytes = $bytes; $group_stats[$gid]->count_udp_pkts = $pkts; } } if ($proto == "icmp") { if ($chain == "ACCEPT") { $group_data[$gid]->accept_icmp = true; $group_stats[$gid]->accept_icmp_bytes = $bytes; $group_stats[$gid]->accept_icmp_pkts = $pkts; continue; } if ($chain == "DROP") { $group_data[$gid]->drop_icmp = true; $group_stats[$gid]->drop_icmp_bytes = $bytes; $group_stats[$gid]->drop_icmp_pkts = $pkts; continue; } if ($chain == "COUNT".$gid) { $group_data[$gid]->count_icmp = true; $group_stats[$gid]->count_icmp_bytes = $bytes; $group_stats[$gid]->count_icmp_pkts = $pkts; } } }
function add_count_rule($group, $gid) { syslog(LOG_INFO, "Adding count rules: group=".$group." gid=".$gid); $chain = "COUNT".$gid; $handle = popen('iptables-restore -n', 'w'); fwrite($handle, "*filter\n"); fwrite($handle, ":INPUT ACCEPT [0:0]\n"); fwrite($handle, ":FORWARD ACCEPT [0:0]\n"); fwrite($handle, ":OUTPUT ACCEPT [0:0]\n"); fwrite($handle, ":$chain - [0:0]\n"); fwrite($handle, "-I OUTPUT 1 -o eth0 -p tcp -m owner --gid-owner $gid -j $chain\n"); fwrite($handle, "-I OUTPUT 2 -o eth0 -p udp -m owner --gid-owner $gid -j $chain\n"); fwrite($handle, "-I OUTPUT 3 -o eth0 -p icmp -m owner --gid-owner $gid -j $chain\n"); fwrite($handle, "COMMIT\n"); pclose($handle); }
function delete_count_rule($group, $gid) { syslog(LOG_INFO, "Deleting count rules: group=".$group." gid=".$gid); $chain = "COUNT".$gid; system("iptables -D OUTPUT -o eth0 -p tcp -m owner --gid-owner $gid -j $chain 2>/dev/null"); system("iptables -D OUTPUT -o eth0 -p udp -m owner --gid-owner $gid -j $chain 2>/dev/null"); system("iptables -D OUTPUT -o eth0 -p icmp -m owner --gid-owner $gid -j $chain 2>/dev/null"); }
function add_all_rules($group, $gid, $block) { $c = 1; syslog(LOG_INFO, "Adding rules: group=".$group." gid=".$gid." tcp_limit=".TCP_LIMIT." udp_limit=".UDP_LIMIT." icmp_limit=".ICMP_LIMIT." drop=".bool2string($block)); $handle = popen('iptables-restore -n', 'w'); fwrite($handle, "*filter\n"); fwrite($handle, ":INPUT ACCEPT [0:0]\n"); fwrite($handle, ":FORWARD ACCEPT [0:0]\n"); fwrite($handle, ":OUTPUT ACCEPT [0:0]\n"); if (!$block) fwrite($handle, "-I OUTPUT ".$c++." -p tcp -d 91.200.40.224/27 -m owner --gid-owner $gid -j ACCEPT\n"); fwrite($handle, "-I OUTPUT ".$c++." -p tcp -m owner --gid-owner $gid -m multiport --dport ".MAIL_PORTS." -j DROP\n"); fwrite($handle, "-I OUTPUT ".$c++." -p tcp -m owner --gid-owner $gid -d 91.200.40.0/24 --dport 443 -j DROP\n"); fwrite($handle, "-I OUTPUT ".$c++." -p tcp -m owner --gid-owner $gid -d 127.0.0.1 --dport 443 -j DROP\n"); if (!$block) fwrite($handle, "-I OUTPUT ".$c++." -p tcp -m owner --gid-owner $gid -m limit --limit ".TCP_LIMIT."/sec --limit-burst ".TCP_LIMIT." -j ACCEPT\n"); fwrite($handle, "-I OUTPUT ".$c++." -p tcp -m owner --gid-owner $gid -j DROP\n"); if (!$block) fwrite($handle, "-I OUTPUT ".$c++." -p udp -m owner --gid-owner $gid -m limit --limit ".UDP_LIMIT."/sec --limit-burst ".UDP_LIMIT." -j ACCEPT\n"); fwrite($handle, "-I OUTPUT ".$c++." -p udp -m owner --gid-owner $gid -j DROP\n"); if (!$block) fwrite($handle, "-I OUTPUT ".$c++." -p icmp -m owner --gid-owner $gid -m limit --limit ".ICMP_LIMIT."/sec --limit-burst ".ICMP_LIMIT." -j ACCEPT\n"); fwrite($handle, "-I OUTPUT ".$c++." -p icmp -m owner --gid-owner $gid -j DROP\n"); fwrite($handle, "COMMIT\n"); pclose($handle); }
function delete_all_rules($group, $gid) { syslog(LOG_INFO, "Deleting rules: group=".$group." gid=".$gid); system("iptables -D OUTPUT -p tcp -d 91.200.40.224/27 -m owner --gid-owner $gid -j ACCEPT 2>/dev/null"); system("iptables -D OUTPUT -p tcp -m owner --gid-owner $gid -m multiport --dport ".MAIL_PORTS." -j DROP 2>/dev/null"); system("iptables -D OUTPUT -p tcp -m owner --gid-owner $gid -d 91.200.40.0/24 --dport 443 -j DROP 2>/dev/null"); system("iptables -D OUTPUT -p tcp -m owner --gid-owner $gid -d 127.0.0.1 --dport 443 -j DROP 2>/dev/null"); system("iptables -D OUTPUT -p tcp -m owner --gid-owner $gid -m limit --limit ".TCP_LIMIT."/sec --limit-burst ".TCP_LIMIT." -j ACCEPT 2>/dev/null"); system("iptables -D OUTPUT -p tcp -m owner --gid-owner $gid -j DROP 2>/dev/null"); system("iptables -D OUTPUT -p udp -m owner --gid-owner $gid -m limit --limit ".UDP_LIMIT."/sec --limit-burst ".UDP_LIMIT." -j ACCEPT 2>/dev/null"); system("iptables -D OUTPUT -p udp -m owner --gid-owner $gid -j DROP 2>/dev/null"); system("iptables -D OUTPUT -p icmp -m owner --gid-owner $gid -m limit --limit ".ICMP_LIMIT."/sec --limit-burst ".ICMP_LIMIT." -j ACCEPT 2>/dev/null"); system("iptables -D OUTPUT -p icmp -m owner --gid-owner $gid -j DROP 2>/dev/null"); }
$stats = array();
if (count($group_stats_old) > 0) { $delta_t = $new_timemark - $timemark; foreach ($group_stats_old as $gid => $stat) { $group = $stat->group; if ($gid >= 1000) { if (isset($stat->block_counter)) $group_stats[$gid]->block_counter = $stat->block_counter; if (isset($stat->block_counter_updated)) $group_stats[$gid]->block_counter_updated = $stat->block_counter_updated; if (isset($stat->tcp_rate)) $group_stats[$gid]->tcp_rate = $stat->tcp_rate; if (isset($stat->udp_rate)) $group_stats[$gid]->udp_rate = $stat->udp_rate; if (isset($stat->icmp_rate)) $group_stats[$gid]->icmp_rate = $stat->icmp_rate; if (isset($stat->smtp_rate)) $group_stats[$gid]->smtp_rate = $stat->smtp_rate; if (isset($stat->block)) $group_stats[$gid]->block = $stat->block;
$tcp_accept_rate = round(($stat->accept_tcp_pkts >= $group_stats[$gid]->accept_tcp_pkts) ? 0 : ($group_stats[$gid]->accept_tcp_pkts - $stat->accept_tcp_pkts)/$delta_t, 2); $udp_accept_rate = round(($stat->accept_udp_pkts >= $group_stats[$gid]->accept_udp_pkts) ? 0 : ($group_stats[$gid]->accept_udp_pkts - $stat->accept_udp_pkts)/$delta_t, 2); $icmp_accept_rate = round(($stat->accept_icmp_pkts >= $group_stats[$gid]->accept_icmp_pkts) ? 0 : ($group_stats[$gid]->accept_icmp_pkts - $stat->accept_icmp_pkts)/$delta_t, 2);
$tcp_drop_rate = round(($stat->drop_tcp_pkts >= $group_stats[$gid]->drop_tcp_pkts) ? 0 : ($group_stats[$gid]->drop_tcp_pkts - $stat->drop_tcp_pkts)/$delta_t, 2); $udp_drop_rate = round(($stat->drop_udp_pkts >= $group_stats[$gid]->drop_udp_pkts) ? 0 : ($group_stats[$gid]->drop_udp_pkts - $stat->drop_udp_pkts)/$delta_t, 2); $icmp_drop_rate = round(($stat->drop_icmp_pkts >= $group_stats[$gid]->drop_icmp_pkts) ? 0 : ($group_stats[$gid]->drop_icmp_pkts - $stat->drop_icmp_pkts)/$delta_t, 2);
$smtp_drop_rate = round(($stat->drop_smtp_pkts >= $group_stats[$gid]->drop_smtp_pkts) ? 0 : ($group_stats[$gid]->drop_smtp_pkts - $stat->drop_smtp_pkts)/$delta_t, 2);
$tcp_rate = $tcp_accept_rate + $tcp_drop_rate; $udp_rate = $udp_accept_rate + $udp_drop_rate; $icmp_rate = $icmp_accept_rate + $icmp_drop_rate;
$smtp_rate = $smtp_drop_rate; $total_rate = $tcp_rate + $udp_rate + $icmp_rate + $smtp_rate;
if ($total_rate > 0) echo $group." ".$total_rate." pps\n"; if ($tcp_rate >= TCP_LIMIT || $udp_rate >= UDP_LIMIT || $icmp_rate >= ICMP_LIMIT || $smtp_rate >= SMTP_LIMIT) { $group_stats[$gid]->block_counter = $stat->block_counter + 1; $group_stats[$gid]->block_counter_updated = $new_timemark;
$group_stats[$gid]->tcp_rate = $tcp_rate; $group_stats[$gid]->udp_rate = $udp_rate; $group_stats[$gid]->icmp_rate = $icmp_rate; $group_stats[$gid]->smtp_rate = $smtp_rate;
$stats[$gid]->tcp_rate = $tcp_rate; $stats[$gid]->udp_rate = $udp_rate; $stats[$gid]->icmp_rate = $icmp_rate; $stats[$gid]->smtp_rate = $smtp_rate; $stats[$gid]->group = $group_stats[$gid]->group; // print_r($group_stats[$gid]);
} else $group_stats[$gid]->block_counter = 0; if ($group_stats[$gid]->block_counter >= BLOCK_THRESHOLD) { if (!isset($group_stats[$gid]->block) || $group_stats[$gid]->block != true) $stats[$gid]->just_blocked = true; $group_stats[$gid]->block = true; } } } } //print_r($stats);
foreach ($group_data as $gid => $group) { if ($gid < 1000) { if (!$group->count_icmp && !$group->count_udp && !$group->count_tcp) add_count_rule($group->group, $gid); else { if (!$group->count_icmp || !$group->count_udp || !$group->count_tcp) { delete_count_rule($group->group, $gid); add_count_rule($group->group, $gid); } } } else { if ($group->accept_icmp && $group->accept_udp && $group->accept_tcp) { $group->accept_ok = true; } else { if ($group->accept_icmp || $group->accept_udp || $group->accept_tcp) $group->accept_not_all = true; $group->accept_ok = false; }
if ($group->drop_icmp && $group->drop_udp && $group->drop_tcp && $group->drop_multiport) { $group->drop_ok = true; } else { if ($group->drop_icmp || $group->drop_udp || $group->drop_tcp || $group->drop_multiport) $group->drop_not_all = true; $group->drop_ok = false; }
if ($group_stats[$gid]->block) { if (!$group->drop_ok && !$group->drop_not_all && !$group->accept_ok && !$group->accept_not_all) add_all_rules($group->group, $gid, true); if ($group->accept_ok || $group->accept_not_all || $group->drop_not_all) { delete_all_rules($group->group, $gid); add_all_rules($group->group, $gid, true); } } else { if (!$group->accept_ok || !$group->drop_ok) { if ($group->drop_not_all || $group->accept_not_all || ($group->drop_ok && !$group->accept_ok)) delete_all_rules($group->group, $gid); add_all_rules($group->group, $gid, false); } } } }
if (!$group_data[0]->drop_all) { syslog(LOG_INFO, "Adding final rule to drop everything"); system("iptables -A OUTPUT -o eth0 -m owner --gid-owner 1000-65533 -j DROP"); }
$group_stats[0]->timemark = $new_timemark; file_put_contents($tmp_file, serialize($group_stats));
foreach ($stats as $gid => $stat) { if ($stat->just_blocked) { $group = $stat->group; $tcp_rate = $stat->tcp_rate; $udp_rate = $stat->udp_rate; $icmp_rate = $stat->icmp_rate; $smtp_rate = $stat->smtp_rate; exec("lsof -i -n | grep ".$group, $run);
$message = " Hello. I've noticed and blocked an abnormal traffic generated by group $group (gid:$gid) at $hostname:
tcp_rate = $tcp_rate pps udp_rate = $udp_rate pps icmp_rate = $icmp_rate pps smtp_rate = $smtp_rate pps ";
if (isset($run) && count($run) > 0) { $message .= " Running processes by $group: ============================ ".implode("\n", $run)." ============================ "; }
$message .= "Please check!\n\n";
$subject = "[warn] Network activity of $group@$hostname"; exec("killall -9 -u ".$group.""); exec("/usr/local/ispmgr/sbin/mgrctl user.disable elid=".$group.""); exec("/usr/local/ispmgr/sbin/mgrctl restart"); mail("nucleus@hvosting.ua", $subject, $message, "From: no-reply@hvosting.ua"); mail("support@hvosting.ua", $subject, $message, "From: no-reply@hvosting.ua"); $fp = fsockopen("tcp://".$host, $port, $errno, $errstr); if (!$fp) { echo "ERROR: $errno - $errstr<br />\n"; } else { fwrite($fp, "\n".$message); fclose($fp); } } }
function mysql_go($query) { $group_data = mysql_query($query); if (!$group_data) { syslog(LOG_INFO, "Mysql query error: ".mysql_error()); exit(-3); } return $group_data; }
function bool2string($a) { return ($a) ? "true" : "false"; }
$dbcnx = @mysql_connect($server, $user, $pass); if (!$dbcnx) { syslog(LOG_ERR, "Mysql connection error: ".mysql_error()); exit(-1); }
if (!@mysql_select_db($db, $dbcnx)) { syslog(LOG_ERR, "Mysql error: ".mysql_error()); exit(-2); }
$res = mysql_go("select server_id from servers where server_name='".$hostname."' limit 1"); $row = mysql_fetch_row($res); $server_id = $row[0]; if ($server_id == 0) { $to = 'nucleus@hvosting.ua'; $subject = 'adding request'; $message = "Please add server to the list, its hostname: ".$hostname."\n"; $headers = "From: systemdb@hvosting.ua"."\r\n"; mail($to, $subject, $message, $headers); syslog(LOG_ERR, "Error: please add server $hostname to the database!!!"); exit(-4); } else syslog(LOG_INFO, "Obtained value server_id=".$server_id);
//print_r($group_data); ?>
|