Pfsense: Difference between revisions

From RARForge
Jump to navigation Jump to search
No edit summary
Line 22: Line 22:


<source lang=php>
<source lang=php>
#!/usr/local/bin/php -f
#!/usr/local/bin/php -f
<?php
  <?php
 
require_once("functions.inc");
require_once("functions.inc");
require_once("config.inc");
require_once("config.inc");
require_once("notices.inc");
require_once("notices.inc");
 
 
/* Rob Reed
/* Rob Reed
  *
  *
Line 38: Line 39:
  *
  *
  */
  */
 
 
define(DEBUG, 0); // ghetto debugging... not really useful
define(DEBUG, 0); // ghetto debugging... not really useful
 
// get snort alert logs
// get snort alert logs
$alert_logs = GetLogs();
$alert_logs = GetLogs();
 
// date stuff
// date stuff
$log_date = `date "+%m/%d/%y"`;
$log_date = `date "+%m/%d/%y"`;
$log_date = preg_replace( "/\r|\n/", "", $log_date );
$log_date = preg_replace( "/\r|\n/", "", $log_date );
$today = date("F j, Y H:i:s");
$today = date("F j, Y H:i:s");
 
// sadly th built in pfsense notification do not allow for a custom subject.. maybe later
// sadly th built in pfsense notification do not allow for a custom subject.. maybe later
$subject = "Snort Autoblock: $today";
$subject = "Snort Autoblock: $today";
 
// status file of current blocks
// status file of current blocks
$statusfile = '/tmp/blocked.status';
$statusfile = '/tmp/blocked.status';
 
