Pfsense

From RARForge
Revision as of 18:43, 2 July 2015 by Robertr (talk | contribs) (→‎snort_autoblock_notify.php)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
  • just some things to remember...


Install Emacs

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

PHP Mode

<source> cat ~/.emacs

make sure the target directory is on your load-path

(add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp")) (require 'php-mode) </source> <source> cd ~/.emacs.d wget http://php-mode.svn.sourceforge.net/svnroot/php-mode/tags/php-mode-1.5.0/php-mode.el </source>

Snort Auto Block Email

this has been tested on pfsense 2.1-BETA1
  • 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 will notify email/growl -- using the default notification list from pfsense (i.e. system / advanced / notifications )
  • It will log to syslog snort2c on Blocked/Unblocked events
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=text>

   min: */5
  hour: *
  mday: *
 month: *
  wday: *
   who: root

command: /usr/local/bin/snort_autoblock_notify.php &> /dev/null </source>



snort_autoblock_notify.php

<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-06-18
*
*  Version: 0.0.6
*
* Notify when snort autoblocks - run this on a cron. Every 5 minutes should be fine. 
*
* .0.0.6 - added $exclude_country -- will not notify if country is in the list
* .0.0.5 - whois function will check Parent block if reassigned
*/


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

$exclude_country = array('CN','UA',);

// body header $header = ; $footer = __FILE__ . ' SNORT Auto Block Notifcation'; //$footer .= "\n-----------------------------------------------------------------------------------------------------------------------------------\n";

// 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",trim($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:*//'"); //$out = shell_exec("/sbin/pfctl -t snort2c -T show |"); $ips = explode("\n",trim($out));

$message_body;

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

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

}

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

 global $header; 
 $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
     if (DEBUG) {     print "Check Blocked IP: $ip \n";   }
     list ($action,$tmp_body,$country,$netname,$inc_host) = CheckIP($ip,$fp);
     if (in_array(strtoupper($country),$exclude_country)) {
          if (DEBUG) {     print "Skipping notify on $ip -- $country is in the exclude_country list\n";   }
          continue;
     }
     if ($action) {
       $format = "%-26s [%-2s] %-15.15s [%s] \n";
       $actions .= sprintf($format, $action,  $country, $netname, $inc_host);
       $message_body .= $tmp_body;
       if (DEBUG && !$message_body) {     print "  no message_body for $ip \n";   }
     }
   } 
 }
 fclose($fp);

 // Notify if we had any results
 if (!empty($message_body)) {

   $notify = $header;

   $notify .= "------- Actions -------\n\n";
   $notify .= $actions . "\n";
   $notify .= "-----------------------\n\n\n";
   $notify .= "------- Deatailed Info -------\n\n";
   $notify .= $message_body . "\n";
   $notify .= $footer;
   if (DEBUG) {     print $notify . "\n";   }
   notify_via_smtp($notify);
   notify_via_growl($notify);
 }

}

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

function CheckIP($ip,$fp) {

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

 // debug mode - send notifies even if old
 if (DEBUG) {    
    list ($action,$body,$country,$netname,$inc_host) = NotifyNewBlock($ip); 
    return array ($action,$body,$country,$netname,$inc_host);
 } 

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


}


// 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\n-----------------------------------------------------------------------------------------------------------------------------------\n";
 $action = "* Blocked: $ip";
 $body .= "\n$action [$inc_host]\n";



 // iterate through snort logs to find reason for block
 $body .= "\n  ------------------ LOGS for $ip $log_date -----------------------\n";
 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";}
   $result .= shell_exec ($cmd);
   if ($result) {
     $body .= "LogFile: $log\n\n";
     $tmp_log = explode("\n",trim($result));
     if ($tmp_log[0]) {
       $log_body = $tmp_log[0];  // only get on for logger - last one
     }
    $body .= $result;
   }

 }
$body .= "\n  ---------------- END LOGS for $ip $log_date ---------------------\n";


 // try to get whois info
if ( list ($whois,$country,$netname) = get_whois($ip) ) {    $body .= "\n" . $whois . "\n"; }

// log to syslog
if ($log_body) {
  $log_body = str_replace('"', "'", $log_body );
   $log_cmd = "echo \"Blocked=$ip $log_body\" | logger -P local0 -t snort2c";
 }
 shell_exec($log_cmd);

 return array ($action,$body,$country,$netname,$inc_host);

}


