%%(php) #!/usr/bin/php \n"; } } function GetRules($filename) { global $Debug, $Events, $LongestHitTime; $blocks=0; $lines = file($filename); foreach ($lines as $num => $line) { $line=CleanLine($line); $x=strpos($line, "=") - 1; $cmd=trim(substr($line, 0, $x)); $val=trim(substr($line, $x)); switch ($val) { case "{": $blocks++; $Events['Name'][$blocks] = $cmd; break; case "}": // End of block break; default: $val=strtolower(trim(substr($val, strpos($val, "=") + 1))); switch ($cmd) { case "domain": $q = 0; while (strpos($val, "|")) { $x=strpos($val, "|"); $Events['Domain'][$blocks][$q] = substr($val, 0, $x); $val=substr($val, $x+1); $q++; } $Events['Domain'][$blocks][$q] = $val; break; case "hits": if (! is_numeric($val)) $val = 0; $Events['Hits'][$blocks] = $val; break; case "hittime": $Events['HitTime'][$blocks] = $val; $chkTime = adjTime($val); if ($LongestHitTime < $chkTime) { $LongestHitTime = $chkTime; } break; case "info": $Events['Info'][$blocks] = $val; break; case "time": $Events['Time'][$blocks] = $val; break; case "match": $q = 0; while (strpos($val, "|")) { $x=strpos($val, "|"); $Events['Match'][$blocks][$q] = substr($val, 0, $x); $val=substr($val, $x+1); $q++; } $Events['Match'][$blocks][$q] = $val; break; case "source": $Events['Source'][$blocks] = $val; break; } break; } } } function CleanLine($line) { // Clean up input and remove comments $line=trim($line); $x=strpos($line, "#"); if (! is_numeric($x)) $x=strlen($line); $line=substr($line, 0, $x); $x=strpos($line, "//"); if (! is_numeric($x)) $x=strlen($line); $line=substr($line, 0, $x); return $line; } function UpdateIP($eIP, $eHits, $eTime, $eHitTime, $eName) { global $Blocked, $Debug, $DIR; global $IPTABLES, $Interface; $fwTest = exec("$IPTABLES -nL autoblock | grep \" $eIP \""); $whitelist = exec("grep ^$eIP $DIR/whitelist"); $NewDate = date("YmdHis", strtotime("+$eTime")); if ($eHitTime < 0) $eHitTime = 0; $HitDate = date("YmdHis", strtotime("+$eHitTime")); if ($whitelist) { logger("$eIP is whitelisted"); } elseif ($eHits < 1) { // These are immediate blocks $Blocked[$eIP]['Time'][$Blocked[$eIP]['Time'].count] = time(); if ($fwTest == "") { // Adding new entry to iptables // exec("$IPTABLES -A autoblock -i $Interface -s $eIP -j autoblock_drop > /dev/null 2>&1"); addIP($eIP); Broadcast("+$eIP:$NewDate"); if ($Debug & 2) { if ($eHits == -1) logger("Quick-block $eIP until $NewDate"); elseif ($eHits == -2) logger("Broadcast-block $eIP until $eTime"); else logger("Blocking $eIP until $NewDate (Rule=$eName)"); } } if ($eHits == -2) { $Blocked[$eIP]['Expire'] = $eTime; $Blocked[$eIP]['Count'] = -2; } else { $Blocked[$eIP]['Expire'] = $NewDate; $Blocked[$eIP]['Count'] = -1; } } else { // These events require multiple hits before blocking the IP address $Blocked[$eIP]['Count']++; $Blocked[$eIP][$Blocked[$eIP]['Time'].count] = time(); //echo " $eIP (x".$Blocked[$eIP]['Count'].")\n"; if ($Blocked[$eIP]['Count'] >= $eHits) { if ($fwTest == "") { // Adding new entry to iptables // exec("$IPTABLES -A autoblock -i $Interface -s $eIP -j autoblock_drop > /dev/null 2>&1"); addIP($eIP); Broadcast("+$eIP:$NewDate"); if ($Debug & 2) logger("Blocking $eIP (" . $Blocked[$eIP]['Count'] . "/$eHits) until $NewDate (Rule=$eName)"); } $Blocked[$eIP]['Expire'] = $NewDate; $Blocked[$eIP]['Count'] = -1; } else { $Blocked[$eIP]['Expire'] = $HitDate; if ($Debug & 8) logger("Updating $eIP (" . $Blocked[$eIP]['Count'] . "/$eHits) ($HitDate)"); } } } function addIP($IP) { global $IPTABLES, $Interface; exec("$IPTABLES -A autoblock -i $Interface -s $IP -j autoblock_drop > /dev/null 2>&1"); } function logger($info) { syslog(LOG_NOTICE, $info); } //----------------------------------------// //Read config files and existing blocklist// //----------------------------------------// $RulesDate = filemtime($RULES); GetRules("$RULES"); exec("touch $Blocklist"); // Set up IPTABLES //if (exec("$IPTABLES -N autoblock 2> /dev/null; echo $?") == "0") { exec("$IPTABLES -F autoblock 2> /dev/null"); exec("$IPTABLES -X autoblock 2> /dev/null"); exec("$IPTABLES -N autoblock 2> /dev/null"); exec("$IPTABLES -F autoblock_drop 2> /dev/null"); exec("$IPTABLES -X autoblock_drop 2> /dev/null"); exec("$IPTABLES -N autoblock_drop 2> /dev/null"); exec("$IPTABLES -A autoblock_drop -j DROP"); if (! exec("$IPTABLES -nL INPUT | grep autoblock")) exec("$IPTABLES -I INPUT -j autoblock"); $lines = file($Blocklist); foreach ($lines as $num => $line) { $line=CleanLine($line); $x=strpos($line, " "); if (! is_numeric($x)) $x=strpos($line, " "); if (is_numeric($x)) { $IP = trim(substr($line, 0, $x)); $Blocked[$IP]['Expire'] = trim(substr($line, $x)); $Blocked[$IP]['Count'] = -1; exec("$IPTABLES -A autoblock -i $Interface -s $IP -j autoblock_drop > /dev/null 2>&1"); if ($Debug & 32) logger("Blocklist: $IP (" . $Blocked[$IP]['Expire'] . ")"); } } //----------------------------------------// // Begin monitoring log files for events // //----------------------------------------// if ($Debug & 1) logger("Autoblock initialized..."); // Open filter log and jump backwards $linecount lines $fp = fopen($Filter, "r"); $fpRef=array($fp); fseek ($fp, 0, SEEK_END); $pos = -2; $lc = 1; $t=" "; $linecount = 2; while ($t != "\n" and $lc <= $linecount) { fseek ($fp, $pos, SEEK_END); $t = fgetc($fp); $pos = $pos - 1; if ($t == "\n" and $lc < $linecount) { fseek ($fp, $pos, SEEK_END); $t = fgetc($fp); $pos = $pos - 1; $lc++; } } $NextUpdate = date("YmdHis", strtotime("+$BlockUpdates seconds")); while ( True ) { fseek ($fp, ftell($fp), 0); if (stream_select($fpRef, $w=null, $e=null, 0)) $line = fgets($fp, 1024); else $line=""; if ($line == "") { // // pause for a moment then reset the connection and try again // $Now = date("YmdHis"); foreach ($Blocked as $IP => $test) { if ($Blocked[$IP]['Expire'] < $Now) { $log = False; if (($Debug & 4) && ($Blocked[$IP]['Count'] < 0)) $log=True; if (($Debug & 16) && ($Blocked[$IP]['Count'] >= 0)) $log=True; if ($log == True) logger("$IP expired at " . $Blocked[$IP]['Expire']); exec("$IPTABLES -D autoblock -i $Interface -s $IP -j autoblock_drop > /dev/null 2>&1"); if ($Blocked[$IP]['Count'] == -1) Broadcast("-$IP"); unset($Blocked[$IP]['Count']); unset($Blocked[$IP]['Expire']); unset($Blocked[$IP]['Time']); unset($Blocked[$IP]); } if (is_array($Blocked[$IP]['Time'])) { foreach ($Blocked[$IP]['Time'] as $HT => $test) { // if time of this hit is longer than $LongestHitTime, // remove it from the array echo "\$Blocked[$IP]['Time'][$test] = $HT\n"; //if (time()-$HT > $LongestHitTime) { unset $Blocked[$IP]['Time'][$HT]; } } } } if (date("YmdHis") > $NextUpdate) { if ($Debug & 128) logger("--- Updating Blocklist ---"); $wr = fopen($Blocklist, "w"); foreach ($Blocked as $IP => $test) { if ($Blocked[$IP]['Count'] < 0) { // Write update to file $padIP = substr("$IP ", 0, 15); fputs($wr, $padIP . " " . $Blocked[$IP]['Expire'] . "\n"); } } fclose($wr); $NextUpdate = date("YmdHis", strtotime("+$BlockUpdates seconds")); } else { // Nothing else to do clearstatcache(); $ChkDate = filemtime($RULES); if ($ChkDate != $RulesDate) { GetRules("$RULES"); $RulesDate = filemtime($RULES); if ($Debug & 1) logger("$RULES has been updated."); } // Check for broadcast messages if (@socket_recvfrom($socket, $msg, 256, 0, $sndIP, $sndPort)) { if ($localIP != $sndIP) { // logger("Broadcast Msg: $msg"); $cmd = substr($msg,0,1); $x = strpos($msg, ":"); $mIP = substr($msg, 1, $x-1); $mDate = substr($msg, $x+1); switch($cmd) { case "+": logger("+($sndIP) $mIP until $mDate"); exec("$IPTABLES -A autoblock -i $Interface -s $mIP -j autoblock_drop > /dev/null 2>&1"); break; case "-": logger("-($sndIP) $mIP"); exec("$IPTABLES -D autoblock -i $Interface -s $mIP -j autoblock_drop > /dev/null 2>&1"); break; } } } usleep(200000); } } else { // // got a new line of data to process // $lline=strtolower($line); //echo $line; for($x=1; $Events['Name'][$x]!=""; $x++) { // Test Match $test=0; $q=0; while ($test == 0) { //echo $Events['Match'][$x][$q]; if (! isset($Events['Match'][$x][$q])) $test = 1; elseif (! is_numeric(strpos($lline, $Events['Match'][$x][$q]))) $test = -1; $q++; } // End Match if ($test == 1) { //echo "::" . $Events['Name'][$x] . "\n"; $IP = substr($line, strpos($lline, $Events['Source'][$x]) + strlen($Events['Source'][$x])); $q = strpos($IP, "#"); if (is_numeric($q)) { $IP = substr($IP, 0, $q); } $IP = trim($IP); $q = strpos($IP, " "); if (is_numeric($q)) { $IP = substr($IP, 0, $q); } //echo " $IP\n"; if (strlen($IP) < 7) $IP=""; if ($IP != "") { UpdateIP($IP, $Events['Hits'][$x], $Events['Time'][$x], $Events['HitTime'][$x], $Events['Name'][$x]); if (isset($Events['Domain'][$x][0])) { $beg = strpos($lline, $Events['Domain'][$x][0]) + strlen($Events['Domain'][$x][0]); $end = strpos($lline, $Events['Domain'][$x][1], $beg); $Domain = substr($line, $beg, $end-$beg); $HitIP = "|$IP|"; $HitNum = 1; for($i=$qbLines; $i>0; $i=$i-1) { $j = $i - 1; $Tail['IP'][$i] = $Tail['IP'][$j]; $Tail['Domain'][$i] = $Tail['Domain'][$j]; if (($Domain == $Tail['Domain'][$i]) && ($Tail['IP'][$i] != "")) { $test = strpos($HitIP, $Tail['IP'][$i]); if ($test == "") { $HitIP = $HitIP . $Tail['IP'][$i] . "|"; $HitNum++; } } } $Tail['IP'][1] = $IP; $Tail['Domain'][1] = $Domain; if ($HitNum >= $qbUniq) { $HitIP = substr($HitIP, 1); $xIP=""; while (strlen($HitIP) > 1) { $end = strpos($HitIP, "|"); $xIP = substr($HitIP, 0, $end); $HitIP = substr($HitIP, $end + 1); UpdateIP($xIP, -1, $Events['Time'][$x], $Events['HitTime'][$x], $Events['Name'][$x]); } } } } break; } } } } ?> %% ---- CategoryDNSBlockList