Pfsense: Difference between revisions
Line 6: | Line 6: | ||
</source> | </source> | ||
== | == Snort Auto Block Email == | ||
<source> | |||
* snort does not have any way to notify when it blocks/unblocks an IP. Here is a PHP script that will. | |||
* It uses the default notification list from pfsense (i.e. system/setup/notifications ) | |||
* | <source lang=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-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"; | |||
} | |||
} | |||
// 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 -c'; | |||
if (DEBUG) { print "\tDEBUG: " . $cmd . "\n\n";} | |||
$body .= "\n LOGS for $ip $log_date\n";; | |||
$body .= shell_exec ($cmd); | |||
$body .= "\n"; | |||
} | |||
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<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(); | |||
$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> | </source> |
Revision as of 23:14, 1 May 2013
- some minor changes I do to
Install Emacs
<source> pkg_add -r emacs-nox11 </source>
Snort Auto Block Email
* snort does not have any way to notify when it blocks/unblocks an IP. Here is a PHP script that will. * It uses the default notification list from pfsense (i.e. system/setup/notifications )
<source lang=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-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"; }
}
// 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 -c'; if (DEBUG) { print "\tDEBUG: " . $cmd . "\n\n";} $body .= "\n LOGS for $ip $log_date\n";; $body .= shell_exec ($cmd); $body .= "\n"; } 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>