// 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);
 // if there is now Country info -- lets get the Parent Block info (hack - works for comcast.. not sure of others)
 if (!preg_match("/Country/",$whois_data) && preg_match("/NET-([\d\-]+)/",$whois_data, $matches) ) {
   $whois_old = $whois_data;
   $whois_data = get_whois_from_server($whois_server , $matches[0]);
 }


 $a = explode("\n",trim($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

   inetnum:        111.72.0.0 - 111.79.255.255
   netname:        CHINANET-JX
   descr:          CHINANET JIANGXI PROVINCE NETWORK
   descr:          China Telecom
   descr:          No.31,jingrong street
   descr:          Beijing 100032
   country:        CN
 */



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



 $whois .= "  ------------------------ WHOIS -----------------------------\n";
 $whois .= "  whois server: $whois_server\n\n";

 $seen = array();
 $netname = ;
 foreach ($wanted as $w) {
   $p = preg_grep( "/^$w/i" , $a );
   foreach ($p as $l) {
     $tmp = "\t" . $l . "\n";
     if (!in_array($tmp,$seen)) {
           $whois .= $tmp;
     }
     $seen[] = $tmp;
   }
 } 


 // get netnamt for action line
 $p = preg_grep( "/^NetName/i" , $a );
 foreach ($p as $l) {
   if (preg_match('/netname:\s+(.*)/i' , $l , $m)) { $netname = $m[1]; }
 }
 // get country too
 $p = preg_grep( "/^country/i" , $a );
 foreach ($p as $l) {
   if (preg_match('/country:\s+(.*)/i' , $l , $m)) { $country = $m[1]; }
 }
 $netname = ltrim(rtrim($netname));
 $country = ltrim(rtrim($country));

 if (empty($seen)) {
   foreach ($a as $l) {
     if (!preg_match("/^#/",$l) && preg_match("/\w/",$l)) {
       $whois .= $l . "\n";
     }
   }
 }
 // show the original info if it exist..
  if ($whois_old) {
   $o = explode("\n",trim($whois_old));
   foreach ($o as $l) {
     if (!preg_match("/^#/",$l) && preg_match("/\w/",$l)) {
       $whois .= "\t" . $l . "\n";
     }
   }
 }


 $whois .= "  ---------------------- END WHOIS ---------------------------\n";


 return array ($whois,$country,$netname);

}


// 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();
 $logs = `/usr/bin/find /var/log/snort/ -name alert`;

 $alert_logs = explode("\n",trim($logs));

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

}


?> </source>

Example Output

  • Email on Unblocked and/or Blocked

<source lang=text>

Unblocked: 8.8.8.8
Unblocked: 4.4.4.2

  • Blocked: 61.156.238.56
 ------------------------ WHOIS -----------------------------
 whois server: whois.apnic.net

netname: UNICOM-SD address: No.21,Jin-Rong Street address: Beijing,100033 address: P.R.China address: Jinan,Shandong P.R China inetnum: 61.156.0.0 - 61.156.255.255 descr: China Unicom Shandong province network descr: China Unicom descr: CNC Group CHINA169 Shandong Province Network country: CN

 ---------------------- END WHOIS ---------------------------
 ------------------ LOGS for 61.156.238.56 05/01/13 -----------------------

SID=1:2001219:18 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Potential SSH Scan" SRC_IP=61.156.238.56 SRC_PORT=5920 DST_IP={hidden} DST_PORT=22 PROTO=TCP SID=1:2500088:2849 PRI=2 CLASS=Misc Attack DESC="ET COMPROMISED Known Compromised or Hostile Host Traffic TCP (45)" SRC_IP=61.156.238.56 SRC_PORT=5920 DST_IP={hidden} DST_PORT=22 PROTO=TCP

 ---------------- END LOGS for 61.156.238.56 05/01/13 ---------------------



  • Blocked: 111.74.238.58
 ------------------------ WHOIS -----------------------------
 whois server: whois.apnic.net

netname: CHINANET-JX address: Jiangxi telecom network operation support department address: No.2009, Beijing East Road , nanchang,jiangxi province inetnum: 111.72.0.0 - 111.79.255.255 descr: CHINANET JIANGXI PROVINCE NETWORK descr: China Telecom descr: No.31,jingrong street descr: Beijing 100032 country: CN

 ---------------------- END WHOIS ---------------------------
 ------------------ LOGS for 111.74.238.58 05/01/13 -----------------------

SID=1:2001219:18 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Potential SSH Scan" SRC_IP=111.74.238.58 SRC_PORT=31091 DST_IP={hidden} DST_PORT=22 PROTO=TCP

 ---------------- END LOGS for 111.74.238.58 05/01/13 ---------------------



  • Blocked: 173.167.52.169 [173-167-52-169-ip-static.hfc.comcastbusiness.net]
 ------------------------ WHOIS -----------------------------
 whois server: whois.arin.net

Comcast Business Communications, LLC CBC-CM-4 (NET-173-160-0-0-1) 173.160.0.0 - 173.167.255.255 CONCEPT MINING INC CONCEPTMININGINC (NET-173-167-52-168-1) 173.167.52.168 - 173.167.52.175 Comcast Business Communications, LLC CBC-RICHMOND-17 (NET-173-167-52-0-1) 173.167.52.0 - 173.167.55.255

 ---------------------- END WHOIS ---------------------------
 ------------------ LOGS for 173.167.52.169 05/01/13 -----------------------

SID=1:2008578:6 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious Scan" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP SID=1:2011716:4 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious User-Agent Detected (friendly-scanner)" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP SID=1:2011716:4 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious User-Agent Detected (friendly-scanner)" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP SID=1:2011716:4 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious User-Agent Detected (friendly-scanner)" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP SID=1:2011716:4 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious User-Agent Detected (friendly-scanner)" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP SID=1:2011716:4 PRI=2 CLASS=Attempted Information Leak DESC="ET SCAN Sipvicious User-Agent Detected (friendly-scanner)" SRC_IP=173.167.52.169 SRC_PORT=5067 DST_IP={hidden} DST_PORT=5060 PROTO=UDP

 ---------------- END LOGS for 173.167.52.169 05/01/13 ---------------------

</source>