// read in current blocks
// read in current blocks
if (file_exists($statusfile) && filesize($statusfile) > 0) {
if (file_exists($statusfile) && filesize($statusfile) > 0) {
Line 64: Line 65:
$is_blocked = array();
$is_blocked = array();
$is_blocked = explode("\n",$contents);
$is_blocked = explode("\n",$contents);
 
// Liste currently blocked IP's from snort - from the pf table (snort2c)
// Liste currently blocked IP's from snort - from the pf table (snort2c)
$out = shell_exec("/sbin/pfctl -t snort2c -T show | sed -e 's/^[[:space:]]*//'");
$out = shell_exec("/sbin/pfctl -t snort2c -T show | sed -e 's/^[[:space:]]*//'");
$ips = explode("\n",$out);     
$ips = explode("\n",$out);     
 
 
$message_body;
$message_body;
 
// notify on unblocked
// notify on unblocked
foreach ($is_blocked as $ib) {
foreach ($is_blocked as $ib) {
   if (!in_array($ib, $ips)) {
   if (!in_array($ib, $ips)) {
     $message_body .= " Unblocked: $ib\n";
     $message_body .= " Unblocked: $ib\n";
    // log to syslog
    $log_cmd = "echo \"$message_body\" | logger -P local0 -t snort2c";
    shell_exec($log_cmd);
   }
   }
}
}
 
// iterate through IP blocks
// iterate through IP blocks
if (is_array($ips)) {         
if (is_array($ips)) {         
 
   $fp = fopen($statusfile, 'w');
   $fp = fopen($statusfile, 'w');
 
   foreach ($ips as $ip) {
   foreach ($ips as $ip) {
     $ip= ltrim(rtrim($ip));
     $ip= ltrim(rtrim($ip));
Line 92: Line 96:
   }
   }
   fclose($fp);
   fclose($fp);
 
   // Notify if we had any results
   // Notify if we had any results
   if (!empty($message_body)) {
   if (!empty($message_body)) {
Line 100: Line 104:
   }
   }
}
}
 
/************* FUNCTIONS **************************/
/************* FUNCTIONS **************************/
 
function CheckIP($ip,$fp) {
function CheckIP($ip,$fp) {
   global $is_blocked;
   global $is_blocked;
   fwrite($fp, $ip . "\n");
   fwrite($fp, $ip . "\n");
 
   // debug mode - send notifies even if old
   // debug mode - send notifies even if old
   if (DEBUG) {    $body = NotifyNewBlock($ip); }  
   if (DEBUG) {    $body = NotifyNewBlock($ip); }  
 
   else {
   else {
     if (is_array($is_blocked)) {
     if (is_array($is_blocked)) {
       if (!in_array($ip,$is_blocked)) {
       if (!in_array($ip,$is_blocked)) {
// not in current block list - obtain IP info - whois/alert logs
        // not in current block list - obtain IP info - whois/alert logs
$body = NotifyNewBlock($ip,$body);
        $body = NotifyNewBlock($ip,$body);
       }
       }
     }
     }
Line 120: Line 124:
   return $body;
   return $body;
}
}
 
 
// generate the data for the notification - whois info, alert log info, etc..
// generate the data for the notification - whois info, alert log info, etc..
function NotifyNewBlock($ip) {
function NotifyNewBlock($ip) {
   global $alert_logs,$log_date;
   global $alert_logs,$log_date;
 
   // reverse dns for ip
   // reverse dns for ip
   $host = gethostbyaddr($ip);
   $host = gethostbyaddr($ip);
   if ($host != $ip) {  $inc_host = "[$host]"; }
   if ($host != $ip) {  $inc_host = "[$host]"; }
 
   // start of body
   // start of body
   $body = "\n* Blocked: $ip [$inc_host]\n";
   $body = "\n* Blocked: $ip [$inc_host]\n";
 
   // try to get whois info
   // try to get whois info
   if ( $whois = get_whois($ip) ) {    $body .= $whois; }
   if ( $whois = get_whois($ip) ) {    $body .= $whois; }
 
   // iterate through snort logs to find reason for block
   // iterate through snort logs to find reason for block
   foreach ($alert_logs as $log) {
   foreach ($alert_logs as $log) {
     $cmd = 'grep ' . "$ip $log | grep $log_date " .  
     $cmd = 'grep ' . "$ip $log | grep $log_date " .  
       ' | awk -F, \'{ print "SID="$2":"$3":"$4" PRI="$13" CLASS="$12" DESC="$5" SRC_IP="$7" SRC_PORT="$8" DST_IP="$9" DST_PORT="$10" PROTO="$6}\' ' .
       ' | awk -F, \'{ print "SID="$2":"$3":"$4" PRI="$13" CLASS="$12" DESC="$5" SRC_IP="$7" SRC_PORT="$8" DST_IP="$9" DST_PORT="$10" PROTO="$6}\' ' .
       ' | sort | uniq -c';
       ' | sort | uniq ';
   
     if (DEBUG) { print "\tDEBUG: " . $cmd . "\n\n";}
     if (DEBUG) { print "\tDEBUG: " . $cmd . "\n\n";}
   
     $body .= "\n  LOGS for $ip $log_date\n";;
     $body .= "\n  LOGS for $ip $log_date\n";;
     $body .= shell_exec ($cmd);
     $result .= shell_exec ($cmd);
    $tmp_log = explode("\n",$result);
    $log_body = $tmp_log[0];  // only get on for logger - last one
    $body .= $result;
     $body .= "\n";
     $body .= "\n";
   }
   }
    
 
   // log to syslog
  $log_body = str_replace('"', "'", $log_body );
  $log_cmd = "echo \"Blocked=$ip $log_body\" | logger -P local0 -t snort2c";
  shell_exec($log_cmd);
   return $body;
   return $body;
}
}
 
 
// whois function - work in progress
// whois function - work in progress
function get_whois($ip) {
function get_whois($ip) {
Line 161: Line 173:
   $whois_data = get_whois_from_server($whois_server , $ip);
   $whois_data = get_whois_from_server($whois_server , $ip);
   $a = explode("\n",$whois_data);
   $a = explode("\n",$whois_data);
 
   /* wanted info  
   /* wanted info  
     NetRange:      50.16.0.0 - 50.19.255.255
     NetRange:      50.16.0.0 - 50.19.255.255
Line 171: Line 183:
     NetType:        Direct Assignment
     NetType:        Direct Assignment
     Ref:            http://whois.arin.net/rest/net/NET-50-16-0-0-1
     Ref:            http://whois.arin.net/rest/net/NET-50-16-0-0-1
   
     OrgName:        Amazon.com, Inc.
     OrgName:        Amazon.com, Inc.
     OrgId:          AMAZO-4
     OrgId:          AMAZO-4
Line 180: Line 192:
     PostalCode:    98144
     PostalCode:    98144
   */
   */
 
   $wanted = array('NetRange',
   $wanted = array('NetRange',
  'CIDR',
                  'CIDR',
  'OriginAS',
                  'OriginAS',
  'NetName',
                  'NetName',
  'NetHandle',
                  'NetHandle',
  'Parent',
                  'Parent',
  'NetType',
                  'NetType',
  'Ref',
                  'Ref',
  'OrgName',
                  'OrgName',
  'OrgId',
                  'OrgId',
  'Address',
                  'Address',
  'Address',
                  'Address',
  'City',
                  'City',
  'StateProv',
                  'StateProv',
  'PostalCode',
                  'PostalCode',
  );
                  );
 
 
 
   $whois .= "  ------------------------ WHOIS -----------------------------\n";
   $whois .= "  ------------------------ WHOIS -----------------------------\n";
   foreach ($wanted as $w) {
   foreach ($wanted as $w) {
Line 210: Line 222:
   return $whois;
   return $whois;
}
}
 
 
// whois server loookup  
// whois server loookup  
function get_whois_from_server($server , $ip) {
function get_whois_from_server($server , $ip) {
Line 224: Line 236:
   }
   }
}
}
 
 
 
// lists all sensors - return array of sensor alert files
// lists all sensors - return array of sensor alert files
function GetLogs() {
function GetLogs() {
Line 235: Line 247:
     foreach ($psa as $ps) {
     foreach ($psa as $ps) {
       if (preg_match( "/\s-l\s+([^\s]+)/i" , $ps, $m)) {
       if (preg_match( "/\s-l\s+([^\s]+)/i" , $ps, $m)) {
array_push ($alert_logs,$m[1] . "/alert");
        array_push ($alert_logs,$m[1] . "/alert");
       }
       }
     }
     }
   }
   }
 
   if (!empty($alert_logs)) {
   if (!empty($alert_logs)) {
     return $alert_logs;
     return $alert_logs;
Line 250: Line 262:
   }
   }
}
}
 
 
?>
?>
</source>
</source>

Revision as of 23:35, 1 May 2013

  • just some things to remember...


Install Emacs

<source> pkg_add -r emacs-nox11 </source>



Snort Auto Block Email

  • SNORT does not have any way to notify (as I know of) when it blocks/unblocks an IP automatically. Below is a PHP script that will.
  • It uses the default notification list from pfsense (i.e. system / advanced / notifications )
Install
  • copy code below into: /usr/local/bin/snort_autoblock_notify.php
  • chmod +x /usr/local/bin/snort_autoblock_notify.php
  • Install CRON from the GUI Package Manger
  • setup CRON to execute /usr/local/bin/snort_autoblock_notify.php every 5 minutes as root

<source lang=php>

  1. !/usr/local/bin/php -f
  <?php

require_once("functions.inc"); require_once("config.inc"); require_once("notices.inc");


/* Rob Reed

*
*  Created: 2013-05-01
* Modified: 2013-05-01
*
* Notify when snort autoblocks - run this on a cron. Every 5 minutes should be fine. 
*
*/


define(DEBUG, 0); // ghetto debugging... not really useful

// get snort alert logs $alert_logs = GetLogs();

// date stuff $log_date = `date "+%m/%d/%y"`; $log_date = preg_replace( "/\r|\n/", "", $log_date ); $today = date("F j, Y H:i:s");

// sadly th built in pfsense notification do not allow for a custom subject.. maybe later $subject = "Snort Autoblock: $today";

// status file of current blocks $statusfile = '/tmp/blocked.status';

// read in current blocks if (file_exists($statusfile) && filesize($statusfile) > 0) {

 $read = fopen($statusfile, "r");
 $contents = fread($read, filesize($statusfile));
 fclose($read);

} $is_blocked = array(); $is_blocked = explode("\n",$contents);

// Liste currently blocked IP's from snort - from the pf table (snort2c) $out = shell_exec("/sbin/pfctl -t snort2c -T show | sed -e 's/^space:*//'"); $ips = explode("\n",$out);


$message_body;

// notify on unblocked foreach ($is_blocked as $ib) {

 if (!in_array($ib, $ips)) {
   $message_body .= " Unblocked: $ib\n";
   // log to syslog
   $log_cmd = "echo \"$message_body\" | logger -P local0 -t snort2c";
   shell_exec($log_cmd);
 }

}

