Note: You are viewing an old version of this page. View the current version.

Differences between version 2 and previous revision of StopGrind.

Other diffs: Previous Major 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);

?>