Differences between version 2 and predecessor to the previous major change of StopGrind.
Other diffs: Previous Revision, Previous Author
Newer page: | version 2 | Last edited on Wednesday, 3 September 2008 7:31:49 | by CyberLeo | Revert |
Older page: | version 1 | Last edited on Sunday, 31 August 2008 23:03:16 | by CyberLeo | Revert |
@@ -22,8 +22,16 @@
$line = call_user_func_array('sprintf', $args);
syslog(LOG_NOTICE, $line);
//printf("\n");
//printf("%s: %s\n", strftime("%Y-%m-%d:%H:%M:%S"), $line);
+}
+
+function loadState() {
+ logit("fixme:STUB:loadState()");
+}
+
+function saveState($state) {
+ logit("fixme:STUB:saveState()");
}
function authorizedHost($ip) {
global $ignore_hosts, $ignore_hosts_cache, $ignore_hosts_cache_timeout;
@@ -50,13 +58,21 @@
}
}
}
return FALSE;
+}
+
+function banBadHost($ip) {
+ // Magical Gnomes
+ global $bad_hosts;
+ logit("bad host banned: %s", $ip);
+ $cmd = sprintf("/root/siteban/autoban %s", escapeshellarg($ip));
+ //exec($cmd);
+ unset($bad_hosts[$ip]);
}
function badHost($ip, $line) {
global $bad_hosts, $bad_hosts_timeout, $bad_hosts_limit;
- //printf("==> badHost(%s)\n", $ip);
// Expire
foreach($bad_hosts as $key => $value)
if ($value['expires'] < time())
unset($bad_hosts[$key]);
@@ -67,25 +83,15 @@
$bad_hosts[$ip]['expires'] = time() + $bad_hosts_timeout;
$bad_hosts[$ip]['evidence'][] = $line;
if (count($bad_hosts[$ip]['evidence']) > $bad_hosts_limit)
banBadHost($ip);
-}
-
-function banBadHost($ip) {
- // Magical Gnomes
- global $bad_hosts;
- logit("Banning %s for grinding.", $ip);
- $cmd = sprintf("/root/siteban/autoban %s", escapeshellarg($ip));
- exec($cmd);
- unset($bad_hosts[$ip]);
}
function matchLine($pattern, $key, $line) {
global $trig_vars;
$regs = Array();
if ($res = preg_match($pattern, $line, $regs)) {
$out = Array();
- //printf("[%s]=> (%s) %s \n", $key, $res, $line);
foreach($trig_vars[$key] as $index => $name) {
if ($name) $out[$name] = $regs[$index];
}
@@ -106,9 +112,13 @@
fgets($source, 4096);
return $source;
}
-tailLog
($log
);
+function handle
($line) {
+ global $trig_pats;
+ $line = trim($line);
+ array_walk($trig_pats, "matchLine", $line
);
+}
$trig_pats = Array(
"/Failed ([^ ]+) for( invalid user){0,1} ([^ ]+) from ([^ ]+) port ([^ ]+)/",
"/Invalid user ([^ ]+) from ([^ ]+)/",
@@ -130,8 +140,46 @@
);
logit("Starting scanner");
+$state = loadState();
+
+$lines = 0;
+$running = TRUE;
+$buf = "";
+while ($running) {
+ $read = Array(STDIN);
+ $write = NULL;
+ $except = NULL;
+ $timeout = 60;
+ if ($res = stream_select($read, $write, $except, $timeout)) {
+ // Handle incoming data
+ if (0 == strlen($tmp = fread(STDIN, 4096))) {
+ // EOF
+ logit("No more input. Night night.");
+ $running = FALSE;
+ } else {
+ $buf.= $tmp;
+ while (FALSE !== ($pt = strpos($buf, "\n"))) {
+ $lines++;
+ $line = substr($buf, 0, $pt);
+ $buf = substr($buf, $pt + 1, strlen($buf));
+ handle($line);
+ }
+ }
+ } else {
+ // Timeout or interrupt. Die.
+ logit("Timeout. Night night.");
+ $running = FALSE;
+ }
+}
+
+logit("Processed %u lines", $lines);
+saveState($state);
+
+return 0;
+
+tailLog($log);
while ($line = fgets($source, 16384)) {
$line = trim($line);
// Check for newsyslog message
if (preg_match('/newsyslog[^:]+: logfile turned over/', $line)) {
@@ -143,7 +191,8 @@
}
array_walk($trig_pats, "matchLine", $line);
}
+pclose($source);
?>
</verbatim>
version 2
#!/usr/bin/env php <?php $log = '/var/log/auth.log'; $ignore_hosts = Array( "yiff.myftp.org" ); $ignore_hosts_cache = Array(); // ip => Array('ip' => <ip>, 'name' => <name>, 'expires' => <time>) $ignore_hosts_cache_timeout = 60; $bad_hosts = Array(); // ip => Array('expires' => <time>, 'evidence' => Array(<evidence>)) $bad_hosts_timeout = 60; $bad_hosts_limit = 10; openlog('StopGrind', LOG_PID|LOG_PERROR, LOG_AUTHPRIV); function logit() { //printf("%s: ", strftime("%Y-%m-%d:%H:%M:%S")); $args = func_get_args(); $line = call_user_func_array('sprintf', $args); syslog(LOG_NOTICE, $line); //printf("\n"); //printf("%s: %s\n", strftime("%Y-%m-%d:%H:%M:%S"), $line); } function loadState() { logit("fixme:STUB:loadState()"); } function saveState($state) { logit("fixme:STUB:saveState()"); } function authorizedHost($ip) { global $ignore_hosts, $ignore_hosts_cache, $ignore_hosts_cache_timeout; // Expire cache entries $now = time(); foreach ($ignore_hosts_cache as $key => $ignore_host) if ($ignore_host['expires'] < $now) unset($ignore_hosts_cache[$key]); // Now look up a cached entry if (isset($ignore_hosts_cache[$ip])) return TRUE; // Now look up the ignore_hosts one by one until we get a match foreach ($ignore_hosts as $host) { $record = dns_get_record($host, DNS_ANY); foreach($record as $entry) { if ($entry['ip']) { $ignore_hosts_cache[] = Array( 'ip' => $entry['ip'], 'name' => $entry['host'], 'expires' => time() + $entry['ttl'] ); if ($entry['ip'] == $ip) return TRUE; } } } return FALSE; } function banBadHost($ip) { // Magical Gnomes global $bad_hosts; logit("bad host banned: %s", $ip); $cmd = sprintf("/root/siteban/autoban %s", escapeshellarg($ip)); //exec($cmd); unset($bad_hosts[$ip]); } function badHost($ip, $line) { global $bad_hosts, $bad_hosts_timeout, $bad_hosts_limit; // Expire foreach($bad_hosts as $key => $value) if ($value['expires'] < time()) unset($bad_hosts[$key]); // Check if (!is_array($bad_hosts[$ip])) $bad_hosts[$ip] = Array('evidence' => Array()); $bad_hosts[$ip]['expires'] = time() + $bad_hosts_timeout; $bad_hosts[$ip]['evidence'][] = $line; if (count($bad_hosts[$ip]['evidence']) > $bad_hosts_limit) banBadHost($ip); } function matchLine($pattern, $key, $line) { global $trig_vars; $regs = Array(); if ($res = preg_match($pattern, $line, $regs)) { $out = Array(); foreach($trig_vars[$key] as $index => $name) { if ($name) $out[$name] = $regs[$index]; } if (!authorizedHost($out['ip'])) { badHost($out['ip'], $line); } } } function tailLog($log) { global $source; if (is_resource($source)) pclose($source); $cmd = sprintf("tail -fn 1024 %s", escapeshellarg($log)); //logit("%s", $cmd); $source = popen($cmd, "r"); // Ignore the first line, in case it's a newsyslog message. fgets($source, 4096); return $source; } function handle($line) { global $trig_pats; $line = trim($line); array_walk($trig_pats, "matchLine", $line); } $trig_pats = Array( "/Failed ([^ ]+) for( invalid user){0,1} ([^ ]+) from ([^ ]+) port ([^ ]+)/", "/Invalid user ([^ ]+) from ([^ ]+)/", ); $trig_vars = Array( Array( "", "method", "", "username", "ip", "port" ), Array( "", "username", "ip" ) ); logit("Starting scanner"); $state = loadState(); $lines = 0; $running = TRUE; $buf = ""; while ($running) { $read = Array(STDIN); $write = NULL; $except = NULL; $timeout = 60; if ($res = stream_select($read, $write, $except, $timeout)) { // Handle incoming data if (0 == strlen($tmp = fread(STDIN, 4096))) { // EOF logit("No more input. Night night."); $running = FALSE; } else { $buf.= $tmp; while (FALSE !== ($pt = strpos($buf, "\n"))) { $lines++; $line = substr($buf, 0, $pt); $buf = substr($buf, $pt + 1, strlen($buf)); handle($line); } } } else { // Timeout or interrupt. Die. logit("Timeout. Night night."); $running = FALSE; } } logit("Processed %u lines", $lines); saveState($state); return 0; tailLog($log); while ($line = fgets($source, 16384)) { $line = trim($line); // Check for newsyslog message if (preg_match('/newsyslog[^:]+: logfile turned over/', $line)) { //logit($line); logit("Reloading logfile\n"); pclose($source); die(); tailLog($log); } array_walk($trig_pats, "matchLine", $line); } pclose($source); ?>