// iterate through IP blocks if (is_array($ips)) {

 $fp = fopen($statusfile, 'w');

 foreach ($ips as $ip) {
   $ip= ltrim(rtrim($ip));
   if (preg_match("/\d+\./",$ip)) {
     // CheckIP - return info about IP if this is not currently blocked
     $message_body = CheckIP($ip,$fp,$message_body);
   } 
 }
 fclose($fp);

 // Notify if we had any results
 if (!empty($message_body)) {
   if (DEBUG) {     print $message_body . "\n";   }
   notify_via_smtp($message_body);
   notify_via_growl($message_body);
 }

}

/************* FUNCTIONS **************************/

function CheckIP($ip,$fp) {

 global $is_blocked;
 fwrite($fp, $ip . "\n");

 // debug mode - send notifies even if old
 if (DEBUG) {    $body = NotifyNewBlock($ip); } 

 else {
   if (is_array($is_blocked)) {
     if (!in_array($ip,$is_blocked)) {
       // not in current block list - obtain IP info - whois/alert logs
       $body = NotifyNewBlock($ip,$body);
     }
   }
 }
 return $body;

}


// generate the data for the notification - whois info, alert log info, etc.. function NotifyNewBlock($ip) {

 global $alert_logs,$log_date;

 // reverse dns for ip
 $host = gethostbyaddr($ip);
 if ($host != $ip) {   $inc_host = "[$host]"; }

 // start of body
 $body = "\n* Blocked: $ip [$inc_host]\n";

 // try to get whois info
 if ( $whois = get_whois($ip) ) {    $body .= $whois; }

 // iterate through snort logs to find reason for block
 foreach ($alert_logs as $log) {
   $cmd = 'grep ' . "$ip $log | grep $log_date " . 
     ' | awk -F, \'{ print "SID="$2":"$3":"$4" PRI="$13" CLASS="$12" DESC="$5" SRC_IP="$7" SRC_PORT="$8" DST_IP="$9" DST_PORT="$10" PROTO="$6}\' ' .
     ' | sort | uniq ';

   if (DEBUG) { print "\tDEBUG: " . $cmd . "\n\n";}

   $body .= "\n   LOGS for $ip $log_date\n";;
   $result .= shell_exec ($cmd);
   $tmp_log = explode("\n",$result);
   $log_body = $tmp_log[0];  // only get on for logger - last one
   $body .= $result;
   $body .= "\n";
 }
 // log to syslog
 $log_body = str_replace('"', "'", $log_body );
 $log_cmd = "echo \"Blocked=$ip $log_body\" | logger -P local0 -t snort2c";
 shell_exec($log_cmd);

 return $body;

}


