Pfsense

From RARFORGE
Jump to: navigation, search
  • just some things to remember...


Contents

Install Emacs

pkg_add -r emacs-nox11

PHP Mode

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)
cd ~/.emacs.d
wget http://php-mode.svn.sourceforge.net/svnroot/php-mode/tags/php-mode-1.5.0/php-mode.el

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
    min: */5
   hour: *
   mday: *
  month: *
   wday: *
    who: root
command: /usr/local/bin/snort_autoblock_notify.php  &> /dev/null



snort_autoblock_notify.php

#!/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<br />\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;
  }
}
 
 
?>

Example Output

  • Email on Unblocked and/or Blocked
 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 ---------------------
 
-----------------------------------------------------------------------------------------------------------------------------------
Personal tools
Namespaces

Variants
Views
Actions
Navigation
Toolbox