// whois function - work in progress function get_whois($ip) {

 $w = get_whois_from_server('whois.iana.org' , $ip);
 preg_match('/whois:\s+([\w\.\-]+)/' , $w , $data);
 $whois_server = $data[1];
 //now get actual whois data
 $whois_data = get_whois_from_server($whois_server , $ip);
 $a = explode("\n",$whois_data);

 /* wanted info 
   NetRange:       50.16.0.0 - 50.19.255.255
   CIDR:           50.16.0.0/14
   OriginAS:       
   NetName:        AMAZON-EC2-8
   NetHandle:      NET-50-16-0-0-1
   Parent:         NET-50-0-0-0-0
   NetType:        Direct Assignment
   Ref:            http://whois.arin.net/rest/net/NET-50-16-0-0-1

   OrgName:        Amazon.com, Inc.
   OrgId:          AMAZO-4
   Address:        Amazon Web Services, Elastic Compute Cloud, EC2
   Address:        1200 12th Avenue South
   City:           Seattle
   StateProv:      WA
   PostalCode:     98144
 */

 $wanted = array('NetRange',
                 'CIDR',
                 'OriginAS',
                 'NetName',
                 'NetHandle',
                 'Parent',
                 'NetType',
                 'Ref',
                 'OrgName',
                 'OrgId',
                 'Address',
                 'Address',
                 'City',
                 'StateProv',
                 'PostalCode',
                 );



 $whois .= "  ------------------------ WHOIS -----------------------------\n";
 foreach ($wanted as $w) {
   $p = preg_grep( "/^$w/i" , $a );
   foreach ($p as $l) {
     $whois .= "\t" . $l . "\n";
   }
 } 
 $whois .= "  ---------------------- END WHOIS ---------------------------\n";
 return $whois;

}


// whois server loookup function get_whois_from_server($server , $ip) {

 $fp = fsockopen("tcp://$server", 43, $errno, $errstr);
 if (!$fp) {
   echo "ERROR: $errno - $errstr
\n"; } else { fwrite($fp, "$ip\n"); while (!feof($fp)) $result .= fread($fp,32000); fclose($fp); return $result; }

}


// lists all sensors - return array of sensor alert files function GetLogs() {

 $alert_logs = array();
 $ps_logs = `ps auxw | grep snort | grep "\-l " | grep -v grep`;
 $psa = explode("\n",$ps_logs);
 if (!empty($psa)) {
   foreach ($psa as $ps) {
     if (preg_match( "/\s-l\s+([^\s]+)/i" , $ps, $m)) {
       array_push ($alert_logs,$m[1] . "/alert");
     }
   }
 }

 if (!empty($alert_logs)) {
   return $alert_logs;
 } else {
   $notificationmsg = "failed to locate alert logs - snort running?\n";
   print $notificationmsg;
   notify_via_smtp($notificationmsg);
   notify_via_growl($notificationmsg);
   exit;
 }

}


?> </source>