aboutsummaryrefslogtreecommitdiffstats
path: root/config/pfblockerng
diff options
context:
space:
mode:
Diffstat (limited to 'config/pfblockerng')
-rw-r--r--config/pfblockerng/countrycodes.tar.bz2bin0 -> 841191 bytes
-rw-r--r--config/pfblockerng/geoipupdate.sh162
-rw-r--r--config/pfblockerng/pfblockerng.inc2616
-rw-r--r--config/pfblockerng/pfblockerng.js79
-rw-r--r--config/pfblockerng/pfblockerng.php1475
-rw-r--r--config/pfblockerng/pfblockerng.priv.inc30
-rw-r--r--config/pfblockerng/pfblockerng.sh927
-rw-r--r--config/pfblockerng/pfblockerng.widget.php280
-rw-r--r--config/pfblockerng/pfblockerng.xml495
-rw-r--r--config/pfblockerng/pfblockerng_alerts.php769
-rw-r--r--config/pfblockerng/pfblockerng_diag_dns.php318
-rw-r--r--config/pfblockerng/pfblockerng_log.php428
-rw-r--r--config/pfblockerng/pfblockerng_sync.xml246
-rw-r--r--config/pfblockerng/pfblockerng_top20.xml294
-rw-r--r--config/pfblockerng/pfblockerng_update.php426
-rw-r--r--config/pfblockerng/pfblockerng_v4lists.xml426
-rw-r--r--config/pfblockerng/pfblockerng_v6lists.xml421
-rw-r--r--config/pfblockerng/widget-pfblockerng.inc7
18 files changed, 9399 insertions, 0 deletions
diff --git a/config/pfblockerng/countrycodes.tar.bz2 b/config/pfblockerng/countrycodes.tar.bz2
new file mode 100644
index 00000000..afebf58a
--- /dev/null
+++ b/config/pfblockerng/countrycodes.tar.bz2
Binary files differ
diff --git a/config/pfblockerng/geoipupdate.sh b/config/pfblockerng/geoipupdate.sh
new file mode 100644
index 00000000..4b8fbb63
--- /dev/null
+++ b/config/pfblockerng/geoipupdate.sh
@@ -0,0 +1,162 @@
+#!/bin/sh
+#
+# pfBlockerNG MaxMind GeoLite GeoIP Updater Script - By BBcan177@gmail.com
+# Copyright (C) 2014 BBcan177@gmail.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation. You may not use, modify or
+# distribute this program under any other version of the GNU General
+# Public License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The GeoLite databases by MaxMind Inc., are distributed under the Creative Commons
+# Attribution-ShareAlike 3.0 Unported License. The attribution requirement
+# may be met by including the following in all advertising and documentation
+# mentioning features of or use of this database.
+
+# Folder Locations
+pathfetch=/usr/bin/fetch
+pathtar=/usr/bin/tar
+pathgunzip=/usr/bin/gunzip
+
+# File Locations
+pathdb=/var/db/pfblockerng
+pathlog=/var/log/pfblockerng
+errorlog=$pathlog/geoip.log
+pathgeoipdatgz=$pathdb/GeoIP.dat.gz
+pathgeoipdatgzv6=$pathdb/GeoIPv6.dat.gz
+pathgeoipdat=$pathdb/GeoIP.dat
+pathgeoipdatv6=$pathdb/GeoIPv6.dat
+pathgeoipcc=$pathdb/country_continent.csv
+pathgeoipcsv4=$pathdb/GeoIPCountryCSV.zip
+pathgeoipcsvfinal4=$pathdb/GeoIPCountryWhois.csv
+pathgeoipcsv6=$pathdb/GeoIPv6.csv.gz
+pathgeoipcsvfinal6=$pathdb/GeoIPv6.csv
+
+if [ ! -d $pathdb ]; then mkdir $pathdb; fi
+if [ ! -d $pathlog ]; then mkdir $pathlog; fi
+
+now=$(date)
+echo; echo "$now - Updating pfBlockerNG - Country Database Files"
+echo "pfBlockerNG uses GeoLite data created by MaxMind, available from http://www.maxmind.com"; echo
+
+#Function to update MaxMind GeoIP Binary (For Reputation Process)
+binaryupdate() {
+
+# Download Part 1 - GeoLite IPv4 Binary Database
+
+echo " ** Downloading MaxMind GeoLite IPv4 Binary Database (For Reputation/Alerts Processes) **"; echo
+URL="http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
+$pathfetch -v -o $pathgeoipdatgz -T 20 $URL
+if [ "$?" -eq "0" ]; then
+ $pathgunzip -f $pathgeoipdatgz
+ echo; echo " ( MaxMind IPv4 GeoIP.dat has been updated )"; echo
+ echo "Current Date/Timestamp:"
+ /bin/ls -alh $pathgeoipdat
+ echo
+else
+ echo; echo " => MaxMind IPv4 GeoIP.dat Update [ FAILED ]"; echo
+ echo "MaxMind IPV4 Binary Update FAIL [ $now ]" >> $errorlog
+fi
+
+# Download Part 2 - GeoLite IPv6 Binary Database
+
+echo; echo " ** Downloading MaxMind GeoLite IPv6 Binary Database (For Reputation/Alerts Processes) **"; echo
+URL="http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz"
+$pathfetch -v -o $pathgeoipdatgzv6 -T 20 $URL
+if [ "$?" -eq "0" ]; then
+ $pathgunzip -f $pathgeoipdatgzv6
+ echo; echo " ( MaxMind IPv6 GeoIPv6.dat has been updated )"; echo
+ echo "Current Date/Timestamp:"
+ /bin/ls -alh $pathgeoipdatv6
+ echo
+else
+ echo; echo " => MaxMind IPv6 GeoIPv6.dat Update [ FAILED ]"; echo
+ echo "MaxMind IPv6 Binary Update FAIL [ $now ]" >> $errorlog
+fi
+}
+
+
+#Function to update MaxMind Country Code Files
+csvupdate() {
+
+# Download Part 1 - CSV IPv4 Database
+
+echo; echo " ** Downloading MaxMind GeoLite IPv4 CSV Database **"; echo
+URL="http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip"
+$pathfetch -v -o $pathgeoipcsv4 -T 20 $URL
+if [ "$?" -eq "0" ]; then
+ $pathtar -zxvf $pathgeoipcsv4 -C $pathdb
+ if [ "$?" -eq "0" ]; then
+ echo; echo " ( MaxMind GeoIPCountryWhois has been updated )"; echo
+ echo "Current Date/Timestamp:"
+ /bin/ls -alh $pathgeoipcsvfinal4
+ echo
+ else
+ echo; echo " => MaxMind IPv4 GeoIPCountryWhois [ FAILED ]"; echo
+ echo "MaxMind CSV Database Update FAIL - Tar extract [ $now ]" >> $errorlog
+ fi
+else
+ echo; echo " => MaxMind IPv4 CSV Download [ FAILED ]"; echo
+ echo "MaxMind CSV Database Update FAIL [ $now ]" >> $errorlog
+fi
+
+# Download Part 2 - Country Definitions
+
+echo; echo " ** Downloading MaxMind GeoLite Database Country Definition File **"; echo
+URL="http://dev.maxmind.com/static/csv/codes/country_continent.csv"
+$pathfetch -v -o $pathgeoipcc -T 20 $URL
+if [ "$?" -eq "0" ]; then
+ echo; echo " ( MaxMind ISO 3166 Country Codes has been updated. )"; echo
+ echo "Current Date/Timestamp:"
+ /bin/ls -alh $pathgeoipcc
+ echo
+else
+ echo; echo " => MaxMind ISO 3166 Country Codes Update [ FAILED ]"; echo
+ echo "MaxMind ISO 3166 Country Code Update FAIL [ $now ]" >> $errorlog
+fi
+
+# Download Part 3 - Country Definitions IPV6
+
+echo " ** Downloading MaxMind GeoLite IPv6 CSV Database **"; echo
+URL="http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz"
+$pathfetch -v -o $pathgeoipcsv6 -T 20 $URL
+if [ "$?" -eq "0" ]; then
+ $pathgunzip -f $pathgeoipcsv6
+ echo; echo " ( MaxMind GeoIPv6.csv has been updated )"; echo
+ echo "Current Date/Timestamp:"
+ /bin/ls -alh $pathgeoipcsvfinal6
+ echo
+else
+ echo; echo " => MaxMind GeoLite IPv6 Update [ FAILED ]"; echo
+ echo "MaxMind GeoLite IPv6 Update FAIL [ $now ]" >> $errorlog
+fi
+}
+
+
+# CALL APPROPRIATE PROCESSES using Script Argument $1
+case $1 in
+ bu)
+ binaryupdate
+ ;;
+ cu)
+ csvupdate
+ ;;
+ all)
+ binaryupdate
+ csvupdate
+ ;;
+ *)
+ exit
+ ;;
+esac
+exit \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.inc b/config/pfblockerng/pfblockerng.inc
new file mode 100644
index 00000000..d612dbf1
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.inc
@@ -0,0 +1,2616 @@
+<?php
+/*
+ pfBlockerNG.inc
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ part of the Postfix package for pfSense
+ Copyright (C) 2010 Erik Fonnesbeck
+ Based upon pfBlocker by
+ Copyright (C) 2011-2012 Marcello Coutinho
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+//error_reporting(E_ALL);
+
+require_once("util.inc");
+require_once("functions.inc");
+require_once("pkg-utils.inc");
+require_once("pfsense-utils.inc");
+require_once("globals.inc");
+require_once("services.inc");
+
+# [ $pfb ] pfBlockerNG Global Array for Paths and Variables. This needs to be called to get the Updated Settings.
+function pfb_global() {
+
+ global $g,$config,$pfb;
+
+ # Folders
+ $pfb['dbdir'] = "{$g['vardb_path']}/pfblockerng";
+ $pfb['aliasdir'] = "{$g['vardb_path']}/aliastables";
+ $pfb['logdir'] = "{$g['varlog_path']}/pfblockerng";
+ $pfb['etdir'] = "{$pfb['dbdir']}/ET";
+ $pfb['nativedir'] = "{$pfb['dbdir']}/native";
+ $pfb['denydir'] = "{$pfb['dbdir']}/deny";
+ $pfb['matchdir'] = "{$pfb['dbdir']}/match";
+ $pfb['permitdir'] = "{$pfb['dbdir']}/permit";
+ $pfb['origdir'] = "{$pfb['dbdir']}/original";
+ $pfb['ccdir'] = "/usr/pbi/pfblockerng-" . php_uname("m") . "/share/GeoIP";
+
+ # Create Folders if not Exist.
+ $folder_array = array ("{$pfb['dbdir']}","{$pfb['logdir']}","{$pfb['ccdir']}","{$pfb['origdir']}","{$pfb['nativedir']}","{$pfb['denydir']}","{$pfb['matchdir']}","{$pfb['permitdir']}","{$pfb['aliasdir']}");
+ foreach ($folder_array as $folder) {
+ safe_mkdir ("{$folder}",0755);
+ }
+
+ # Files
+ $pfb['master'] = "{$pfb['dbdir']}/masterfile";
+ $pfb['errlog'] = "{$pfb['logdir']}/error.log";
+ $pfb['geolog'] = "{$pfb['logdir']}/geoip.log";
+ $pfb['log'] = "{$pfb['logdir']}/pfblockerng.log";
+ $pfb['supptxt'] = "{$pfb['dbdir']}/pfbsuppression.txt";
+ $pfb['script'] = 'sh /usr/local/pkg/pfblockerng/pfblockerng.sh';
+
+ # Collect pfSense Version
+ $pfb['pfsenseversion'] = substr(trim(file_get_contents("/etc/version")),0,3);
+
+ # General Variables
+ $pfb['config'] = $config['installedpackages']['pfblockerng']['config'][0];
+
+ # Enable/Disable of pfBlockerNG
+ $pfb['enable'] = $pfb['config']['enable_cb'];
+ # Keep Blocklists on pfBlockerNG Disable
+ $pfb['keep'] = $pfb['config']['pfb_keep'];
+ # Enable Suppression
+ $pfb['supp'] = $pfb['config']['suppression'];
+ # Max Lines in pfblockerng.log file
+ $pfb['logmax'] = $pfb['config']['log_maxlines'];
+ $pfb['iplocal'] = $config['interfaces']['lan']['ipaddr'];
+ # Disable Country Database CRON Updates
+ $pfb['cc'] = $pfb['config']['database_cc'];
+
+ # Set pfBlockerNG to Disabled on 'Re-Install'
+ if (isset($pfb['install']) && $pfb['install']) {
+ $pfb['enable'] = "";
+ $pfb['install'] = FALSE;
+ }
+}
+
+pfb_global();
+
+# Set Max PHP Memory Setting
+$uname = posix_uname();
+if ($uname['machine'] == 'amd64')
+ ini_set('memory_limit', '256M');
+
+
+# Function to decode to Alias Custom Entry Box.
+function pfbng_text_area_decode($text) {
+ return preg_replace('/\r\n/', "\n",base64_decode($text));
+}
+
+
+# Manage Log File Line Limit
+function pfb_log_mgmt() {
+ global $pfb;
+ pfb_global();
+
+ if ($pfb['logmax'] == "nolimit") {
+ # Skip Log Mgmt
+ } else {
+ exec("/usr/bin/tail -n {$pfb['logmax']} {$pfb['log']} > /tmp/pfblog; /bin/mv -f /tmp/pfblog {$pfb['log']}");
+ }
+}
+
+
+# Record Log Messsages to pfBlockerNG Log File and/or Error Log File.
+function pfb_logger($log, $type) {
+ global $g,$pfb,$pfbarr;
+
+ $now = date("m/d/y G:i:s", time());
+
+ # Only log timestamp if new
+ if (preg_match("/NOW/", $log)) {
+ if ($now == $pfb['pnow']) {
+ $log = str_replace("[ NOW ]", "", "{$log}");
+ } else {
+ $log = str_replace("NOW", $now, "{$log}");
+ }
+ $pfb['pnow'] = "{$now}";
+ }
+
+ if ($type == 2) {
+ @file_put_contents("{$pfb['log']}", "{$log}", FILE_APPEND);
+ @file_put_contents("{$pfb['errlog']}", "{$log}", FILE_APPEND);
+ } elseif ($type == 3) {
+ @file_put_contents("{$pfb['geolog']}", "{$log}", FILE_APPEND);
+ } else {
+ @file_put_contents("{$pfb['log']}", "{$log}", FILE_APPEND);
+ }
+}
+
+
+# Determine Folder Location for 'List'
+function pfb_determine_list_detail($list) {
+ global $g,$pfb,$pfbarr;
+ $pfbarr = array();
+
+ if (in_array($list,array('Match_Both','Match_Inbound','Match_Outbound','Alias_Match'))) {
+ $pfbarr['skip'] = FALSE;
+ $pfbarr['folder'] = "{$pfb['matchdir']}";
+ } elseif (in_array($list,array('Permit_Both','Permit_Inbound','Permit_Outbound','Alias_Permit'))) {
+ $pfbarr['skip'] = FALSE;
+ $pfbarr['folder'] = "{$pfb['permitdir']}";
+ } elseif ($list == "Alias_Native") {
+ $pfbarr['skip'] = FALSE;
+ $pfbarr['folder'] = "{$pfb['nativedir']}";
+ } else {
+ # Deny
+ $pfbarr['skip'] = TRUE;
+ $pfbarr['folder'] = "{$pfb['denydir']}";
+ }
+
+ // Collect proper Alias Table Description (Alias Only vs AutoRules)
+ if (preg_match("/Alias/", $list)) {
+ $pfbarr['descr'] = "";
+ } else {
+ $pfbarr['descr'] = " Auto ";
+ }
+
+ return $pfbarr;
+}
+
+# Create Suppression Alias
+function pfb_create_suppression_alias() {
+ global $config;
+
+ // Collect existing pfsense alias(s)
+ if (is_array($config['aliases']['alias'])) {
+ foreach($config['aliases']['alias'] as $exalias) {
+ $new_aliases[] = $exalias;
+ }
+ }
+ // Create New pfBlockerNGSuppress Alias
+ $new_aliases[] = array( "name" => "pfBlockerNGSuppress",
+ "address" => "",
+ "descr" => "pfBlockerNG Suppression List (24|32 CIDR only)",
+ "type" => "network",
+ "detail" => ""
+ );
+ $config['aliases']['alias'] = $new_aliases;
+ write_config();
+}
+
+
+# Create Suppression file from Alias
+function pfb_create_suppression_file() {
+ global $config,$pfb;
+
+ // Find pfBlockerNGSuppress Array ID Number
+ $pfb['found'] = FALSE;
+ if (is_array($config['aliases']['alias'])) {
+ $pfb_id = 0;
+ foreach ($config['aliases']['alias'] as $alias) {
+ if ($alias['name'] == "pfBlockerNGSuppress") {
+ $pfb['found'] = TRUE;
+ break;
+ }
+ $pfb_id++;
+ }
+
+ if ($pfb['found']) {
+ $pfb_suppress = str_replace(" ", "\n", $config['aliases']['alias'][$pfb_id]['address']);
+ if (!empty($pfb_suppress))
+ @file_put_contents("{$pfb['supptxt']}",$pfb_suppress, LOCK_EX);
+ } else {
+ # Delete Suppression File if Alias is Empty.
+ unlink_if_exists("{$pfb['supptxt']}");
+ }
+ }
+
+ // Call Function to Create Suppression Alias.
+ if (!$pfb['found'])
+ pfb_create_suppression_alias();
+}
+
+
+// IPv6 Range to CIDR function used courtesey from:
+// https://github.com/stilez/pfsense-leases/blob/50cc0fa81dba5fe91bcddaea016c245d1b8479cc/etc/inc/util.inc
+function ip_range_to_subnet_array_temp2($ip1, $ip2) {
+
+ if (is_ipaddrv4($ip1) && is_ipaddrv4($ip2)) {
+ $proto = 'ipv4'; // for clarity
+ $bits = 32;
+ $ip1bin = decbin(ip2long32($ip1));
+ $ip2bin = decbin(ip2long32($ip2));
+ } elseif (is_ipaddrv6($ip1) && is_ipaddrv6($ip2)) {
+ $proto = 'ipv6';
+ $bits = 128;
+ $ip1bin = Net_IPv6::_ip2Bin($ip1);
+ $ip2bin = Net_IPv6::_ip2Bin($ip2);
+ } else
+ return array();
+
+ // it's *crucial* that binary strings are guaranteed the expected length; do this for certainty even though for IPv6 it's redundant
+ $ip1bin = str_pad($ip1bin, $bits, '0', STR_PAD_LEFT);
+ $ip2bin = str_pad($ip2bin, $bits, '0', STR_PAD_LEFT);
+
+ if ($ip1bin === $ip2bin)
+ return array($ip1 . '/' . $bits);
+
+ if (strcmp($ip1bin, $ip2bin) > 0)
+ list ($ip1bin, $ip2bin) = array($ip2bin, $ip1bin); // swap contents of ip1 <= ip2
+
+ $rangesubnets = array();
+ $netsize = 0;
+
+ do {
+ // at loop start, $ip1 is guaranteed strictly less than $ip2 (important for edge case trapping and preventing accidental binary wrapround)
+ // which means the assignments $ip1 += 1 and $ip2 -= 1 will always be "binary-wrapround-safe"
+
+ // step #1 if start ip (as shifted) ends in any '1's, then it must have a single cidr to itself (any cidr would include the '0' below it)
+
+ if (substr($ip1bin, -1, 1) == '1') {
+ // the start ip must be in a separate one-IP cidr range
+ $new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ $n = strrpos($ip1bin, '0'); //can't be all 1's
+ $ip1bin = ($n == 0 ? '' : substr($ip1bin, 0, $n)) . '1' . str_repeat('0', $bits - $n - 1); // BINARY VERSION OF $ip1 += 1
+ }
+
+ // step #2, if end ip (as shifted) ends in any zeros then that must have a cidr to itself (as cidr cant span the 1->0 gap)
+
+ if (substr($ip2bin, -1, 1) == '0') {
+ // the end ip must be in a separate one-IP cidr range
+ $new_subnet_ip = substr($ip2bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ $n = strrpos($ip2bin, '1'); //can't be all 0's
+ $ip2bin = ($n == 0 ? '' : substr($ip2bin, 0, $n)) . '0' . str_repeat('1', $bits - $n - 1); // BINARY VERSION OF $ip2 -= 1
+ // already checked for the edge case where end = start+1 and start ends in 0x1, above, so it's safe
+ }
+
+ // this is the only edge case arising from increment/decrement.
+ // it happens if the range at start of loop is exactly 2 adjacent ips, that spanned the 1->0 gap. (we will have enumerated both by now)
+
+ if (strcmp($ip2bin, $ip1bin) < 0)
+ continue;
+
+ // step #3 the start and end ip MUST now end in '0's and '1's respectively
+ // so we have a non-trivial range AND the last N bits are no longer important for CIDR purposes.
+
+ $shift = $bits - max(strrpos($ip1bin, '0'), strrpos($ip2bin, '1')); // num of low bits which are '0' in ip1 and '1' in ip2
+ $ip1bin = str_repeat('0', $shift) . substr($ip1bin, 0, $bits - $shift);
+ $ip2bin = str_repeat('0', $shift) . substr($ip2bin, 0, $bits - $shift);
+ $netsize += $shift;
+ if ($ip1bin === $ip2bin) {
+ // we're done.
+ $new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ continue;
+ }
+
+ // at this point there's still a remaining range, and either startip ends with '1', or endip ends with '0'. So repeat cycle.
+ } while (strcmp($ip1bin, $ip2bin) < 0);
+
+ // subnets are ordered by bit size. Re sort by IP ("naturally") and convert back to IPv4/IPv6
+
+ ksort($rangesubnets, SORT_STRING);
+ $out = array();
+
+ foreach ($rangesubnets as $ip => $netmask) {
+ if ($proto == 'ipv4') {
+ $i = str_split($ip, 8);
+ $out[] = implode('.', array( bindec($i[0]),bindec($i[1]),bindec($i[2]),bindec($i[3]))) . '/' . $netmask;
+ } else
+ $out[] = Net_IPv6::compress(Net_IPv6::_bin2Ip($ip)) . '/' . $netmask;
+ }
+
+ return $out;
+}
+
+
+# Main pfBlockerNG Function
+function sync_package_pfblockerng($cron = "") {
+
+ global $g,$config,$pfb,$pfbarr;
+ pfb_global();
+
+ # Detect Boot Process or Update via CRON
+ if (isset($_POST) && $cron == "") {
+ if (!preg_match("/\w+/",$_POST['__csrf_magic'])) {
+ log_error("[pfBlockerNG] Sync terminated during boot process.");
+ return;
+ }
+ }
+ log_error("[pfBlockerNG] Starting sync process.");
+
+ # Start of pfBlockerNG Logging to 'pfblockerng.log'
+ if ($pfb['enable'] == "on" && !$pfb['save']) {
+ $log = " UPDATE PROCESS START [ NOW ]\n";
+ } else {
+ $log = "\n**Saving Configuration [ NOW ] ...\n";
+ }
+ pfb_logger("{$log}","1");
+
+ # TBC if Required ! (Fetch Timeout in 2.2)
+
+ #apply fetch timeout to pfsense-utils.inc
+ $pfsense_utils = file_get_contents('/etc/inc/pfsense-utils.inc');
+ $new_pfsense_utils = preg_replace("/\/usr\/bin\/fetch -q/","/usr/bin/fetch -T 5 -q",$pfsense_utils);
+ if ($new_pfsense_utils != $pfsense_utils) {
+ @file_put_contents('/etc/inc/pfsense-utils.inc',$new_pfsense_utils, LOCK_EX);
+ }
+
+ # Collect pfSense Max Table Size Entry
+ $pfb['table_limit'] = ($config['system']['maximumtableentries'] != "" ? $config['system']['maximumtableentries'] : "2000000");
+
+ # If Table limit not defined, set Default to 2M
+ $config['system']['maximumtableentries'] = "{$pfb['table_limit']}";
+
+ # Collect local web gui configuration
+ $pfb['weblocal'] = ($config['system']['webgui']['protocol'] != "" ? $config['system']['webgui']['protocol'] : "http");
+ $pfb['port'] = $config['system']['webgui']['port'];
+ if ($pfb['port'] == "") {
+ if ($config['system']['webgui']['protocol'] == "http") {
+ $pfb['port'] = "80";
+ } else {
+ $pfb['port'] = "443";
+ }
+ }
+ $pfb['weblocal'] .= "://127.0.0.1:{$pfb['port']}/pfblockerng/pfblockerng.php";
+
+ # Define Inbound/Outbound Action is not user selected.
+ $pfb['deny_action_inbound'] = ($pfb['config']['inbound_deny_action'] != "" ? $pfb['config']['inbound_deny_action'] : "block");
+ $pfb['deny_action_outbound'] = ($pfb['config']['outbound_deny_action'] != "" ? $pfb['config']['outbound_deny_action'] : "reject");
+
+ # Validation check to see if the Original pfBlocker package is Enabled
+ $pfb['validate']= $pfb['config']['pfblocker_cb'];
+ # User Defined CRON Start Minute
+ $pfb['min'] = $pfb['config']['pfb_min'];
+ # Reloads Existing Blocklists without Downloading New Lists
+ $pfb['reuse'] = $pfb['config']['pfb_reuse'];
+ # Enable OpenVPN AutoRules
+ $pfb['openvpn'] = $pfb['config']['openvpn_action'];
+ # Enable/Disable Floating Auto-Rules
+ $pfb['float'] = $pfb['config']['enable_float'];
+ # Enable Remove of Duplicate IPs utilizing Grepcidr
+ $pfb['dup'] = $pfb['config']['enable_dup'];
+ # Order of the Auto-Rules
+ $pfb['order'] = $pfb['config']['pass_order'];
+ # Suffix used for Auto-Rules
+ $pfb['suffix'] = $pfb['config']['autorule_suffix'];
+
+ # Reputation Variables
+ $pfb['config_rep'] = $config['installedpackages']['pfblockerngreputation']['config'][0];
+
+ # Enable/Disable Reputation
+ $pfb['rep'] = $pfb['config_rep']['enable_rep'];
+ # Enable/Disable 'pDup'
+ $pfb['pdup'] = $pfb['config_rep']['enable_pdup'];
+ # Enable/Disable 'dDup'
+ $pfb['dedup'] = ($pfb['config_rep']['enable_dedup'] != "" ? $pfb['config_rep']['enable_dedup'] : "x");
+ # 'Max' variable setting for Reputation
+ $pfb['max'] = ($pfb['config_rep']['p24_max_var'] != "" ? $pfb['config_rep']['p24_max_var'] : "x");
+ # 'dMax' variable setting for Reputation
+ $pfb['dmax'] = ($pfb['config_rep']['p24_dmax_var'] != "" ? $pfb['config_rep']['p24_dmax_var'] : "x");
+ # 'pMax' variable setting for Reputation
+ $pfb['pmax'] = ($pfb['config_rep']['p24_pmax_var'] != "" ? $pfb['config_rep']['p24_pmax_var'] : "x");
+ # Action for Whitelist Country Category
+ $pfb['ccwhite'] = $pfb['config_rep']['ccwhite'];
+ # Action for Blacklist Country Category
+ $pfb['ccblack'] = $pfb['config_rep']['ccblack'];
+ # List of Countries in the Whitelist Category
+ $pfb['ccexclude']= ($pfb['config_rep']['ccexclude'] != "" ? $pfb['config_rep']['ccexclude'] : "x");
+ # Emerging Threats IQRisk Block Categories
+ $pfb['etblock'] = ($pfb['config_rep']['etblock'] != "" ? $pfb['config_rep']['etblock'] : "x");
+ # Emerging Threats IQRisk Match Categories
+ $pfb['etmatch'] = ($pfb['config_rep']['etmatch'] != "" ? $pfb['config_rep']['etmatch'] : "x");
+ # Perform a Force Update on ET Categories
+ $pfb['etupdate']= $pfb['config_rep']['et_update'];
+
+ # Variables
+
+ # Starting Variable to Skip rep, pdup and dedeup functions if no changes are required
+ $pfb['dupcheck'] = FALSE;
+ ## $pfb['save'] is used to determine if User pressed "Save" Button to avoid Collision with CRON.
+ ## This is defined in each pfBlockerNG XML Files
+
+ # Validation Check to ensure pfBlocker and pfBlockerNG are not running at the same time.
+ if ($pfb['validate'] == "") {
+ # Collect pfBlocker Enabled Status from config file
+ $pfb['validate_chk'] = $config['installedpackages']['pfblocker']['config'][0]['enable_cb'];
+ if ($pfb['validate_chk'] == "on") {
+ $log = "\n The Package 'pfBlocker' is currently Enabled. Either Disable pfBlocker, or 'Disable Validation Check' in pfBlockerNG \n";
+ pfb_logger("{$log}","1");
+ return;
+ }
+ }
+
+
+ #############################################
+ # Configure ARRAYS #
+ #############################################
+
+ $continents = array ( "Africa" => "pfB_Africa",
+ "Antartica" => "pfB_Antartica",
+ "Asia" => "pfB_Asia",
+ "Europe" => "pfB_Europe",
+ "North America" => "pfB_NAmerica",
+ "Oceania" => "pfB_Oceania",
+ "South America" => "pfB_SAmerica",
+ "Top Spammers" => "pfB_Top",
+ "Proxy and Satellite" => "pfB_PS"
+ );
+
+ #create rules vars and arrays
+ # Array used to Collect Changes to Aliases to be saved to Config
+ $new_aliases = array();
+ $new_aliases_list = array();
+ $continent_existing = array();
+ $continent_new = array();
+ $permit_inbound = array();
+ $permit_outbound = array();
+ $deny_inbound = array();
+ $deny_outbound = array();
+ # An Array of all Aliases (Active and non-Active)
+ $aliases_list = array();
+ # This is an Array of Aliases that Have Updated Lists via CRON/Force Update when 'Reputation' disabled.
+ $pfb_alias_lists = array();
+ # This is an Array of All Active Aliases used when 'Reputation' enabled
+ $pfb_alias_lists_all = array();
+
+ # Base Rule Array
+ $base_rule_reg = array( "id" => "",
+ "tag" => "",
+ "tagged" => "",
+ "max" => "",
+ "max-src-nodes" => "",
+ "max-src-conn" => "",
+ "max-src-states"=> "",
+ "statetimeout" => "",
+ "statetype" => "keep state",
+ "os" => ""
+ );
+
+ # Floating Rules, Base Rule Array
+ $base_rule_float = array("id" => "",
+ "tag" => "",
+ "tagged" => "",
+ "quick" => "yes",
+ "floating" => "yes",
+ "max" => "",
+ "max-src-nodes" => "",
+ "max-src-conn" => "",
+ "max-src-states"=> "",
+ "statetimeout" => "",
+ "statetype" => "keep state",
+ "os" => ""
+ );
+
+
+ #############################################
+ # Configure Rule Suffix #
+ #############################################
+
+ # Discover if any Rules are AutoRules (If no AutoRules found, $pfb['autorules'] is FALSE, Skip Rules Re-Order )
+ # To configure Auto Rule Suffix. pfBlockerNG must be disabled to change Suffix and to avoid Duplicate Rules
+ $pfb['autorules'] = FALSE;
+ $pfb['found'] = FALSE;
+ foreach ($continents as $continent => $pfb_alias) {
+ if (is_array($config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config'])) {
+ $continent_config = $config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config'][0];
+ if ($continent_config['action'] != "Disabled" && in_array($continent_config['action'],array('Deny_Both','Deny_Inbound','Deny_Outbound','Match_Both','Match_Inbound','Match_Outbound','Permit_Both','Permit_Inbound','Permit_Outbound'))) {
+ $pfb['autorules'] = TRUE;
+ $pfb['found'] = TRUE;
+ break;
+ }
+ }
+ }
+
+ $list_type = array ("pfblockernglistsv4", "pfblockernglistsv6");
+ foreach ($list_type as $ip_type) {
+ if ($config['installedpackages'][$ip_type]['config'] != "" && !$pfb['found']) {
+ foreach($config['installedpackages'][$ip_type]['config'] as $list) {
+ if ($list['action'] != "Disabled" && in_array($list['action'],array('Deny_Both','Deny_Inbound','Deny_Outbound','Match_Both','Match_Inbound','Match_Outbound','Permit_Both','Permit_Inbound','Permit_Outbound'))) {
+ $pfb['autorules'] = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ #Configure Auto Rule Suffix. pfBlockerNG must be disabled to change Suffix and to avoid Duplicate Rules
+ # Count Number of Rules with 'pfB_'
+ $count = 0;
+ if (is_array($config['filter']['rule'])) {
+ foreach ($config['filter']['rule'] as $rule) {
+ # Collect any pre-existing Suffix
+ if (preg_match("/pfB_\w+(\s.*)/",$rule['descr'], $pfb_suffix_real) && $count == 0) {
+ $pfb_suffix_match = $pfb_suffix_real[1];
+ }
+ # Query for Existing pfB Rules
+ if (preg_match("/pfB_/",$rule['descr'])) {
+ $count++;
+ break;
+ }
+ }
+ }
+
+ # Change Suffix only if No pfB Rules Found and Auto Rules are Enabled.
+ if ($pfb['autorules'] && $count == 0) {
+ switch ($pfb['suffix']) {
+ case "autorule":
+ $pfb['suffix'] = " auto rule";
+ break;
+ case "standard":
+ $pfb['suffix'] = "";
+ break;
+ case "ar":
+ $pfb['suffix'] = " AR";
+ break;
+ }
+ } else {
+ if ($pfb['autorules']) {
+ # Use existing Suffix Match
+ $pfb['suffix'] = $pfb_suffix_match;
+ } else {
+ # Leave Rule Suffix 'Blank'
+ $pfb['suffix'] = "";
+ }
+ }
+
+
+ #############################################
+ # Configure INBOUND/OUTBOUND INTERFACES #
+ #############################################
+
+ # Collect pfSense Interface Order
+ $ifaces = get_configured_interface_list();
+
+ if (!empty($pfb['config']['inbound_interface'])) {
+ # Sort Interface Array to match pfSense Interface order to allow Floating Rules to populate.
+ $selected_interfaces = explode(",",$pfb['config']['inbound_interface']);
+ # Sort pfBlockerNG Interface order to pfSense Interface Order
+ $sort_interfaces = array_intersect($ifaces, $selected_interfaces);
+ $implode_interfaces = ltrim(implode(",",$sort_interfaces), ",");
+ # CSV String for Inbound Interfaces for 'pfB_' Match Rules
+ $pfb['inbound_floating'] = $implode_interfaces;
+ $pfb['inbound_interfaces_float'] = explode(" ",$implode_interfaces);
+
+ # Assign Inbound Base Rule/Interfaces
+ if ($pfb['float'] == "on") {
+ # Define Base Firewall Floating Rules Settings
+ $base_rule = $base_rule_float;
+ $pfb['inbound_interfaces'] = $pfb['inbound_interfaces_float'];
+ } else {
+ # Define Base Firewall Rules Settings
+ $base_rule = $base_rule_reg;
+ $pfb['inbound_interfaces'] = explode(",",$pfb['config']['inbound_interface']);
+ }
+ } else {
+ # Define Empty Variable/Array
+ $pfb['inbound_interfaces_float'] = "";
+ $pfb['inbound_interfaces'] = array();
+ }
+
+ if (!empty($pfb['config']['outbound_interface'])) {
+ # Sort Interface Array to match pfSense Interface order to allow Floating Rules to populate.
+ $selected_interfaces = explode(",",$pfb['config']['outbound_interface']);
+ # Sort pfBlockerNG Interface order to pfSense Interface Order
+ $sort_interfaces = array_intersect($ifaces, $selected_interfaces);
+ // If OpenVPN Interfaces are not in dropdown menu
+ if ($pfb['openvpn'] == "on" && $config['openvpn']['openvpn-server'] || $pfb['openvpn'] == "on" && $config['openvpn']['openvpn-client'])
+ if (!in_array("openvpn",$sort_interfaces))
+ array_push($sort_interfaces, "openvpn");
+ $implode_interfaces = ltrim(implode(",",$sort_interfaces), ",");
+ # CSV String for Outbound Interfaces for 'pfB_' Match Rules
+ $pfb['outbound_floating'] = $implode_interfaces;
+ $pfb['outbound_interfaces_float'] = explode(" ",$implode_interfaces);
+
+ # Assign Outbound Base Rule/Interfaces
+ if ($pfb['float'] == "on") {
+ $base_rule = $base_rule_float;
+ $pfb['outbound_interfaces'] = $pfb['outbound_interfaces_float'];
+ } else {
+ $base_rule = $base_rule_reg;
+ $pfb['outbound_interfaces'] = explode(",",$pfb['config']['outbound_interface']);
+ // If OpenVPN Interfaces are not in dropdown menu
+ if ($pfb['openvpn'] == "on" && $config['openvpn']['openvpn-server'] || $pfb['openvpn'] == "on" && $config['openvpn']['openvpn-client'])
+ if (!in_array("openvpn",$sort_interfaces))
+ array_push($pfb['outbound_interfaces'], "openvpn");
+ }
+ } else {
+ # Define Empty Variable/Array
+ $pfb['outbound_interfaces_float'] = "";
+ $pfb['outbound_interfaces'] = array();
+ }
+
+
+ #############################################
+ # Clear Removed Lists from Masterfiles #
+ #############################################
+
+ # Process to keep Masterfiles in Sync with Valid Lists from config.conf file.
+ $pfb['sync_master'] = TRUE;
+
+ # Don't execute this function when pfBlockerNG is Disabled and 'Keep Blocklists' is enabled.
+ if ($pfb['enable'] == "" && $pfb['keep'] == "on")
+ $pfb['sync_master'] = FALSE;
+
+ if ($pfb['sync_master']) {
+ $pfb['existing']['match']['type'] = "match";
+ $pfb['existing']['permit']['type'] = "permit";
+ $pfb['existing']['deny']['type'] = "deny";
+ $pfb['existing']['native']['type'] = "native";
+ $pfb['existing']['match']['folder'] = "{$pfb['matchdir']}";
+ $pfb['existing']['permit']['folder'] = "{$pfb['permitdir']}";
+ $pfb['existing']['deny']['folder'] = "{$pfb['denydir']}";
+ $pfb['existing']['native']['folder'] = "{$pfb['nativedir']}";
+ $pfb['actual']['match']['type'] = "match";
+ $pfb['actual']['permit']['type'] = "permit";
+ $pfb['actual']['deny']['type'] = "deny";
+ $pfb['actual']['native']['type'] = "native";
+ $pfb['actual']['match']['folder'] = "{$pfb['matchdir']}";
+ $pfb['actual']['permit']['folder'] = "{$pfb['permitdir']}";
+ $pfb['actual']['deny']['folder'] = "{$pfb['denydir']}";
+ $pfb['actual']['native']['folder'] = "{$pfb['nativedir']}";
+
+ // Find all Enabled Continents Lists
+ foreach ($continents as $continent => $pfb_alias) {
+ if (is_array($config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config']) && $pfb['enable'] == "on") {
+ $continent_config = $config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config'][0];
+ if ($continent_config['action'] != "Disabled") {
+ $cont_type = array ("countries4" => "_v4", "countries6" => "_v6");
+ foreach ($cont_type as $c_type => $vtype) {
+ if ($continent_config[$c_type] != "") {
+ # Set Parameters for 'Match', 'Permit', 'Native' and 'Deny'
+ if (in_array($continent_config['action'],array('Match_Both','Match_Inbound','Match_Outbound','Alias_Match'))) {
+ $pfb['existing']['match'][] = "{$pfb_alias}{$vtype}";
+ } elseif (in_array($continent_config['action'],array('Permit_Both','Permit_Inbound','Permit_Outbound','Alias_Permit'))){
+ $pfb['existing']['permit'][] = "{$pfb_alias}{$vtype}";
+ } elseif ($continent_config['action'] == "Alias_Native") {
+ $pfb['existing']['native'][] = "{$pfb_alias}{$vtype}";
+ } else {
+ $pfb['existing']['deny'][] = "{$pfb_alias}{$vtype},"; // Add Trailing ','
+ }
+ }
+ }
+ }
+ }
+ }
+
+ # Find all Enabled IPv4/IPv6 Lists
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($config['installedpackages'][$ip_type]['config'] != "" && $pfb['enable'] == "on") {
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ if (is_array($list['row']) && $list['action'] != "Disabled") {
+ foreach ($list['row'] as $row) {
+ if ($vtype == "_v4") {
+ $pfb_alias = "{$row['header']}";
+ } else {
+ $pfb_alias = "{$row['header']}_v6";
+ }
+ # Collect Enabled Lists
+ if ($row['url'] != "" && $row['state'] != "Disabled") {
+ # Set Parameters for 'Match', 'Permit', 'Native' and 'Deny'
+ if (in_array($list['action'],array('Match_Both','Match_Inbound','Match_Outbound','Alias_Match'))) {
+ $pfb['existing']['match'][] = "{$pfb_alias}";
+ } elseif (in_array($list['action'],array('Permit_Both','Permit_Inbound','Permit_Outbound','Alias_Permit'))) {
+ $pfb['existing']['permit'][] = "{$pfb_alias}";
+ } elseif ($list['action'] == "Alias_Native") {
+ $pfb['existing']['native'][] = "{$pfb_alias}";
+ } else {
+ $pfb['existing']['deny'][] = "{$pfb_alias},"; // Add Trailing ','
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ # Find all Enabled IPv4 'Custom List' Header Names and Check if 'Emerging Threats Update' and 'Custom List Update' Needs Force Updating
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($config['installedpackages'][$ip_type]['config'] != "" && $pfb['enable'] == "on") {
+ $count = -1;
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ if (is_array($list['row']) && $list['action'] != "Disabled") {
+ $count++;
+ # Check if 'Emerging Threats Update' Needs Updating before next CRON Event.
+ if (is_array($list['row']) && $row['state'] != "Disabled" && $pfb['etupdate'] == "enabled" && $vtype == "_v4") {
+ foreach ($list['row'] as $row) {
+ $aliasname = $row['header'];
+ if ($row['format'] == "et") {
+ unlink_if_exists("{$pfb['denydir']}/{$aliasname}.txt");
+ $config['installedpackages']['pfblockerngreputation']['config'][0]['et_update'] = "disabled";
+ break;
+ }
+ }
+ }
+ }
+
+ # Collect Enabled Custom List Box Aliases
+ if (pfbng_text_area_decode($list['custom']) != "") {
+ if ($vtype == "_v4") {
+ $pfb_alias = "{$list['aliasname']}_custom";
+ } else {
+ $pfb_alias = "{$list['aliasname']}_custom_v6";
+ }
+ # Determine Folder Location for 'List'
+ if (in_array($list['action'],array('Match_Both','Match_Inbound','Match_Outbound','Alias_Match'))) {
+ $pfb['existing']['match'][] = "{$pfb_alias}";
+ $pfbfolder = "{$pfb['matchdir']}";
+ } elseif (in_array($list['action'],array('Permit_Both','Permit_Inbound','Permit_Outbound','Alias_Permit'))) {
+ $pfb['existing']['permit'][] = "{$pfb_alias}";
+ $pfbfolder = "{$pfb['permitdir']}";
+ } elseif ($list['action'] == "Alias_Native") {
+ $pfb['existing']['native'][] = "{$pfb_alias}";
+ $pfbfolder = "{$pfb['nativedir']}";
+ } else {
+ $pfb['existing']['deny'][] = "{$pfb_alias},"; // Add Trailing ','
+ $pfbfolder = "{$pfb['denydir']}";
+ }
+ # Determine if 'Custom List' Needs Force Updating before next CRON Event.
+ if ($list['custom_update'] == "enabled") {
+ unlink_if_exists("{$pfbfolder}/{$pfb_alias}.txt");
+ # Uncheck 'Enabled' in List 'Custom_update' Setting
+ $config['installedpackages'][$ip_type]['config'][$count]['custom_update'] = "disabled";
+ }
+ }
+ }
+ }
+ }
+
+ # Collect all .txt file Names for each List Type
+ $list_types = array('match' => $pfb['matchdir'], 'permit' => $pfb['permitdir'], 'deny' => $pfb['denydir'], 'native' => $pfb['nativedir']);
+ foreach ($list_types as $type => $pfbfolder) {
+ $pfb_files = glob("$pfbfolder/*.txt");
+ foreach ($pfb_files as $pfb_list) {
+ $pfb_file = basename($pfb_list,".txt");
+ if ($type == "deny") {
+ $pfb['actual'][$type][] = "{$pfb_file},"; // Add Trailing ','
+ } else {
+ $pfb['actual'][$type][] = "{$pfb_file}";
+ }
+ }
+ }
+
+ # Flag to execute pfctl and Rules Ordering
+ $pfb['remove'] = FALSE;
+ # Execute Final Summary as a List was Removed
+ $pfb['summary'] = FALSE;
+
+ # Process to Remove Lists from Masterfile/DB Folder if they do not Exist
+ if (isset($pfb['existing'])) {
+ foreach ($pfb['existing'] as $pfb_exist) {
+ $existing_type = $pfb_exist['type'];
+ $pfbfolder = $pfb_exist['folder'];
+ foreach ($pfb['actual'] as $pfb_act) {
+ $actual_type = $pfb_act['type'];
+ if ($existing_type == $actual_type) {
+ switch ($existing_type) {
+ case "deny":
+ $results = array_diff($pfb_act, $pfb_exist);
+ $f_result = implode($results);
+ if ($f_result != "") {
+ $log = "[ Removing List(s) : {$f_result} ]\n";
+ pfb_logger("{$log}","1");
+ # Script to Remove un-associated Lists
+ exec ("{$pfb['script']} remove x x x {$f_result} >> {$pfb['log']} 2>&1");
+ $pfb['summary'] = TRUE;
+ $pfb['remove'] = TRUE;
+ }
+ break;
+ case "match":
+ case "permit":
+ case "native":
+ $results = array_diff($pfb_act, $pfb_exist);
+ # This variable ($f_result) used in next section below.
+ $f_result = implode($results);
+ if (!empty($results)) {
+ foreach ($results as $pfb_results) {
+ $log = "[ Removing List(s) : {$pfb_results} ]\n";
+ pfb_logger("{$log}","1");
+ unlink_if_exists("{$pfbfolder}/{$pfb_results}.txt");
+ }
+ $pfb['summary'] = TRUE;
+ $pfb['remove'] = TRUE;
+ }
+ break;
+ }
+
+ # Allow Rebuilding of Changed Aliase to purge 'SKIP' Lists (when pfBlockerNG is Enabled)
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($f_result != "" && $pfb['enable'] == "on") {
+ foreach ($results as $removed_header) {
+ if ($config['installedpackages'][$ip_type]['config'] != "" && $pfb['enable'] == "on") {
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ $alias = "pfB_" . preg_replace("/\W/","",$list['aliasname']);
+ if (is_array($list['row'])) {
+ foreach ($list['row'] as $row) {
+ $removed = rtrim($removed_header, ',');
+ if ($row['header'] == $removed) {
+ $pfb['summary'] = TRUE;
+ $pfb['remove'] = TRUE;
+ # Add Alias to Update Array
+ $pfb_alias_lists[] = "{$alias}";
+ $pfb_alias_lists_all[] = "{$alias}";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ##############################################
+ # Clear Match/Pass/ET/Original Files/Folders #
+ ##############################################
+
+ # When pfBlockerNG is Disabled and 'Keep Blocklists' is Disabled.
+ if ($pfb['enable'] == "" && $pfb['keep'] == "" && !$pfb['install']) {
+ $log = "\n Removing DB Files/Folders \n";
+ pfb_logger("{$log}","1");
+
+ unlink_if_exists("{$pfb['dbdir']}/masterfile");
+ unlink_if_exists("{$pfb['dbdir']}/mastercat");
+ unlink_if_exists("{$pfb['supptxt']}");
+ rmdir_recursive("{$pfb['origdir']}");
+ rmdir_recursive("{$pfb['matchdir']}");
+ rmdir_recursive("{$pfb['permitdir']}");
+ rmdir_recursive("{$pfb['denydir']}");
+ rmdir_recursive("{$pfb['nativedir']}");
+ rmdir_recursive("{$pfb['etdir']}");
+ }
+
+
+ #############################################
+ # Create Suppression Txt File #
+ #############################################
+
+ if ($pfb['enable'] == "on" && $pfb['supp'] == "on")
+ pfb_create_suppression_file();
+
+
+ #############################################
+ # Assign Countries #
+ #############################################
+
+ foreach ($continents as $continent => $pfb_alias) {
+ if (is_array($config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config'])) {
+ $continent_config = $config['installedpackages']['pfblockerng' . strtolower(preg_replace('/ /','',$continent))]['config'][0];
+ if ($continent_config['action'] != "Disabled" && $pfb['enable'] == "on") {
+
+ # Determine Folder Location for Alias (return array $pfbarr)
+ pfb_determine_list_detail($continent_config['action']);
+ $pfb['skip'] = $pfbarr['skip'];
+ $pfb_descr = $pfbarr['descr'];
+ $pfbfolder = $pfbarr['folder'];
+
+ // Determine if Continent Lists require Action (IPv4 and IPv6)
+ $cont_type = array ("countries4" => "_v4", "countries6" => "_v6");
+ foreach ($cont_type as $c_type => $vtype) {
+
+ $continent = "";
+ if ($continent_config[$c_type] != "") {
+
+ // Collect Selected ISO Country Files
+ foreach (explode(",", $continent_config[$c_type]) as $iso) {
+ if ($iso != "" && file_exists($pfb['ccdir'] .'/' . $iso . $vtype . '.txt')) {
+ $continent .= file_get_contents ($pfb['ccdir'] . '/' . $iso . $vtype . '.txt');
+ }
+ }
+
+ if (file_exists($pfb['origdir'] . '/' . $pfb_alias . $vtype . '.orig'))
+ $continent_existing = preg_replace('/\s/', '', file ($pfb['origdir'] . '/' . $pfb_alias . $vtype . '.orig'));
+
+ // Collect New Continent Data for comparison. Cleanup Array for Comparison
+ $continent_new = preg_split ('/$\R?^/m', $continent);
+ $line = count ( $continent_new ) - 1;
+ $match = $continent_new[$line];
+ $continent_new[$line] = rtrim($match, "\n");
+
+ # Check if pfBlockerNG pfctl Continent Tables are Empty (pfBlockerNG was Disabled w/ "keep", then Re-enabled)
+ $pfctlck = exec ("/sbin/pfctl -vvsTables | grep -A1 {$pfb_alias}{$vtype} | awk '/Addresses/ {s+=$2}; END {print s}'");
+ if (empty($pfctlck) && file_exists($pfbfolder . '/' . $pfb_alias . $vtype . '.txt')) {
+ $file_cont = file_get_contents($pfbfolder . '/' . $pfb_alias . $vtype . '.txt');
+ @file_put_contents($pfb['aliasdir'] . '/' . $pfb_alias . $vtype . '.txt',$file_cont, LOCK_EX);
+ # PFCTL - Update Only Aliases that have been updated. ('Reputation' Disabled)
+ $pfb_alias_lists[] = "{$pfb_alias}{$vtype}";
+ }
+
+ # Collect Active Alias Lists (Used for pfctl Update when 'Reputation' is enabled).
+ $pfb_alias_lists_all[] = "{$pfb_alias}{$vtype}";
+
+ // Compare Existing (Original File) and New Continent Data
+ if ($continent_new === $continent_existing && !empty($pfctlck) && file_exists($pfbfolder . '/' . $pfb_alias . $vtype . '.txt') && $pfb['reuse'] == "") {
+ # Format Log into clean Tab Spaces
+ $string_final = "{$pfb_alias}{$vtype}";
+ if (strlen($string_final) > 10) {
+ $log_tab = "\t";
+ } else {
+ $log_tab = "\t\t";
+ }
+
+ if (!$pfb['save']) {
+ $log = "\n[ {$pfb_alias}{$vtype} ] {$log_tab} exists, Reloading File [ NOW ]\n";
+ pfb_logger("{$log}","1");
+ }
+ } else {
+ // Do not proceed with Changes on User 'Save'
+ if (!$pfb['save']) {
+ $log = "\n[ {$pfb_alias}{$vtype} ] {$log_tab} Changes Found... Updating \n";
+ pfb_logger("{$log}","1");
+
+ # Test to Skip d-dup and p-dup functions when changes are found.
+ $pfb['dupcheck'] = TRUE;
+
+ $pfb_alias_lists[] = "{$pfb_alias}{$vtype}";
+
+ // Script to call Duplication Check Process only on IPv4
+ if ($pfb['dup'] == "on" && $pfb['skip'] && $vtype == "_v4") {
+ // Copy Continent Data to 'lists' folder for duplication processing
+ @file_put_contents($pfb['origdir'] . '/' . $pfb_alias . $vtype . '.orig',$continent, LOCK_EX);
+ @file_put_contents($pfb['denydir'] . '/' . $pfb_alias . $vtype . '.txt',$continent, LOCK_EX);
+ exec ("{$pfb['script']} continent {$pfb_alias}{$vtype} >> {$pfb['log']} 2>&1");
+ $continent = file_get_contents($pfbfolder . '/' . $pfb_alias . $vtype . '.txt');
+ @file_put_contents($pfb['aliasdir'] . '/' . $pfb_alias . $vtype . '.txt',$continent, LOCK_EX);
+ } else {
+ @file_put_contents($pfbfolder . '/' . $pfb_alias . $vtype . '.txt',$continent, LOCK_EX);
+ @file_put_contents($pfb['origdir'] . '/' . $pfb_alias . $vtype . '.orig',$continent, LOCK_EX);
+ @file_put_contents($pfb['aliasdir'] . '/' . $pfb_alias . $vtype . '.txt',$continent, LOCK_EX);
+ }
+
+ # Check if File Exists and is >0 in Size and Save alias file
+ $file_chk = "0";
+ $cont_chk = "{$pfbfolder}/{$pfb_alias}{$vtype}.txt";
+ if (file_exists($cont_chk) && @filesize($cont_chk) >0)
+ $file_chk = exec ("/usr/bin/grep -cv '^#\|^$' {$cont_chk}");
+
+ if ($file_chk == "0" || $file_chk == "1") {
+ $new_file = "1.1.1.1\n";
+ @file_put_contents($pfbfolder . '/' . $pfb_alias . $vtype . '.txt', $new_file, LOCK_EX);
+ @file_put_contents($pfb['aliasdir'] . "/" . $pfb_alias . $vtype . ".txt", $new_file, LOCK_EX);
+ $log = "[ {$pfb_alias}{$vtype} ] Found no Unique IPs, Adding '1.1.1.1' to avoid Empty File\n";
+ pfb_logger("{$log}","1");
+ }
+ }
+ }
+
+
+ if (file_exists($pfbfolder . '/' . $pfb_alias . $vtype . '.txt')) {
+ #Create alias config
+ $new_aliases_list[] = "{$pfb_alias}{$vtype}";
+
+ $pfb_contlog = $continent_config['aliaslog'];
+
+ $new_aliases[] = array( "name" => "{$pfb_alias}{$vtype}",
+ "url" => "{$pfb['weblocal']}?pfb={$pfb_alias}{$vtype}",
+ "updatefreq" => "32",
+ "address" => "",
+ "descr" => "pfBlockerNG {$vtype} {$pfb_descr} Country Alias",
+ "type" => "urltable",
+ "detail" => "DO NOT EDIT THIS ALIAS"
+ );
+
+ #Create rule if action permits
+ switch ($continent_config['action']) {
+ case "Deny_Both":
+ case "Deny_Outbound":
+ $rule = $base_rule;
+ $rule['type'] = "{$pfb['deny_action_outbound']}";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr']= "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array("any" => "");
+ $rule['destination'] = array ("address" => "{$pfb_alias}{$vtype}");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $deny_outbound[] = $rule;
+ if ($continent_config['action'] != "Deny_Both")
+ break;
+ case "Deny_Inbound":
+ $rule = $base_rule;
+ $rule['type'] = "{$pfb['deny_action_inbound']}";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array("address" => "{$pfb_alias}{$vtype}");
+ $rule['destination'] = array ("any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $deny_inbound[] = $rule;
+ break;
+ case "Permit_Both":
+ case "Permit_Outbound":
+ $rule = $base_rule;
+ $rule['type'] = "pass";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array ("any" => "");
+ $rule['destination'] = array("address" => "{$pfb_alias}{$vtype}");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $permit_outbound[] = $rule;
+ if ($continent_config['action'] != "Permit_Both")
+ break;
+ case "Permit_Inbound":
+ $rule = $base_rule;
+ $rule['type'] = "pass";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array("address"=> "{$pfb_alias}{$vtype}");
+ $rule['destination'] = array ("any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $permit_inbound[] = $rule;
+ break;
+ case "Match_Both":
+ case "Match_Outbound":
+ $rule = $base_rule_float;
+ $rule['type'] = "match";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array ("any" => "");
+ $rule['destination'] = array ("address" => "{$pfb_alias}{$vtype}");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $match_outbound[] = $rule;
+ if ($list['action'] != "Match_Both")
+ break;
+ case "Match_Inbound":
+ $rule = $base_rule_float;
+ $rule['type'] = "match";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$pfb_alias}{$vtype}{$pfb['suffix']}";
+ $rule['source'] = array ("address" => "{$pfb_alias}{$vtype}");
+ $rule['destination'] = array ( "any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $pfb_contlog == "enabled")
+ $rule['log'] = "";
+ $match_inbound[] = $rule;
+ break;
+ }
+ } else {
+ #unlink continent list if any
+ unlink_if_exists($pfb['aliasdir'] . '/' . $pfb_alias . $vtype . '.txt');
+ }
+ }
+ }
+ }
+ #mark pfctl aliastable for cleanup
+ if (!in_array($pfb_alias, $aliases_list)) {
+ $aliases_list[] = "{$pfb_alias}{$vtype}";
+ }
+ }
+ }
+ # UNSET variables
+ unset ($continent, $continent_existing, $continent_new);
+
+ #############################################
+ # Download and Collect IPv4/IPv6 lists #
+ #############################################
+
+ # IPv4 REGEX Definitions
+ $pfb['range'] = '/((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))-((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/';
+ $pfb['block'] = '/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[ 0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.([0]{1})\s+/';
+ $pfb['cidr'] = '/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)?\/[0-9]{2}/';
+ $pfb['single'] = '/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\s+/';
+ $pfb['s_html'] = '/(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/';
+
+ # IPv4 preg_replace Regex Filter array
+ $pfb_ipreg = array();
+ $pfb_ipreg[0] = '/\b0+(?=\d)/'; # Remove any Leading Zeros in each Octet
+ $pfb_ipreg[1] = '/\s/'; # Remove any Whitespaces
+ $pfb_ipreg[2] = '/127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/'; # Remove any Loopback Addresses 127/8
+ $pfb_ipreg[3] = '/0\.0\.0\.0/'; # Remove 0.0.0.0
+
+ # IPv6 REGEX Definitions -- ** Still Needs some Adjustment on Regex Definition for IPv6 **
+ # https://mebsd.com/coding-snipits/php-regex-ipv6-with-preg_match.html
+ $pattern1 = '([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}';
+ $pattern2 = '([A-Fa-f0-9]{1,4}::([A-Fa-f0-9]{1,4}:){0,5}[A-Fa-f0-9]{1,4}';
+ $pattern3 = '([A-Fa-f0-9]{1,4}:){2}:([A-Fa-f0-9]{1,4}:){0,4}[A-Fa-f0-9]{1,4}';
+ $pattern4 = '([A-Fa-f0-9]{1,4}:){3}:([A-Fa-f0-9]{1,4}:){0,3}[A-Fa-f0-9]{1,4}';
+ $pattern5 = '([A-Fa-f0-9]{1,4}:){4}:([A-Fa-f0-9]{1,4}:){0,2}[A-Fa-f0-9]{1,4}';
+ $pattern6 = '([A-Fa-f0-9]{1,4}:){5}:([A-Fa-f0-9]{1,4}:){0,1}[A-Fa-f0-9]{1,4}';
+ $pattern7 = '([A-Fa-f0-9]{1,4}:){6}:[A-Fa-f0-9]{1,4}';
+ $pfb['ipv6'] = "/^($pattern1)$|^($pattern2)$|^($pattern3)$|^($pattern4)$|^($pattern5)$|^($pattern6)$|^($pattern7)$/";
+
+ $pfb['supp_update'] = FALSE;
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($config['installedpackages'][$ip_type]['config'] != "") {
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ if ($list['action'] != "Disabled" && $pfb['enable'] == "on" && !$pfb['save'] && is_array($list['row'])) {
+ # Capture Alias Name
+ $alias = "pfB_" . preg_replace("/\W/","",$list['aliasname']);
+ foreach ($list['row'] as $row) {
+ if ($row['url'] != "" && $row['state'] != "Disabled") {
+
+ # Determine Folder Location for Alias (return array $pfbarr)
+ pfb_determine_list_detail($list['action']);
+ $pfb['skip'] = $pfbarr['skip'];
+ $pfbfolder = $pfbarr['folder'];
+
+ if ($vtype == "_v4") {
+ $header_url = "{$row['header']}";
+ } else {
+ $header_url = "{$row['header']}_v6";
+ }
+
+ # Format Log into clean Tab Spaces
+ if (strlen($header_url) > 10) {
+ $log_tab = "\t";
+ } else {
+ $log_tab = "\t\t";
+ }
+
+ // Empty Header Field Validation Check
+ if (empty($header_url) || preg_match("/\W/",$header_url)) {
+ $log = "\n [ {$row['url']} ]\n ** TERMINATED - Header contains Blank/International/Special or Spaces\n";
+ pfb_logger("{$log}","2");
+ continue;
+ }
+
+ # Collect Active Alias List (Used for pfctl Update when 'Reputation' is enabled.
+ $pfb_alias_lists_all[] = "{$alias}";
+
+ if (file_exists($pfbfolder . '/' . $header_url . '.txt') && $pfb['reuse'] == "") {
+ if ($row['state'] == "Hold") {
+ $log = "\n[ {$header_url} ] {$log_tab} Static Hold [ NOW ]\n";
+ } else {
+ $log = "\n[ {$header_url} ] {$log_tab} exists, Reloading File [ NOW ]\n";
+ }
+ pfb_logger("{$log}","1");
+ } else {
+ if ($pfb['reuse'] == "on" && file_exists($pfb['origdir'] . '/' . $header_url . '.orig')) {
+ $log = "\n[ {$header_url} ] {$log_tab} Using Previously Downloaded File [ NOW ]\n";
+ } else {
+ $log = "\n[ {$header_url} ] {$log_tab} Downloading New File [ NOW ]\n";
+ }
+ pfb_logger("{$log}","1");
+
+ # Perform Remote URL Date/Time Stamp checks
+ $host = @parse_url($row['url']);
+ $list_url = "{$row['url']}";
+ if ($row['format'] != "rsync" || $row['format'] != "html") {
+ if ($host['host'] == "127.0.0.1" || $host['host'] == $pfb['iplocal'] || empty($host['host'])) {
+ $remote_tds = "local";
+ } else {
+ $remote_tds = @implode(preg_grep("/Last-Modified/", get_headers($list_url)));
+ $remote_tds = preg_replace("/^Last-Modified: /","", $remote_tds);
+ }
+ }
+
+ $url_list = array();
+ if ($row['format'] == "gz" || $row['format'] == "gz_2") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.gz";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_gz = "{$row['url']}";
+ $file_gz = @file_get_contents($url_gz);
+ @file_put_contents($file_dwn, $file_gz, LOCK_EX);
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ $url_list = @gzfile($file_dwn);
+ }
+
+ # IBlock Large Files mixed with IPs and Domains. PHP mem of 256M can't handle very large Files.
+ if ($row['format'] == "gz_lg") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.gz";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_gz = "{$row['url']}";
+ $file_gz = @file_get_contents($url_gz);
+ @file_put_contents($file_dwn, $file_gz, LOCK_EX);
+ exec ("/usr/bin/gunzip -c {$file_dwn} | /usr/bin/sed 's/^.*://' | /usr/bin/grep -v '[a-zA-Z]\|^$\|^#' > {$pfb['origdir']}/{$header_url}.orig");
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ $url_list = @file($pfb['origdir'] . '/' . $header_url . '.orig');
+ }
+
+ elseif ($row['format'] == "zip") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.zip";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_zip = "{$row['url']}";
+ if (!$file_zip = @file_get_contents($url_zip)) {
+ $error = error_get_last();
+ $log = "\n [ {$header_url} ] {$error['message']} \n";
+ pfb_logger("{$log}","2");
+ } else {
+ @file_put_contents($file_dwn, $file_zip, LOCK_EX);
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ }
+ $zip_out = "{$pfb['origdir']}/{$header_url}.orig";
+ exec ("/usr/bin/tar -xOf {$file_dwn} | tr ',' '\n' > {$zip_out}");
+ $url_list = @file($zip_out);
+ }
+
+ elseif ($row['format'] == "et") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.gz";
+ # Script to Call ET IQRISK Process
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_et = "{$row['url']}";
+ $file_et = @file_get_contents($url_et);
+ @file_put_contents($file_dwn, $file_et, LOCK_EX);
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ exec ("{$pfb['script']} et {$header_url} x x x x x {$pfb['etblock']} {$pfb['etmatch']} >> {$pfb['log']} 2>&1");
+ $url_list = @file($pfb['origdir'] . '/' . $header_url . '.orig');
+ }
+
+ elseif ($row['format'] == "xlsx") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.zip";
+ # Script to Call XLSX Process
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_xlsx = "{$row['url']}";
+ $file_xlsx = @file_get_contents($url_xlsx);
+ @file_put_contents($file_dwn, $file_xlsx, LOCK_EX);
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ exec ("{$pfb['script']} xlsx {$header_url} >> {$pfb['log']} 2>&1");
+ $url_list = @file($pfb['origdir'] . '/' . $header_url . '.orig');
+ }
+
+ elseif ($row['format'] == "txt") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.orig";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ $url_list = @file($file_dwn);
+ } else {
+ $url_other = @file($row['url']);
+ $url_list = $url_other;
+ @file_put_contents($file_dwn, $url_other, LOCK_EX);
+ if ($remote_tds == "local")
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($file_dwn));
+ $remote_stamp = strtotime($remote_tds);
+ if (!empty($remote_stamp) && file_exists($file_dwn))
+ touch ($file_dwn, $remote_stamp);
+ }
+ }
+
+ elseif ($row['format'] == "html" || $row['format'] == "block") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.raw";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ $return = 0;
+ } else {
+ $url_html = "{$row['url']}";
+ exec ("/usr/bin/fetch -v -o {$file_dwn} -T 20 {$url_html}",$output,$return);
+ }
+ if ($return == 0)
+ $url_list = @file($file_dwn);
+ }
+
+ elseif ($row['format'] == "rsync") {
+ $file_dwn = "{$pfb['origdir']}/{$header_url}.orig";
+ if ($pfb['reuse'] == "on" && file_exists($file_dwn)) {
+ # File Exists/Reuse
+ } else {
+ $url_rsync = "{$row['url']}";
+ exec ("/usr/local/bin/rsync --timeout=5 {$url_rsync} {$file_dwn}");
+ }
+ $url_list = @file($file_dwn);
+ }
+
+ #extract range lists
+ $new_file = "";
+ if (!empty($url_list)) {
+ if ($row['format'] == "gz" && $vtype == "_v4") {
+ foreach ($url_list as $line) {
+ # Network range 192.168.0.0-192.168.0.254
+ if (preg_match($pfb['range'],$line,$matches)) {
+ $a_cidr = ip_range_to_subnet_array_temp2($matches[1],$matches[2]);
+ if (!empty($a_cidr)) {
+ foreach ($a_cidr as $cidr) {
+ $new_file .= preg_replace($pfb_ipreg,'',$cidr) . "\n";
+ }
+ }
+ }
+ }
+ }
+
+ elseif ($row['format'] == "block" && $vtype == "_v4") {
+ foreach ($url_list as $line) {
+ # Block Type '218.77.79.0 218.77.79.255 24'
+ if (preg_match($pfb['block'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "/24\n";
+ }
+ }
+ }
+
+ elseif ($row['format'] == "html" && $vtype == "_v4") {
+ foreach ($url_list as $line) {
+ # CIDR format 192.168.0.0/16
+ if (preg_match($pfb['cidr'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ # Single ip addresses
+ elseif (preg_match($pfb['s_html'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ }
+ }
+
+ elseif ($vtype == "_v6") {
+ foreach ($url_list as $line) {
+ # IPv6 Regex Match
+ if (preg_match($pfb['ipv6'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ }
+ }
+
+ else {
+ foreach ($url_list as $line) {
+ # CIDR format 192.168.0.0/16
+ if (preg_match($pfb['cidr'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ # Single ip addresses
+ elseif (preg_match($pfb['single'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ }
+ }
+ }
+
+ # Check to see if Blocklist actually Failed Download or has no IPs listed.
+ if ($row['format'] == "html" || $row['format'] == "block") {
+ $url_chk = $file_dwn;
+ } else {
+ $url_chk = "{$pfb['origdir']}/{$header_url}.orig";
+ }
+
+ # Check if File Exists and is >0 in Size
+ $file_chk = "";
+ if (file_exists($url_chk) && @filesize($url_chk) >0)
+ $file_chk = exec ("/usr/bin/grep -cv '^#\|^$' {$url_chk}");
+
+ if ($file_chk == "0") {
+ $new_file = "1.1.1.1\n";
+ $url_other = $new_file;
+ $log = "[ {$header_url} ] Found no IPs, Adding '1.1.1.1' to avoid Download FAIL\n";
+ pfb_logger("{$log}","1");
+ }
+
+ if ($new_file != "") {
+ if ($row['format'] == "gz" || $row['format'] == "gz_2" || $row['format'] == "html" || $row['format'] == "block") {
+ # Re-Save these formats as original file
+ $url_other = $new_file;
+ @file_put_contents($pfb['origdir'] . '/' . $header_url . '.orig',$url_other, LOCK_EX);
+ }
+
+ # Save List to '.txt' format in appropriate Folder
+ @file_put_contents($pfbfolder . '/' .$header_url . '.txt',$new_file, LOCK_EX);
+
+ if ($pfb['rep'] == "on" && $pfb['skip'] && $vtype == "_v4") {
+ # Script to Call p24 Process
+ exec ("{$pfb['script']} p24 {$header_url} {$pfb['max']} {$pfb['dedup']} {$pfb['ccexclude']} {$pfb['ccwhite']} {$pfb['ccblack']} >> {$pfb['log']} 2>&1");
+ }
+
+ if ($pfb['dup'] == "on" && $pfb['skip'] && $vtype == "_v4") {
+ # Script to call Duplication Check Process
+ exec ("{$pfb['script']} duplicate {$header_url} >> {$pfb['log']} 2>&1");
+ }
+
+ # PFCTL - Update Only Aliases that have been updated only.
+ $pfb_alias_lists[] = "{$alias}";
+ # Launch d-dup and p-dup functions when changes are found.
+ if ($pfb['skip'] && $vtype == "_v4")
+ $pfb['dupcheck'] = TRUE;
+ # Enable Suppression Process due to Updates
+ if ($pfb['supp'] == "on" && $vtype == "_v4")
+ $pfb['supp_update'] = TRUE;
+
+ } else {
+ # Log FAILED Downloads and Check if Firewall or Snort/Suricata is Blocking Host
+ $log = "\n [ {$alias} {$header_url} ] Download FAIL [ NOW ]\n";
+ pfb_logger("{$log}","2");
+
+ # Rebuild Previous List File from contents of Masterfile
+ if ($pfb['skip'] && $vtype == "_v4") {
+ # Search with trailing Whitespace to match exact Header in Masterfile
+ $header_url2 = $header_url . "[[:space:]]";
+ $file_chk = exec ("/usr/bin/grep {$header_url2} {$pfb['master']} | grep -c ^");
+
+ if (!file_exists($pfbfolder . '/' . $header_url . '.txt') && @$file_chk > 0 && file_exists($pfb['master'])) {
+ $log = " [ {$alias} {$header_url} ] Found: {$file_chk} Line(s), Restoring previous List from Master \n";
+ pfb_logger("{$log}","2");
+ exec ("/usr/bin/grep {$header_url2} {$pfb['master']} | cut -d' ' -f2 > {$pfbfolder}/{$header_url}.txt");
+ }
+ }
+ # A "Space" string Variable
+ $sp = " ";
+ $ip = @gethostbyname($host['host']);
+ $ip2 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", "\"^$1\.$2\.$3\.\"", $ip);
+
+ # Only Perform these Checks if they are not "localfiles"
+ if ($host['host'] == "127.0.0.1" || $host['host'] == $pfb['iplocal'] || empty($host['host'])) {
+ $log = " [ {$alias} {$header_url} ] Local File Failure \n";
+ pfb_logger("{$log}","2");
+ } else {
+ # only perform these steps if an 'IP' is found.
+ if (!empty($ip)) {
+ // Query for Exact IP Match
+ $result_b1 = array();
+ $pfb_b1 = exec ("/usr/bin/grep ^{$ip} {$pfbfolder}/*", $result_b1);
+ // Query for First Three IP Octet Matches
+ $result_b2 = array();
+ $pfb_b2 = exec ("/usr/bin/grep {$ip2} {$pfbfolder}/*", $result_b2);
+ // Query Snort/Suricata snort2c IP Block Table
+ $snort_pfb = exec("/sbin/pfctl -t snort2c -T show | grep {$ip}");
+
+ # If an exact IP Match is not found report any First Three IP Octets.
+ if (!empty($result_b1)) {
+ $final_b1 = implode("\n ", $result_b1);
+ $log = " [ {$alias} {$header_url}, {$ip} ] Firewall IP Block Found in : \n{$sp}{$final_b1}\n";
+ pfb_logger("{$log}","2");
+ } else {
+ if (!empty($result_b2)) {
+ $final_b2 = implode("\n ", $result_b2);
+ $log = " [ {$alias} {$header_url}, {$ip} ] *Potential* Firewall IP Block Found in : \n{$sp}{$final_b2}\n";
+ pfb_logger("{$log}","2");
+ }
+ }
+ if (!empty($snort_pfb)) {
+ $log = " [ {$alias} {$header_url}, {$ip} ] snort2c IP Block Found in : [ {$snort_pfb} ]\n";
+ pfb_logger("{$log}","2");
+ }
+ } else {
+ $log = " [ {$alias} {$header_url} ] No host IP found \n";
+ pfb_logger("{$log}","2");
+ }
+ }
+ }
+ # UNSET variables
+ unset ($file_gz,$file_zip,$file_et,$file_xlsx,$url_other,$url_list);
+ }
+ }
+ }
+ #check custom network list
+ if (pfbng_text_area_decode($list['custom']) != "") {
+
+ if ($vtype == "_v4") {
+ $aliascustom = "{$list['aliasname']}_custom";
+ } else {
+ $aliascustom = "{$list['aliasname']}_custom_v6";
+ }
+
+ # Format Log into clean Tab Spaces
+ if (strlen($aliascustom) > 10) {
+ $log_tab = "\t";
+ } else {
+ $log_tab = "\t\t";
+ }
+
+ # Collect Active Alias List (Used for pfctl Update when 'Reputation' is enabled.
+ $pfb_alias_lists_all[] = "{$alias}";
+
+ # Determine Folder Location for Alias (return array $pfbarr)
+ pfb_determine_list_detail($list['action']);
+ $pfb['skip'] = $pfbarr['skip'];
+ $pfbfolder = $pfbarr['folder'];
+
+ if (file_exists($pfbfolder . '/' . $aliascustom . '.txt') && $pfb['reuse'] == "") {
+ $log = "\n[ {$aliascustom} ] {$log_tab} exists, Reloading File [ NOW ]\n";
+ pfb_logger("{$log}","1");
+ } else {
+ $url_list = array();
+ $log = "\n[ {$aliascustom} ] {$log_tab} Loading Custom File [ NOW ]\n";
+ pfb_logger("{$log}","1");
+
+ $custom_list = pfbng_text_area_decode($list['custom']) . "\n";
+ @file_put_contents($pfb['origdir'] . '/' . $aliascustom . '.orig', $custom_list, LOCK_EX);
+ $url_list = @file($pfb['origdir'] . '/' . $aliascustom . '.orig');
+
+ $new_file = "";
+ if (!empty($url_list)) {
+ foreach ($url_list as $line) {
+ if ($vtype == "_v4") {
+ # CIDR format 192.168.0.0/16
+ if (preg_match($pfb['cidr'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ # Single ip addresses
+ elseif (preg_match($pfb['s_html'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ # Network range 192.168.0.0-192.168.0.254
+ elseif (preg_match($pfb['range'],$line,$matches)) {
+ $a_cidr = ip_range_to_subnet_array_temp2($matches[1],$matches[2]);
+ if (!empty($a_cidr)) {
+ foreach ($a_cidr as $cidr) {
+ $new_file .= preg_replace($pfb_ipreg, '',$cidr) . "\n";
+ }
+ }
+ }
+ } else {
+ # IPv6 Regex
+ if (preg_match($pfb['ipv6'],$line,$matches)) {
+ $new_file .= preg_replace($pfb_ipreg, '',$matches[0]) . "\n";
+ }
+ }
+ }
+
+ }
+ if ($new_file != "") {
+ # PFCTL - Collect Only Aliases that have been updated only.
+ $pfb_alias_lists[] = "{$alias}";
+ # Collect Updated lists for Suppression Process
+ @file_put_contents($pfbfolder . '/'. $aliascustom . '.txt',$new_file, LOCK_EX);
+ # Enable Suppression Process due to Updates
+ if ($pfb['supp'] == "on" && $vtype == "_v4")
+ $pfb['supp_update'] = TRUE;
+ if ($pfb['rep'] == "on" && $pfb['skip'] && $vtype == "_v4") {
+ # Script to Call p24 Process
+ exec ("{$pfb['script']} p24 {$aliascustom} {$pfb['max']} {$pfb['dedup']} {$pfb['ccexclude']} {$pfb['ccwhite']} {$pfb['ccblack']} >> {$pfb['log']} 2>&1");
+ }
+ if ($pfb['dup'] == "on" && $pfb['skip'] && $vtype == "_v4") {
+ # Script to call Duplication Check Process
+ exec ("{$pfb['script']} duplicate {$aliascustom} >> {$pfb['log']} 2>&1");
+ }
+ } else {
+ $log = "[ {$aliascustom} ] Custom List Error ]\n";
+ pfb_logger("{$log}","1");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ #############################################
+ # REPUTATION PROCESSES #
+ #############################################
+
+ # IP Reputation processes (pdup and ddup)
+ if ($pfb['pdup'] == "on" && $pfb['dupcheck'] && !$pfb['save'] && $pfb['enable'] == "on") {
+ # Script to run pdup process
+ exec ("{$pfb['script']} pdup x {$pfb['pmax']} >> {$pfb['log']} 2>&1");
+ }
+ if ($pfb['dedup'] == "on" && $pfb['dupcheck'] && !$pfb['save'] && $pfb['enable'] == "on") {
+ # Script to run dedup process
+ exec ("{$pfb['script']} dedup x {$pfb['dmax']} {$pfb['dedup']} {$pfb['ccexclude']} {$pfb['ccwhite']} {$pfb['ccblack']} >> {$pfb['log']} 2>&1");
+ }
+
+ #############################################
+ # CONFIGURE ALIASES #
+ #############################################
+
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($config['installedpackages'][$ip_type]['config'] != "" && $pfb['enable'] == "on") {
+ $runonce = 0;
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ $alias = "pfB_" . preg_replace("/\W/","",$list['aliasname']);
+
+ # Determine Folder Location for Alias (return array $pfbarr)
+ pfb_determine_list_detail($list['action']);
+ $pfb['skip'] = $pfbarr['skip'];
+ $pfb_descr = $pfbarr['descr'];
+ $pfbfolder = $pfbarr['folder'];
+
+ // Re-Save Only Aliases that have been updated only.
+ // When 'Reputation' is used, all Aliases need to be Updated.
+ $final_alias = array();
+ if ($pfb['dedup'] == "on" || $pfb['pdup'] == "on") {
+ if (!empty($pfb_alias_lists_all))
+ $final_alias = array_unique($pfb_alias_lists_all);
+ } else {
+ if (!empty($pfb_alias_lists))
+ $final_alias = array_unique($pfb_alias_lists);
+ }
+
+ if ($list['action'] != "Disabled") {
+ #remove empty lists files if any
+ if (is_array($list['row'])) {
+ $update = 0;
+ ${$alias} = "";
+ foreach ($list['row'] as $row) {
+ if ($row['url'] != "" && $row['state'] != "Disabled") {
+ if ($vtype == "_v4") {
+ $header_url = "{$row['header']}";
+ } else {
+ $header_url = "{$row['header']}_v6";
+ }
+ $pfctlck = exec ("/sbin/pfctl -vvsTables | grep -A1 {$alias} | awk '/Addresses/ {s+=$2}; END {print s}'");
+
+ # Update Alias if List File Exists and its been updated or if the Alias URL Table is Empty.
+ if (file_exists($pfbfolder . "/" . $header_url . ".txt") && in_array($alias, $final_alias) || file_exists($pfbfolder . "/" . $header_url . ".txt") && empty($pfctlck)) {
+ # Script to run Suppression process (Print Header Only)
+ if ($pfb['supp'] == "on" && $vtype == "_v4" && $runonce == 0 && $pfb['supp_update']) {
+ exec ("{$pfb['script']} suppress x x x suppressheader >> {$pfb['log']} 2>&1");
+ $runonce++;
+ }
+ # Script to run Suppression Process (Body)
+ if ($pfb['supp'] == "on" && $vtype == "_v4" && $pfb['supp_update']) {
+ if ($pfb['dup'] == "on" || !$pfb['skip']) {
+ # Execute if Duplication Process is Enabled or List is Permit or Match
+ exec ("{$pfb['script']} suppress x x x {$header_url}\|{$pfbfolder}/ >> {$pfb['log']} 2>&1");
+ } else {
+ # Execute if Duplication Process is Disabled
+ exec ("{$pfb['script']} suppress x x off {$header_url}\|{$pfbfolder}/ >> {$pfb['log']} 2>&1");
+ }
+ }
+ ${$alias} .= file_get_contents($pfbfolder . '/' . $header_url . '.txt');
+ $update++;
+ }
+ }
+ }
+ }
+
+ #check custom network list
+ if ($vtype == "_v4") {
+ $aliasname = "{$list['aliasname']}_custom";
+ } else {
+ $aliasname = "{$list['aliasname']}_custom_v6";
+ }
+
+ # Update Alias if List File Exists and its been updated or if the Alias URL Table is Empty.
+ $pfctlck = exec ("/sbin/pfctl -vvsTables | grep -A1 {$alias} | awk '/Addresses/ {s+=$2}; END {print s}'");
+
+ if (pfbng_text_area_decode($list['custom']) != "") {
+ if (file_exists($pfbfolder . "/" . $aliasname . ".txt") && in_array($alias, $final_alias) || file_exists($pfbfolder . "/" . $aliasname . ".txt") && empty($pfctlck)) {
+ ${$alias} .= file_get_contents($pfbfolder . '/' . $aliasname . '.txt');
+ $update++;
+ }
+ }
+ # Determine Validity of Alias URL Tables/Rules. ie: Don't create Empty URL Tables or Aliases
+ if (${$alias} == "" && empty($pfctlck)) {
+ unlink_if_exists($pfb['aliasdir'] . '/' . $alias. '.txt');
+ } else {
+ // Save Only Aliases that have been updated.
+ if ($update > 0) {
+ @file_put_contents($pfb['aliasdir'] . '/' . $alias. '.txt',${$alias}, LOCK_EX);
+ }
+
+ $alias_log = $list['aliaslog'];
+ #create alias
+ $new_aliases_list[] = "{$alias}";
+
+ $new_aliases[] = array( "name" => "{$alias}",
+ "url" => "{$pfb['weblocal']}?pfb={$alias}",
+ "updatefreq" => "32",
+ "address" => "",
+ "descr" => "pfBlockerNG {$pfb_descr} List Alias",
+ "type" => "urltable",
+ "detail" => "DO NOT EDIT THIS ALIAS"
+ );
+
+ #Create rule if action permits
+ switch ($list['action']) {
+ case "Deny_Both":
+ case "Deny_Outbound":
+ $rule = $base_rule;
+ $rule['type'] = "{$pfb['deny_action_outbound']}";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array ("any" => "");
+ $rule['destination'] = array ("address" => "{$alias}");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $deny_outbound[] = $rule;
+ if ($list['action'] != "Deny_Both")
+ break;
+ case "Deny_Inbound":
+ $rule = $base_rule;
+ $rule['type'] = "{$pfb['deny_action_inbound']}";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array("address" => "{$alias}");
+ $rule['destination'] = array ("any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $deny_inbound[] = $rule;
+ break;
+ case "Permit_Both":
+ case "Permit_Outbound":
+ $rule = $base_rule;
+ $rule['type'] = "pass";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array ("any" => "");
+ $rule['destination'] = array ("address" => "{$alias}");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $permit_outbound[] = $rule;
+ if ($list['action'] != "Permit_Both")
+ break;
+ case "Permit_Inbound":
+ $rule = $base_rule;
+ $rule['type'] = "pass";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ if ($pfb['float'] == "on")
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array ("address" => "{$alias}");
+ $rule['destination'] = array ("any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $permit_inbound[] = $rule;
+ break;
+ case "Match_Both":
+ case "Match_Outbound":
+ $rule = $base_rule_float;
+ $rule['type'] = "match";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array ("any" => "");
+ $rule['destination'] = array ("address" => "{$alias}");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $match_outbound[] = $rule;
+ if ($list['action'] != "Match_Both")
+ break;
+ case "Match_Inbound":
+ $rule = $base_rule_float;
+ $rule['type'] = "match";
+ if ($vtype == "_v6")
+ $rule['ipprotocol'] = "inet6";
+ $rule['direction'] = "any";
+ $rule['descr'] = "{$alias}{$pfb['suffix']}";
+ $rule['source'] = array ("address" => "{$alias}");
+ $rule['destination'] = array ("any" => "");
+ if ($pfb['config']['enable_log'] == "on" || $alias_log == "enabled")
+ $rule['log'] = "";
+ $match_inbound[] = $rule;
+ break;
+ }
+ }
+ #mark pfctl aliastable for cleanup
+ if (!in_array($alias, $aliases_list)) {
+ $aliases_list[] = "{$alias}";
+ }
+ } else {
+ #unlink previous pfblockerNG alias list if any
+ unlink_if_exists($pfb['aliasdir'] . '/' . $alias . '.txt');
+ }
+ }
+ }
+ }
+ # Clear Variables
+ ${$alias} = "";
+
+
+ #############################################
+ # UPDATE PfSENSE ALIAS TABLES #
+ #############################################
+
+ #update pfsense alias table
+ if (is_array($config['aliases']['alias'])) {
+ foreach ($config['aliases']['alias'] as $cbalias) {
+ if (preg_match("/pfB_/",$cbalias['name'])) {
+ #mark pfctl aliastable for cleaning
+ if (!in_array($cbalias['name'], $aliases_list)) {
+ $aliases_list[] = $cbalias['name']; #mark aliastable for cleaning
+ }
+ #remove previous aliastable file if alias is not defined any more
+ if (!in_array($cbalias['name'], $new_aliases_list)) {
+ unlink_if_exists($pfb['aliasdir'] . '/' . $cbalias['name'] . ".txt");
+ }
+ } else {
+ $new_aliases[] = $cbalias;
+
+ # Check Table Size
+ if (file_exists($pfb['aliasdir'] . '/' . $alias . '.txt') && $message == "") {
+ preg_match("/(\d+)/",exec("/usr/bin/grep -c ^ " . $pfb['aliasdir'] . '/' . $alias . '.txt'),$matches);
+ }
+ if (($matches[1] * 2.1) >= $pfb['table_limit']) {
+ #alias table too large
+ $message = "{$alias} alias table is too large. Reduce networks in list or increase 'Firewall Maximum Table Entries' value to at least " . (int)($matches[1] * 2.1) . ' in "system - advanced - Firewall/NAT" . ';
+ }
+ }
+ }
+ }
+
+ #apply new alias table to xml
+ if ($message == "") {
+ $config['aliases']['alias'] = $new_aliases;
+ }
+ # UNSET Variables
+ unset($new_aliases, $cbalias);
+
+
+ #############################################
+ # Assign rules #
+ #############################################
+
+ # Only Execute if AutoRules are defined or if an Alias has been removed.
+ if ($pfb['autorules'] || $pfb['enable'] == "" || $pfb['remove']) {
+ if (count($deny_inbound) > 0 || count($permit_inbound) > 0 || count($match_inbound) > 0) {
+ if ($pfb['inbound_interfaces'] == "") {
+ $message = "Unable to apply rules. Inbound Interface option not configured.";
+ }
+ }
+ if (count($deny_outbound) > 0 || count($permit_outbound) > 0 || count($match_outbound) > 0) {
+ if ($pfb['outbound_interfaces'] == "") {
+ $message = "Unable to apply rules. Outbound Interface option not configured.";
+ }
+ }
+
+ if ($message == "") {
+ $new_rules = array();
+ $permit_rules = array();
+ $match_rules = array();
+ $other_rules = array();
+ $fpermit_rules = array();
+ $fmatch_rules = array();
+ $fother_rules = array();
+
+ # Collect All Existing Rules
+ $rules = $config['filter']['rule'];
+ # Collect Existing pfSense Rules 'Pass', 'Match' and 'Other' pfSense rules into new Arrays.
+ if (!empty($rules)) {
+ foreach ($rules as $rule) {
+ if (!preg_match("/pfB_.*" . $pfb['suffix'] . "/",$rule['descr'])) {
+ // Floating rules collection 'Floating Pass/Match'. Balance to 'other'
+ if ($pfb['float'] == "on") {
+ if ($rule['type'] == "pass" && $rule['floating'] == "yes") {
+ $fpermit_rules[] = $rule;
+ } elseif ($rule['type'] == "match" && $rule['floating'] == "yes") {
+ $fmatch_rules[] = $rule;
+ } elseif ($rule['floating'] == "yes") {
+ $fother_rules[] = $rule;
+ } else {
+ $other_rules[] = $rule;
+ }
+ } else {
+ // Collect only 'Selected Inbound and Outbound Interfaces'. Balance to 'Other'
+ if (in_array($rule['interface'],$pfb['inbound_interfaces']) || in_array($rule['interface'],$pfb['outbound_interfaces'])) {
+ // Floating Rules 'off'. Collect 'Floating Other', Balance to 'Other'
+ if ($rule['floating'] == "yes") {
+ $fother_rules[] = $rule;
+ } elseif ($rule['type'] == "pass") {
+ if ($pfb['order'] == "order_0") {
+ $other_rules[] = $rule;
+ } else {
+ $permit_rules[] = $rule;
+ }
+ } elseif ($rule['type'] == "match") {
+ if ($pfb['order'] == "order_0") {
+ $other_rules[] = $rule;
+ } else {
+ $match_rules[] = $rule;
+ }
+ } else {
+ $other_rules[] = $rule;
+ }
+ } else {
+ if ($rule['floating'] == "yes") {
+ $fother_rules[] = $rule;
+ } else {
+ $other_rules[] = $rule;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ #################################################################################
+ # PASS/MATCH RULES ORDER(p/m) #
+ # ORDER 0 - pfBlockerNG / All other Rules #
+ # ORDER 1 - pfSense (p/m) / pfBlockerNG (p/m) / pfBlockerNG Block/Reject #
+ # ORDER 2 - pfBlockerNG (p/m) / pfSense (p/m) / pfBlockerNG Block/Reject #
+ # ORDER 3 - pfBlockerNG (p/m) / pfBlockerNG Block/Reject / pfSense (p/m) #
+ #################################################################################
+
+ if ($pfb['float'] == "") {
+ if (!empty($fother_rules)) {
+ foreach ($fother_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ }
+ if (!empty($fpermit_rules) && $pfb['order'] == "order_1") {
+ foreach ($fpermit_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fmatch_rules) && $pfb['order'] == "order_1") {
+ foreach ($fmatch_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+
+ # Define Inbound Interface Rules
+ if (!empty($pfb['inbound_interfaces'])) {
+ $counter = 0;
+ foreach ($pfb['inbound_interfaces'] as $inbound_interface) {
+ if (!empty($permit_rules) && $pfb['order'] == "order_1") {
+ foreach ($permit_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $inbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($match_rules) && $pfb['order'] == "order_1") {
+ foreach ($match_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $inbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ # Match Inbound Rules defined as Floating Only.
+ if (!empty($match_inbound) && $counter == 0) {
+ foreach ($match_inbound as $cb_rules) {
+ $cb_rules['interface'] = $pfb['inbound_floating'];
+ $new_rules[] = $cb_rules;
+ $counter ++;
+ }
+ }
+ if (!empty($permit_inbound)) {
+ foreach ($permit_inbound as $cb_rules) {
+ $cb_rules['interface'] = $inbound_interface;
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fpermit_rules) && $pfb['order'] == "order_2") {
+ foreach ($fpermit_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fmatch_rules) && $pfb['order'] == "order_2") {
+ foreach ($fmatch_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($permit_rules) && $pfb['order'] == "order_2") {
+ foreach ($permit_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $inbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($match_rules) && $pfb['order'] == "order_2") {
+ foreach ($match_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $inbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($deny_inbound)) {
+ foreach ($deny_inbound as $cb_rules) {
+ $cb_rules['interface'] = $inbound_interface;
+ $new_rules[] = $cb_rules;
+ }
+ }
+ }
+ }
+
+ # Define Outbound Interface Rules
+ if (!empty($pfb['outbound_interfaces'])) {
+ $counter = 0;
+ foreach ($pfb['outbound_interfaces'] as $outbound_interface) {
+ if (!empty($permit_rules) && $pfb['order'] == "order_1") {
+ foreach ($permit_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $outbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($match_rules) && $pfb['order'] == "order_1") {
+ foreach ($match_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $outbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ # Match Outbound Rules defined as Floating Only.
+ if (!empty($match_outbound) && $counter == 0) {
+ foreach ($match_outbound as $cb_rules) {
+ $cb_rules['interface'] = $pfb['outbound_floating'];
+ $new_rules[] = $cb_rules;
+ $counter++;
+ }
+ }
+ if (!empty($permit_outbound)) {
+ foreach ($permit_outbound as $cb_rules) {
+ $cb_rules['interface'] = $outbound_interface;
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($permit_rules) && $pfb['order'] == "order_2") {
+ foreach ($permit_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $outbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($match_rules) && $pfb['order'] == "order_2") {
+ foreach ($match_rules as $cb_rules) {
+ if ($cb_rules['interface'] == $outbound_interface)
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($deny_outbound)) {
+ foreach ($deny_outbound as $cb_rules) {
+ $cb_rules['interface'] = $outbound_interface;
+ $new_rules[] = $cb_rules;
+ }
+ }
+ }
+ }
+
+ if (!empty($fpermit_rules) && $pfb['order'] == "order_0") {
+ foreach ($fpermit_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fmatch_rules) && $pfb['order'] == "order_0") {
+ foreach ($fmatch_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fpermit_rules) && $pfb['order'] == "order_3") {
+ foreach ($fpermit_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($fmatch_rules) && $pfb['order'] == "order_3") {
+ foreach ($fmatch_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($permit_rules) && $pfb['order'] == "order_3") {
+ foreach ($permit_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if (!empty($match_rules) && $pfb['order'] == "order_3") {
+ foreach ($match_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ if ($pfb['float'] == "on") {
+ if (!empty($fother_rules)) {
+ foreach ($fother_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+ }
+ if (!empty($other_rules)) {
+ foreach ($other_rules as $cb_rules) {
+ $new_rules[] = $cb_rules;
+ }
+ }
+
+ # Save New Rule Order to Config
+ $config['filter']['rule'] = $new_rules;
+ }
+ $log = "\n {$message} \n";
+ pfb_logger("{$log}","1");
+
+ # UNSET arrays
+ unset ($cb_rules,$permit_inbound,$permit_outbound,$deny_inbound,$deny_outbound,$match_inbound,$match_outbound);
+ unset ($other_rules,$fother_rules,$permit_rules,$fpermit_rules,$match_rules,$fmatch_rules);
+ }
+
+ #############################################
+ # Define/Apply CRON Jobs #
+ #############################################
+
+ # Clear any existing pfBlockerNG Cron Jobs
+ install_cron_job("pfblockerng.php cron", false);
+
+ # Replace Cron job with any User Changes to $pfb_min
+ if ($pfb['enable'] == "on") {
+ # Define pfBlockerNG CRON Job
+ $pfb_cmd = "/usr/local/bin/php /usr/local/www/pfblockerng/pfblockerng.php cron >> {$pfb['log']} 2>&1";
+ # $pfb['min'] ( User Defined Variable. Variable defined at start of Script )
+ $pfb_hour = "*";
+ $pfb_mday = "*";
+ $pfb_month = "*";
+ $pfb_wday = "*";
+ $pfb_who = "root";
+
+ install_cron_job($pfb_cmd, true, $pfb['min'], $pfb_hour, $pfb_mday, $pfb_month, $pfb_wday, $pfb_who);
+ }
+
+ # Clear any existing pfBlockerNG MaxMind CRON Job
+ install_cron_job("pfblockerng.php dc", false);
+
+ if ($pfb['enable'] == "on") {
+ # Define pfBlockerNG MaxMind CRON Job
+ $pfb_gcmd = "/usr/local/bin/php /usr/local/www/pfblockerng/pfblockerng.php dc >> {$pfb['geolog']} 2>&1";
+
+ # MaxMind GeoIP Cron Hour is randomized between 0-23 Hour to minimize effect on MaxMind Website
+
+ $pfb_gmin = "0";
+ $pfb_ghour = rand(0,23);
+ $pfb_gmday = "1,2,3,4,5,6,7";
+ $pfb_gmonth = "*";
+ $pfb_gwday = "2";
+ $pfb_gwho = "root";
+
+ install_cron_job($pfb_gcmd, true, $pfb_gmin, $pfb_ghour, $pfb_gmday, $pfb_gmonth, $pfb_gwday, $pfb_gwho);
+ }
+
+
+ #############################################
+ # Closing Processes #
+ #############################################
+
+ #uncheck Reusing Existing Downloads Check box
+ if (!$pfb['save'] && $pfb['enable'] == "on")
+ $config['installedpackages']['pfblockerng']['config'][0]['pfb_reuse'] = "";
+
+ # Save all Changes to pfSense config file
+ write_config();
+
+ # If 'Rule Changes' are found, utilize the 'filter_configure()' function, if not, utilize 'pfctl replace' command
+ if ($pfb['autorules'] && $rules != $new_rules || $pfb['enable'] == "" || $pfb['remove']) {
+ require_once("filter.inc");
+
+ $log = "\n===[ Aliastables / Rules ]================================\n\n";
+ pfb_logger("{$log}","1");
+
+ $log = "Firewall Rule Changes Found, Applying Filter Reload \n";
+ pfb_logger("{$log}","1");
+
+ # Remove all pfBlockerNG Alias tables
+ if (!empty($aliases_list)) {
+ foreach ($aliases_list as $table) {
+ exec ("/sbin/pfctl -t " . escapeshellarg($table) . " -T kill 2>&1", $pfb_null);
+ }
+ }
+
+ #load filter file which will create the pfctl tables
+ filter_configure();
+ } else {
+ # Don't Execute on User 'Save'
+ if (!$pfb['save']) {
+
+ $log = "\n===[ Aliastables / Rules ]================================\n\n";
+ pfb_logger("{$log}","1");
+
+ $log = "No Changes to Firewall Rules, Skipping Filter Reload \n";
+ pfb_logger("{$log}","1");
+
+ // Re-Save Only Aliases that have been updated only.
+ // When 'Reputation' is used, all Aliases Need to be Updated.
+ $final_alias = array();
+ if ($pfb['dedup'] == "on" || $pfb['pdup'] == "on") {
+ if (!empty($pfb_alias_lists_all))
+ $final_alias = array_unique($pfb_alias_lists_all);
+ } else {
+ if (!empty($pfb_alias_lists))
+ $final_alias = array_unique($pfb_alias_lists);
+ }
+
+ if (!empty($final_alias)) {
+ foreach ($final_alias as $final) {
+ $log = "\n Updating: {$final} \n";
+ pfb_logger("{$log}","1");
+ $result_pfctl = "";
+ exec ("/sbin/pfctl -t " . escapeshellarg($final) . " -T replace -f " . $pfb['aliasdir'] . "/" . escapeshellarg($final) . ".txt 2>&1", $result_pfctl);
+ $log = implode($result_pfctl);
+ pfb_logger("{$log}","1");
+ }
+ } else {
+ $log = "\n No Changes to Aliases, Skipping pfctl Update \n";
+ pfb_logger("{$log}","1");
+ }
+ }
+ }
+ # UNSET Variables
+ unset($rules, $new_rules);
+
+ #sync config
+ pfblockerng_sync_on_changes();
+
+ #############################################
+ # FINAL REPORTING #
+ #############################################
+
+ # Only run with CRON or Force Invoked Process
+ if ((!$pfb['save'] && $pfb['dupcheck'] && $pfb['enable'] == "on") || $pfb['summary']) {
+ # Script to run Final Script Processes.
+ exec ("{$pfb['script']} closing {$pfb['dup']} >> {$pfb['log']} 2>&1");
+ }
+
+ if ($pfb['enable'] == "on" && !$pfb['save']) {
+ $log = "\n\n UPDATE PROCESS ENDED [ NOW ]\n";
+ pfb_logger("{$log}","1");
+ }
+}
+
+
+function pfblockerng_validate_input($post, &$input_errors) {
+ global $config;
+ foreach ($post as $key => $value) {
+ if (empty($value))
+ continue;
+ if ($key == "message_size_limit" && !is_numeric($value))
+ $input_errors[] = "Message size limit must be numeric.";
+ if ($key == "process_limit" && !is_numeric($value))
+ $input_errors[] = "Process limit must be numeric.";
+ if ($key == "freq" && (!preg_match("/^\d+(h|m|d)$/",$value) || $value == 0))
+ $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'";
+ if (substr($key, 0, 2) == "dc" && !is_hostname($value))
+ $input_errors[] = "{$value} is not a valid host name.";
+ if (substr($key, 0, 6) == "domain" && is_numeric(substr($key, 6))) {
+ if (!is_domain($value))
+ $input_errors[] = "{$value} is not a valid domain name.";
+ } else if (substr($key, 0, 12) == "mailserverip" && is_numeric(substr($key, 12))) {
+ if (empty($post['domain' . substr($key, 12)]))
+ $input_errors[] = "Domain for {$value} cannot be blank.";
+ if (!is_ipaddr($value) && !is_hostname($value))
+ $input_errors[] = "{$value} is not a valid IP address or host name.";
+ }
+ }
+}
+
+
+function pfblockerng_php_install_command() {
+ require_once("/usr/local/www/pfblockerng/pfblockerng.php");
+ global $config,$pfb;
+ pfb_global();
+
+ // Remove previously used CC folder location if exists
+ @rmdir_recursive("{$pfb['dbdir']}/cc");
+
+ # Uncompress Country Code File and delete Archive after extraction.
+ exec("cd /{$pfb['ccdir']}; /usr/bin/tar -jxvf {$pfb['ccdir']}/countrycodes.tar.bz2");
+ unlink_if_exists("{$pfb['ccdir']}/countrycodes.tar.bz2");
+ # Download MaxMind Files and Create Country Code files and Build Continent XML Files
+ update_output_window(gettext("Downloading MaxMind Country Databases. This may take a minute..."));
+ exec("/bin/sh /usr/local/pkg/pfblockerng/geoipupdate.sh all >> {$pfb['geolog']} 2>&1");
+
+ @rename("{$pfb['dbdir']}/GeoIP.dat", "{$pfb['ccdir']}/GeoIP.dat");
+ @rename("{$pfb['dbdir']}/GeoIPv6.dat", "{$pfb['ccdir']}/GeoIPv6.dat");
+
+ update_output_window(gettext("MaxMind Country Database downloads completed..."));
+ update_output_window(gettext("Converting MaxMind Country Databases for pfBlockerNG. This may take a few minutes..."));
+ pfblockerng_uc_countries();
+ update_output_window(gettext("Creating pfBlockerNG Continenet XML Files..."));
+ pfblockerng_get_countries();
+ update_output_window(gettext("Completed Creating pfBlockerNG Continenet XML Files..."));
+
+ // Remove Original Maxmind Database Files
+ @unlink_if_exists("{$pfb['dbdir']}/GeoIPCountryCSV.zip");
+ @unlink_if_exists("{$pfb['dbdir']}/GeoIPCountryWhois.csv");
+ @unlink_if_exists("{$pfb['dbdir']}/GeoIPv6.csv");
+ @unlink_if_exists("{$pfb['dbdir']}/country_continent.csv");
+
+ # Add Widget to Dashboard
+ update_output_window(gettext("Adding pfBlockerNG Widget to Dashboard."));
+ if ($pfb['keep'] == "on" && !empty($pfb['widgets'])) {
+ // Restore previous Widget setting if "Keep" is enabled.
+ $config['widgets']['sequence'] = $pfb['widgets'];
+ } else {
+ $widgets = $config['widgets']['sequence'];
+ if (!preg_match("/pfblockerng-container/", $widgets)) {
+ if (empty($widgets)) {
+ $config['widgets']['sequence'] = "pfblockerng-container:col2:show";
+ } else {
+ $config['widgets']['sequence'] .= ",pfblockerng-container:col2:show";
+ }
+ }
+ }
+}
+
+
+function pfblockerng_php_deinstall_command() {
+ require_once("config.inc");
+ global $config,$pfb;
+
+ # Set these two variables to Disable pfBlockerNG on De-Install
+ $pfb['save'] = TRUE;
+ $pfb['install'] = TRUE;
+ sync_package_pfblockerng();
+ rmdir_recursive("/usr/local/pkg/pfblockerng");
+ rmdir_recursive("/usr/local/www/pfblockerng");
+
+ # Maintain pfBlockerNG Settings and Database Files if $pfb['keep'] is ON.
+ if ($pfb['keep'] != "on") {
+ # Remove pfBlockerNG Log and DB Folder
+ rmdir_recursive("{$pfb['dbdir']}");
+ rmdir_recursive("{$pfb['logdir']}");
+
+ # Remove Settings from Config
+ if (is_array($config['installedpackages']['pfblockerng']))
+ unset($config['installedpackages']['pfblockerng']);
+ if (is_array($config['installedpackages']['pfblockerngglobal']))
+ unset($config['installedpackages']['pfblockerngglobal']);
+ if (is_array($config['installedpackages']['pfblockerngsync']))
+ unset($config['installedpackages']['pfblockerngsync']);
+ if (is_array($config['installedpackages']['pfblockerngreputation']))
+ unset($config['installedpackages']['pfblockerngreputation']);
+ if (is_array($config['installedpackages']['pfblockernglistsv4']))
+ unset($config['installedpackages']['pfblockernglistsv4']);
+ if (is_array($config['installedpackages']['pfblockernglistsv6']))
+ unset($config['installedpackages']['pfblockernglistsv6']);
+ if (is_array($config['installedpackages']['pfblockerngafrica']))
+ unset($config['installedpackages']['pfblockerngafrica']);
+ if (is_array($config['installedpackages']['pfblockerngantartica']))
+ unset($config['installedpackages']['pfblockerngantartica']);
+ if (is_array($config['installedpackages']['pfblockerngasia']))
+ unset($config['installedpackages']['pfblockerngasia']);
+ if (is_array($config['installedpackages']['pfblockerngeurope']))
+ unset($config['installedpackages']['pfblockerngeurope']);
+ if (is_array($config['installedpackages']['pfblockerngnorthamerica']))
+ unset($config['installedpackages']['pfblockerngnorthamerica']);
+ if (is_array($config['installedpackages']['pfblockerngoceania']))
+ unset($config['installedpackages']['pfblockerngoceania']);
+ if (is_array($config['installedpackages']['pfblockerngsouthamerica']))
+ unset($config['installedpackages']['pfblockerngsouthamerica']);
+ if (is_array($config['installedpackages']['pfblockerngtopspammers']))
+ unset($config['installedpackages']['pfblockerngtopspammers']);
+ if (is_array($config['installedpackages']['pfblockerngproxyandsatellite']))
+ unset($config['installedpackages']['pfblockerngproxyandsatellite']);
+ }
+
+ # Remove Widget (code from Snort deinstall)
+ $pfb['widgets'] = $config['widgets']['sequence'];
+ if (!empty($pfb['widgets'])) {
+ $widgetlist = explode(",", $pfb['widgets']);
+ foreach ($widgetlist as $key => $widget) {
+ if (strstr($widget, "pfblockerng-container")) {
+ unset($widgetlist[$key]);
+ break;
+ }
+ }
+ $config['widgets']['sequence'] = implode(",", $widgetlist);
+ }
+ update_output_window(gettext("pfBlockerNG has been Uninstalled"));
+}
+
+/* Uses XMLRPC to synchronize the changes to a remote node */
+function pfblockerng_sync_on_changes() {
+ global $config, $g, $pfb_sync;
+
+ // Create Array of Sync Settings and exit if Sync is Disabled.
+ if (is_array($config['installedpackages']['pfblockerngsync']['config'][0])) {
+ $pfb_sync = $config['installedpackages']['pfblockerngsync']['config'][0];
+ if ($pfb_sync['varsynconchanges'] == "disabled" || $pfb_sync['varsynconchanges'] == "")
+ return;
+
+ $synctimeout = $pfb_sync['varsynctimeout'];
+ } else {
+ return;
+ }
+
+ log_error("[pfBlockerNG] XMLRPC sync is starting.");
+
+ if (is_array($config['installedpackages']['pfblockerngsync']['config'])) {
+ switch ($pfb_sync['varsynconchanges']) {
+ case "manual":
+ if (is_array($pfb_sync[row])) {
+ $rs = $pfb_sync[row];
+ } else {
+ log_error("[pfBlockerNG] XMLRPC sync is enabled but there are no replication targets configured.");
+ return;
+ }
+ break;
+ case "auto":
+ if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){
+ $system_carp = $config['installedpackages']['carpsettings']['config'][0];
+ $rs[0]['varsyncipaddress'] = $system_carp['synchronizetoip'];
+ $rs[0]['varsyncusername'] = $system_carp['username'];
+ $rs[0]['varsyncpassword'] = $system_carp['password'];
+
+ // XMLRPC sync is currently only supported over connections using the same protocol and port as this system
+ if ($config['system']['webgui']['protocol'] == "http") {
+ $rs[0]['varsyncprotocol'] = "http";
+ } else {
+ $rs[0]['varsyncprotocol'] = "https";
+ }
+
+ if ($system_carp['synchronizetoip'] == "") {
+ log_error("[pfBlockerNG] XMLRPC sync is enabled but there are no replication targets configured.");
+ return;
+ }
+ } else {
+ log_error("[pfBlockerNG] XMLRPC sync is enabled but there are no replication targets configured.");
+ return;
+ }
+ break;
+ default:
+ return;
+ break;
+ }
+ if (is_array($rs)) {
+ foreach ($rs as $sh) {
+ // Only Sync Enabled Replication Targets
+ if ($sh['varsyncdestinenable'] == "ON") {
+ $sync_to_ip = $sh['varsyncipaddress'];
+ $port = $sh['varsyncport'];
+ $password = htmlspecialchars($sh['varsyncpassword']);
+ $protocol = $sh['varsyncprotocol'];
+
+ if (!empty($sh['varsyncusername'])) {
+ $username = $sh['varsyncusername'];
+ } else {
+ $username = "admin";
+ }
+
+ pfblockerng_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout);
+ }
+ }
+ if ($success)
+ log_error("[pfBlockerNG] XMLRPC sync completed successfully.");
+ }
+ }
+}
+
+
+/* Do the actual XMLRPC sync */
+function pfblockerng_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) {
+ global $config, $g, $pfb_sync;
+ $success = TRUE;
+
+ /* Exit on missing parameters */
+ if (empty($sync_to_ip) || empty($password)) {
+ log_error("[pfBlockerNG] XMLRPC sync parameter missing (host IP or password) ... aborting xmlrpc sync");
+ $success = FALSE;
+ return $success;
+ }
+
+ /* Do not attempt a package sync while booting up or installing package */
+ if ($g['booting'] || $g['pfblockerng_postinstall']) {
+ log_error("[pfBlockerNG] XMLRPC sync to Replication targets terminated during boot up or during package reinstallation.");
+ $success = FALSE;
+ return $success;
+ }
+
+ // Validate Replication Target IP Address and Port Settings
+ if (!is_ipaddr($sync_to_ip) || !is_port($port)) {
+ log_error("[pfBlockerNG] XMLRPC sync terminated due to mis-configured Replication Target IP Address or Port settings.");
+ $success = FALSE;
+ return $success;
+ }
+
+ /* Test key variables and set defaults if empty */
+ if (empty($synctimeout))
+ $synctimeout = 150;
+
+ $url = "{$protocol}://{$sync_to_ip}";
+
+ if ($port == "") { $port = $config['system']['webgui']['port']; };
+ /* If port is empty lets rely on the protocol selection */
+ if ($port == "") {
+ if ($config['system']['webgui']['protocol'] == "http") {
+ $port = "80";
+ } else {
+ $port = "443";
+ }
+ }
+ /* xml will hold the sections to sync */
+ $xml = array();
+ // If User Disabled, remove 'General Tab Customizations' from Sync
+ if ($config['installedpackages']['pfblockerngsync']['config'][0]['syncinterfaces'] == "")
+ $xml['pfblockerng'] = $config['installedpackages']['pfblockerng'];
+ $xml['pfblockerngreputation'] = $config['installedpackages']['pfblockerngreputation'];
+ $xml['pfblockernglistsv4'] = $config['installedpackages']['pfblockernglistsv4'];
+ $xml['pfblockernglistsv6'] = $config['installedpackages']['pfblockernglistsv6'];
+ $xml['pfblockerngtopspammers'] = $config['installedpackages']['pfblockerngtopspammers'];
+ $xml['pfblockerngafrica'] = $config['installedpackages']['pfblockerngafrica'];
+ $xml['pfblockerngantartica'] = $config['installedpackages']['pfblockerngantartica'];
+ $xml['pfblockerngasia'] = $config['installedpackages']['pfblockerngasia'];
+ $xml['pfblockerngeurope'] = $config['installedpackages']['pfblockerngeurope'];
+ $xml['pfblockerngnorthamerica'] = $config['installedpackages']['pfblockerngnorthamerica'];
+ $xml['pfblockerngoceania'] = $config['installedpackages']['pfblockerngoceania'];
+ $xml['pfblockerngsouthamerica'] = $config['installedpackages']['pfblockerngsouthamerica'];
+
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ log_error("[pfBlockerNG] XMLRPC syncing to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials($username, $password);
+ if ($g['debug']) {
+ $cli->setDebug(1);
+ }
+
+ /* send our XMLRPC message and timeout after defined sync timeout value */
+ $resp = $cli->send($msg, $synctimeout);
+ $error = "";
+ if (!$resp) {
+ log_error("[pfBlockerNG] XMLRPC communications error occurred while attempting sync with {$url}:{$port}.");
+ file_notice("sync_settings", $error, "pfBlockerNG Settings Sync", "");
+ $success = FALSE;
+ return $success;
+ } elseif ($resp->faultCode()) {
+ $cli->setDebug(1);
+ $resp = $cli->send($msg, $synctimeout);
+ log_error("[pfBlockerNG] XMLRPC Error received while attempting sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString());
+ file_notice("sync_settings", $error, "pfBlockerNG Settings Sync", "");
+ $success = FALSE;
+ return $success;
+ } else {
+ log_error("[pfBlockerNG] XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+ return $success;
+}
+?> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.js b/config/pfblockerng/pfblockerng.js
new file mode 100644
index 00000000..cef0ce3b
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.js
@@ -0,0 +1,79 @@
+/* pfBlockerNG update engine */
+
+// Part of pfBlockerNG by BBCan177@gmail.com (c) 2014
+//
+// Javascript and Integration modifications by J. Nieuwenhuizen
+
+
+var pfBlockerNGtimer;
+
+function pfBlockerNG_fetch_new_rules_callback(callback_data) {
+ var data_split;
+ var new_data_to_add = Array();
+ var data = callback_data;
+
+ data_split = data.split("\n");
+
+ // Loop through rows and generate replacement HTML
+ if (data_split.length > 1) {
+ for(var x=0; x<data_split.length-1; x++) {
+ row_split = data_split[x].split("||");
+ if (row_split.length > 3) {
+ var line = '';
+ line = '<td class="listMRr ellipsis">' + row_split[0] + '</td>';
+ line += '<td class="listMRr" align="center">' + row_split[1] + '</td>';
+ line += '<td class="listMRr" align="center">' + row_split[2] + '</td>';
+ line += '<td class="listMRr" align="center">' + row_split[3] + '</td>';
+ line += '<td class="listMRr" align="center">' + row_split[4] + '</td>';
+ new_data_to_add[new_data_to_add.length] = line;
+ }
+ }
+ if (new_data_to_add.length > 0) {
+ pfBlockerNG_update_div_rows(new_data_to_add);
+ }
+ }
+}
+
+
+function pfBlockerNG_update_div_rows(data) {
+ var rows = jQuery('#pfbNG-entries>tr');
+
+ // Number of rows to move by
+ var move = rows.length + data.length;
+ if (move < 0)
+ move = 0;
+
+ for (var i = rows.length - 1; i >= move; i--) {
+ jQuery(rows[i]).html(jQuery(rows[i - move]).html());
+ }
+
+ var tbody = jQuery('#pfbNG-entries');
+ for (var i = data.length - 1; i >= 0; i--) {
+ if (i < rows.length) {
+ jQuery(rows[i]).html(data[i]);
+ } else {
+ jQuery(tbody).prepend('<tr>' + data[i] + '</tr>');
+ }
+ }
+
+ // Add the even/odd class to each of the rows now
+ // they have all been added.
+ rows = jQuery('#pfbNG-entries>tr');
+ for (var i = 0; i < rows.length; i++) {
+ rows[i].className = i % 2 == 0 ? 'listMRodd' : 'listMReven';
+ }
+}
+
+
+function fetch_new_pfBlockerNGcounts() {
+ jQuery.ajax('/widgets/widgets/pfblockerng.widget.php?getNewCounts=' + new Date().getTime(), {
+ type: 'GET',
+ dataType: 'text',
+ success: function(data) {
+ pfBlockerNG_fetch_new_rules_callback(data);
+ }
+ });
+}
+
+/* start local AJAX engine */
+pfBlockerNGtimer = setInterval('fetch_new_pfBlockerNGcounts()', pfBlockerNGupdateDelay); \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.php b/config/pfblockerng/pfblockerng.php
new file mode 100644
index 00000000..1db36334
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.php
@@ -0,0 +1,1475 @@
+<?php
+/*
+ pfBlockerNG.php
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfBlocker by
+ Copyright (C) 2011-2012 Marcello Coutinho
+ All rights reserved.
+
+ Hour Schedule Convertor code by
+ Snort Package
+ Copyright (c) 2014 Bill Meeks
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+require_once("util.inc");
+require_once("functions.inc");
+require_once("pkg-utils.inc");
+require_once("globals.inc");
+require_once("services.inc");
+require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+
+pfb_global();
+
+// IPv6 Range to CIDR function used courtesey from:
+// https://github.com/stilez/pfsense-leases/blob/50cc0fa81dba5fe91bcddaea016c245d1b8479cc/etc/inc/util.inc
+function ip_range_to_subnet_array_temp($ip1, $ip2) {
+
+ if (is_ipaddrv4($ip1) && is_ipaddrv4($ip2)) {
+ $proto = 'ipv4'; // for clarity
+ $bits = 32;
+ $ip1bin = decbin(ip2long32($ip1));
+ $ip2bin = decbin(ip2long32($ip2));
+ } elseif (is_ipaddrv6($ip1) && is_ipaddrv6($ip2)) {
+ $proto = 'ipv6';
+ $bits = 128;
+ $ip1bin = Net_IPv6::_ip2Bin($ip1);
+ $ip2bin = Net_IPv6::_ip2Bin($ip2);
+ } else
+ return array();
+
+ // it's *crucial* that binary strings are guaranteed the expected length; do this for certainty even though for IPv6 it's redundant
+ $ip1bin = str_pad($ip1bin, $bits, '0', STR_PAD_LEFT);
+ $ip2bin = str_pad($ip2bin, $bits, '0', STR_PAD_LEFT);
+
+ if ($ip1bin === $ip2bin)
+ return array($ip1 . '/' . $bits);
+
+ if (strcmp($ip1bin, $ip2bin) > 0)
+ list ($ip1bin, $ip2bin) = array($ip2bin, $ip1bin); // swap contents of ip1 <= ip2
+
+ $rangesubnets = array();
+ $netsize = 0;
+
+ do {
+ // at loop start, $ip1 is guaranteed strictly less than $ip2 (important for edge case trapping and preventing accidental binary wrapround)
+ // which means the assignments $ip1 += 1 and $ip2 -= 1 will always be "binary-wrapround-safe"
+
+ // step #1 if start ip (as shifted) ends in any '1's, then it must have a single cidr to itself (any cidr would include the '0' below it)
+
+ if (substr($ip1bin, -1, 1) == '1') {
+ // the start ip must be in a separate one-IP cidr range
+ $new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ $n = strrpos($ip1bin, '0'); //can't be all 1's
+ $ip1bin = ($n == 0 ? '' : substr($ip1bin, 0, $n)) . '1' . str_repeat('0', $bits - $n - 1); // BINARY VERSION OF $ip1 += 1
+ }
+
+ // step #2, if end ip (as shifted) ends in any zeros then that must have a cidr to itself (as cidr cant span the 1->0 gap)
+
+ if (substr($ip2bin, -1, 1) == '0') {
+ // the end ip must be in a separate one-IP cidr range
+ $new_subnet_ip = substr($ip2bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ $n = strrpos($ip2bin, '1'); //can't be all 0's
+ $ip2bin = ($n == 0 ? '' : substr($ip2bin, 0, $n)) . '0' . str_repeat('1', $bits - $n - 1); // BINARY VERSION OF $ip2 -= 1
+ // already checked for the edge case where end = start+1 and start ends in 0x1, above, so it's safe
+ }
+
+ // this is the only edge case arising from increment/decrement.
+ // it happens if the range at start of loop is exactly 2 adjacent ips, that spanned the 1->0 gap. (we will have enumerated both by now)
+
+ if (strcmp($ip2bin, $ip1bin) < 0)
+ continue;
+
+ // step #3 the start and end ip MUST now end in '0's and '1's respectively
+ // so we have a non-trivial range AND the last N bits are no longer important for CIDR purposes.
+
+ $shift = $bits - max(strrpos($ip1bin, '0'), strrpos($ip2bin, '1')); // num of low bits which are '0' in ip1 and '1' in ip2
+ $ip1bin = str_repeat('0', $shift) . substr($ip1bin, 0, $bits - $shift);
+ $ip2bin = str_repeat('0', $shift) . substr($ip2bin, 0, $bits - $shift);
+ $netsize += $shift;
+ if ($ip1bin === $ip2bin) {
+ // we're done.
+ $new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
+ $rangesubnets[$new_subnet_ip] = $bits - $netsize;
+ continue;
+ }
+
+ // at this point there's still a remaining range, and either startip ends with '1', or endip ends with '0'. So repeat cycle.
+ } while (strcmp($ip1bin, $ip2bin) < 0);
+
+ // subnets are ordered by bit size. Re sort by IP ("naturally") and convert back to IPv4/IPv6
+
+ ksort($rangesubnets, SORT_STRING);
+ $out = array();
+
+ foreach ($rangesubnets as $ip => $netmask) {
+ if ($proto == 'ipv4') {
+ $i = str_split($ip, 8);
+ $out[] = implode('.', array( bindec($i[0]),bindec($i[1]),bindec($i[2]),bindec($i[3]))) . '/' . $netmask;
+ } else
+ $out[] = Net_IPv6::compress(Net_IPv6::_bin2Ip($ip)) . '/' . $netmask;
+ }
+
+ return $out;
+}
+
+# Set php Memory Limit
+$uname = posix_uname();
+if ($uname['machine'] == "amd64")
+ ini_set('memory_limit', '256M');
+
+function pfb_update_check($header_url, $list_url, $url_format) {
+ global $pfb;
+ $pfb['cron_update'] = FALSE;
+
+ if ($url_format == "rsync" || $url_format == "html") {
+ $log = "[ {$header_url} ]\n Skipping timestamp query\n";
+ pfb_logger("{$log}","1");
+ $pfb['cron_update'] = TRUE;
+ }
+
+ switch ($url_format) {
+ case "gz":
+ case "gz_2":
+ case "gz_lg":
+ case "et":
+ $type = '.gz';
+ break;
+ case "zip":
+ case "xlsx":
+ $type = '.zip';
+ break;
+ case "txt":
+ $type = '.orig';
+ break;
+ case "html":
+ case "block":
+ $type = '.raw';
+ break;
+ }
+
+ $log = "[ {$header_url} ]\n";
+ pfb_logger("{$log}","1");
+ $host = @parse_url($list_url);
+ $local_file = "{$pfb['origdir']}/{$header_url}{$type}";
+ if (file_exists($local_file)) {
+ // Determine if URL is Remote or Local
+ if ($host['host'] == "127.0.0.1" || $host['host'] == $pfb['iplocal'] || empty($host['host'])) {
+ $remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($local_file));
+ } else {
+ $remote_tds = @implode(preg_grep("/Last-Modified/", get_headers($list_url)));
+ $remote_tds = preg_replace("/^Last-Modified: /","", $remote_tds);
+ }
+
+ $log = " Remote timestamp: {$remote_tds}\n";
+ pfb_logger("{$log}","1");
+ $local_tds = gmdate ("D, d M Y H:i:s T", filemtime($local_file));
+ $log = " Local timestamp: {$local_tds}\n";
+ pfb_logger("{$log}","1");
+ if ("{$remote_tds}" != "{$local_tds}") {
+ $pfb['cron_update'] = TRUE;
+ } else {
+ $log = " Remote file unchanged. Download Terminated\n";
+ pfb_logger("{$log}","1");
+ $pfb['cron_update'] = FALSE;
+ }
+ } else {
+ $pfb['cron_update'] = TRUE;
+ }
+
+ if ($pfb['cron_update']) {
+ // Trigger CRON Process if Updates are Found.
+ $pfb['update_cron'] = TRUE;
+
+ $log = " Updates Found\n";
+ pfb_logger("{$log}","1");
+ unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
+ }
+}
+
+
+if ($argv[1] == 'update') {
+ sync_package_pfblockerng("cron");
+}
+
+if ($argv[1] == 'dc') {
+ # (Options - 'bu' Binary Update for Reputation/Alerts Page, 'all' for Country update and 'bu' options.
+ if ($pfb['cc'] == "") {
+ exec("/bin/sh /usr/local/pkg/pfblockerng/geoipupdate.sh all >> {$pfb['geolog']} 2>&1");
+ } else {
+ exec("/bin/sh /usr/local/pkg/pfblockerng/geoipupdate.sh bu >> {$pfb['geolog']} 2>&1");
+ }
+ pfblockerng_uc_countries();
+ pfblockerng_get_countries();
+}
+
+if ($argv[1] == 'uc') {
+ pfblockerng_uc_countries();
+}
+
+if ($argv[1] == 'gc') {
+ pfblockerng_get_countries();
+}
+
+if ($argv[1] == 'cron') {
+ $hour = date('H');
+ $dow = date('N');
+ $pfb['update_cron'] = FALSE;
+
+ # Start hour of the 'Once a day' Schedule
+ $pfb['dailystart'] = $config['installedpackages']['pfblockerng']['config'][0]['pfb_dailystart'];
+ # Start hour of the Scheduler
+ if ($config['installedpackages']['pfblockerng']['config'][0]['pfb_hour'] != "") {
+ $pfb['hour'] = $config['installedpackages']['pfblockerng']['config'][0]['pfb_hour'];
+ } else {
+ $pfb['hour'] = "1";
+ }
+ $updates = 0;
+
+ # 2 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch2 = strval($shour);
+ for ($i=0; $i<11; $i++) {
+ $shour += 2;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch2 .= "," . strval($shour);
+ }
+
+ # 3 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch3 = strval($shour);
+ for ($i=0; $i<7; $i++) {
+ $shour += 3;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch3 .= "," . strval($shour);
+ }
+
+ # 4 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch4 = strval($shour);
+ for ($i=0; $i<5; $i++) {
+ $shour += 4;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch4 .= "," . strval($shour);
+ }
+
+ # 6 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch6 = strval($shour);
+ for ($i=0; $i<3; $i++) {
+ $shour += 6;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch6 .= "," . strval($shour);
+ }
+
+ # 8 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch8 = strval($shour);
+ for ($i=0; $i<2; $i++) {
+ $shour += 8;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch8 .= "," . strval($shour);
+ }
+
+ # 12 Hour Schedule Converter
+ $shour = intval(substr($pfb['hour'], 0, 2));
+ $sch12 = strval($shour) . ",";
+ $shour += 12;
+ if ($shour > 24)
+ $shour -= 24;
+ $sch12 .= strval($shour);
+
+ $e_sch2 = explode(",", $sch2);
+ $e_sch3 = explode(",", $sch3);
+ $e_sch4 = explode(",", $sch4);
+ $e_sch6 = explode(",", $sch6);
+ $e_sch8 = explode(",", $sch8);
+ $e_sch12 = explode(",", $sch12);
+
+ $log = " CRON PROCESS START [ NOW ]\n";
+ pfb_logger("{$log}","1");
+
+ $list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
+ foreach ($list_type as $ip_type => $vtype) {
+ if ($config['installedpackages'][$ip_type]['config'] != "") {
+ foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
+ if (is_array($list['row']) && $list['action'] != "Disabled") {
+ foreach ($list['row'] as $row) {
+ if ($row['url'] != "" && $row['state'] != "Disabled") {
+
+ if ($vtype == "_v4") {
+ $header_url = "{$row['header']}";
+ } else {
+ $header_url = "{$row['header']}_v6";
+ }
+
+ # Determine Folder Location for Alias (return array $pfbarr)
+ pfb_determine_list_detail($list['action']);
+ $pfbfolder = $pfbarr['folder'];
+
+ $list_cron = $list['cron'];
+ $list_url = $row['url'];
+ $header_dow = $list['dow'];
+ $url_format = $row['format'];
+
+ // Bypass update if state is defined as "Hold" and list file exists
+ if (file_exists($pfbfolder . '/' . $header_url . '.txt') && $row['state'] == "Hold") {
+ continue;
+ }
+
+ # Check if List file exists, if not found run Update
+ if (!file_exists($pfbfolder . '/' . $header_url . '.txt')) {
+ $log = " Updates Found\n";
+ pfb_logger("{$log}","1");
+ $pfb['update_cron'] = TRUE;
+ continue;
+ }
+
+ switch ($list_cron) {
+ case "01hour":
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "02hours":
+ if (in_array($hour, $e_sch2))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "03hours":
+ if (in_array($hour, $e_sch3))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "04hours":
+ if (in_array($hour, $e_sch4))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "06hours":
+ if (in_array($hour, $e_sch6))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "08hours":
+ if (in_array($hour, $e_sch8))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "12hours":
+ if (in_array($hour, $e_sch12))
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "EveryDay":
+ if ($hour == $pfb['dailystart'])
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ case "Weekly":
+ if ($hour == $pfb['dailystart'] && $dow == $header_dow)
+ pfb_update_check($header_url, $list_url, $url_format, $pfbfolder);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ($pfb['update_cron']) {
+ sync_package_pfblockerng("cron");
+ } else {
+ $log = "\n No Updates required. \n\n";
+ pfb_logger("{$log}","1");
+ }
+
+ $log = " CRON PROCESS ENDED [ NOW ]\n";
+ pfb_logger("{$log}","1");
+
+ # Call Log Mgmt Function
+ // If Update GUI 'Manual view' is selected. Last output will be missed. So sleep for 5 secs.
+ sleep(5);
+ pfb_log_mgmt();
+}
+
+
+// Function to process the downloaded Maxmind Database and format into Continent txt files.
+function pfblockerng_uc_countries() {
+ global $g,$pfb;
+ pfb_global();
+
+ $maxmind_cont = "{$pfb['dbdir']}/country_continent.csv";
+ $maxmind_cc4 = "{$pfb['dbdir']}/GeoIPCountryWhois.csv";
+ $maxmind_cc6 = "{$pfb['dbdir']}/GeoIPv6.csv";
+
+ # Create Folders if not Exist
+ $folder_array = array ("{$pfb['dbdir']}","{$pfb['logdir']}","{$pfb['ccdir']}");
+ foreach ($folder_array as $folder) {
+ safe_mkdir ("{$folder}",0755);
+ }
+
+ $now = date("m/d/y G:i:s", time());
+ $log = "Country Code Update Start - [ NOW ]\n\n";
+ print "Country Code Update Start - [ $now ]\n\n";
+ pfb_logger("{$log}","3");
+
+ if (!file_exists($maxmind_cont) || !file_exists($maxmind_cc4) || !file_exists($maxmind_cc6)) {
+ $log = " [ MAXMIND UPDATE FAIL, CSV Missing, using Previous Country Code Database \n";
+ print $log;
+ pfb_logger("{$log}","3");
+ return;
+ }
+
+ # Save Date/Time Stamp to MaxMind version file
+ $maxmind_ver = "MaxMind GeoLite Date/Time Stamps \n\n";
+ $remote_tds = @implode(preg_grep("/Last-Modified/", get_headers("http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip")));
+ $maxmind_ver .= "MaxMind_v4 \t" . $remote_tds . "\n";
+ $local_tds = @gmdate ("D, d M Y H:i:s T", filemtime($maxmind_cc4));
+ $maxmind_ver .= "Local_v4 \tLast-Modified: " . $local_tds . "\n\n";
+ $remote_tds = @implode(preg_grep("/Last-Modified/", get_headers("http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz")));
+ $maxmind_ver .= "MaxMind_v6 \t" . $remote_tds . "\n";
+ $local_tds = @gmdate ("D, d M Y H:i:s T", filemtime($maxmind_cc6));
+ $maxmind_ver .= "Local_v6 \tLast-Modified: " . $local_tds . "\n";
+ $maxmind_ver .= "\nThese Timestamps should *match* \n";
+ @file_put_contents("{$pfb['logdir']}/maxmind_ver", $maxmind_ver);
+
+ // Collect ISO Codes for Each Continent
+ $log = "Processing Continent Data\n";
+ print $log;
+ pfb_logger("{$log}","3");
+
+ $cont_array = array ( array($AF),array($AS),array($EU),array($NA),array($OC),array($SA),array($AX));
+ if (($handle = fopen("{$maxmind_cont}",'r')) !== FALSE) {
+ while (($cc = fgetcsv($handle)) !== FALSE) {
+
+ $cc_key = $cc[0];
+ $cont_key = $cc[1];
+ switch ($cont_key) {
+ case "AF":
+ $cont_array[0]['continent'] = "Africa";
+ $cont_array[0]['iso'] .= "{$cc_key},";
+ $cont_array[0]['file4'] = "{$pfb['ccdir']}/Africa_v4.txt";
+ $cont_array[0]['file6'] = "{$pfb['ccdir']}/Africa_v6.txt";
+ break;
+ case "AS":
+ $cont_array[1]['continent'] = "Asia";
+ $cont_array[1]['iso'] .= "{$cc_key},";
+ $cont_array[1]['file4'] = "{$pfb['ccdir']}/Asia_v4.txt";
+ $cont_array[1]['file6'] = "{$pfb['ccdir']}/Asia_v6.txt";
+ break;
+ case "EU":
+ $cont_array[2]['continent'] = "Europe";
+ $cont_array[2]['iso'] .= "{$cc_key},";
+ $cont_array[2]['file4'] = "{$pfb['ccdir']}/Europe_v4.txt";
+ $cont_array[2]['file6'] = "{$pfb['ccdir']}/Europe_v6.txt";
+ break;
+ case "NA":
+ $cont_array[3]['continent'] = "North America";
+ $cont_array[3]['iso'] .= "{$cc_key},";
+ $cont_array[3]['file4'] = "{$pfb['ccdir']}/North_America_v4.txt";
+ $cont_array[3]['file6'] = "{$pfb['ccdir']}/North_America_v6.txt";
+ break;
+ case "OC":
+ $cont_array[4]['continent'] = "Oceania";
+ $cont_array[4]['iso'] .= "{$cc_key},";
+ $cont_array[4]['file4'] = "{$pfb['ccdir']}/Oceania_v4.txt";
+ $cont_array[4]['file6'] = "{$pfb['ccdir']}/Oceania_v6.txt";
+ break;
+ case "SA":
+ $cont_array[5]['continent'] = "South America";
+ $cont_array[5]['iso'] .= "{$cc_key},";
+ $cont_array[5]['file4'] = "{$pfb['ccdir']}/South_America_v4.txt";
+ $cont_array[5]['file6'] = "{$pfb['ccdir']}/South_America_v6.txt";
+ break;
+ }
+ }
+ }
+ unset($cc);
+ fclose($handle);
+
+ // Add Maxmind Anonymous Proxy and Satellite Providers to array
+ $cont_array[6]['continent'] = "Proxy and Satellite";
+ $cont_array[6]['iso'] = "A1,A2";
+ $cont_array[6]['file4'] = "{$pfb['ccdir']}/Proxy_Satellite_v4.txt";
+ $cont_array[6]['file6'] = "{$pfb['ccdir']}/Proxy_Satellite_v6.txt";
+
+ // Collect Country ISO data and sort to Continent arrays (IPv4 and IPv6)
+ foreach (array("4", "6") as $type) {
+ $log = "Processing ISO IPv{$type} Continent/Country Data\n";
+ print $log;
+ pfb_logger("{$log}","3");
+
+ if ($type == "4") {
+ $maxmind_cc = "{$pfb['dbdir']}/GeoIPCountryWhois.csv";
+ } else {
+ $maxmind_cc = "{$pfb['dbdir']}/GeoIPv6.csv";
+ }
+ $iptype = "ip{$type}";
+ $filetype = "file{$type}";
+
+ if (($handle = fopen("{$maxmind_cc}",'r')) !== FALSE) {
+ while (($cc = fgetcsv($handle)) !== FALSE) {
+ $cc_key = $cc[4];
+ $country_key = $cc[5];
+ $a_cidr = implode(",", ip_range_to_subnet_array_temp($cc[0],$cc[1]));
+ $counter = 0;
+ foreach ($cont_array as $iso) {
+ if (preg_match("/\b$cc_key\b/", $iso['iso'])) {
+ $cont_array[$counter][$cc_key][$iptype] .= $a_cidr . ",";
+ $cont_array[$counter][$cc_key]['country'] = $country_key;
+ continue;
+ }
+ $counter++;
+ }
+ }
+ }
+ unset($cc);
+ fclose($handle);
+
+ // Build Continent Files
+ $counter = 0;
+ foreach ($cont_array as $iso) {
+ $header = "";
+ $pfb_file = "";
+ $iso_key = "";
+ $header .= "# Generated from MaxMind Inc. on: " . date("m/d/y G:i:s", time()) . "\n";
+ $header .= "# Continent IPv{$type}: " . $cont_array[$counter]['continent'] . "\n";
+ $pfb_file = $cont_array[$counter][$filetype];
+ $iso_key = array_keys($iso);
+ foreach ($iso_key as $key) {
+ if (preg_match("/[A-Z]{2}|A1|A2/", $key)) {
+ $header .= "# Country: " . $iso[$key]['country'] . "\n";
+ $header .= "# ISO Code: " . $key . "\n";
+ $header .= "# Total Networks: " . substr_count($iso[$key][$iptype], ",") . "\n";
+ $header .= str_replace(",", "\n", $iso[$key][$iptype]);
+ $iso[$key][$iptype] = "";
+ }
+ }
+ $counter++;
+ @file_put_contents($pfb_file, $header, LOCK_EX);
+ }
+ }
+}
+
+
+// Function to process Continent txt files and create Country ISO files and to Generate GUI XML files.
+function pfblockerng_get_countries() {
+ global $g,$pfb;
+ pfb_global();
+
+ $files = array ( "Africa" => "{$pfb['ccdir']}/Africa_v4.txt",
+ "Asia" => "{$pfb['ccdir']}/Asia_v4.txt",
+ "Europe" => "{$pfb['ccdir']}/Europe_v4.txt",
+ "North America" => "{$pfb['ccdir']}/North_America_v4.txt",
+ "Oceania" => "{$pfb['ccdir']}/Oceania_v4.txt",
+ "South America" => "{$pfb['ccdir']}/South_America_v4.txt",
+ "Proxy and Satellite" => "{$pfb['ccdir']}/Proxy_Satellite_v4.txt"
+ );
+
+ // Collect Data to generate new continent XML Files.
+ $log = "Building pfBlockerNG XML Files \n";
+ print $log;
+ pfb_logger("{$log}","3");
+
+ foreach ($files as $cont => $file) {
+ // Process the following for IPv4 and IPv6
+ foreach (array("4", "6") as $type) {
+ $log = "IPv{$type} " . $cont . "\n";
+ print $log;
+ pfb_logger("{$log}","3");
+
+ if ($type == "6")
+ $file = preg_replace("/v4/", "v6", $file);
+ $convert = explode("\n", file_get_contents($file));
+ $cont_name = preg_replace("/ /", "", $cont);
+ $cont_name_lower = strtolower($cont_name);
+ $active = array("$cont" => '<active/>');
+ $lastkey = count ($convert) - 1;
+ $pfb['complete'] = FALSE;
+ $keycount = 1;
+ $total = 0;
+
+ foreach ($convert as $line) {
+ if (preg_match("/#/",$line)) {
+ if ($pfb['complete']) {
+ ${'coptions' . $type}[] = $country . '-' . $isocode . ' ('. $total .') ' . ' </name><value>' . $isocode . '</value></option>';
+ ${'roptions' . $type}[] = $country . '-' . $isocode . ' ('. $total .') ' . ' </name><value>' . $isocode . '</value></option>';
+
+ // Save ISO data
+ @file_put_contents($pfb['ccdir'] . '/' . $isocode . '_v' . $type . '.txt', $xml_data, LOCK_EX);
+
+ // Clear variables and restart Continent collection process
+ unset($total, $xml_data);
+ $pfb['complete'] = FALSE;
+ }
+ if (preg_match("/Total Networks: 0/", $line)) { continue;} // Don't Display Countries with Null Data
+ if (preg_match("/Country:\s(.*)/",$line, $matches)) { $country = $matches[1];}
+ if (preg_match("/ISO Code:\s(.*)/",$line, $matches)) { $isocode = $matches[1];}
+ }
+ elseif (!preg_match("/#/",$line)) {
+ $total++;
+ if (!empty($line))
+ $xml_data .= $line . "\n";
+ $pfb['complete'] = TRUE;
+ }
+
+ // Save last EOF ISO IP data
+ if ($keycount == $lastkey) {
+ if (preg_match("/Total Networks: 0/", $line)) { continue;} // Dont Display Countries with Null Data
+ ${'coptions' . $type}[] = $country . '-' . $isocode . ' ('. $total .') ' . ' </name><value>' . $isocode . '</value></option>';
+ ${'roptions' . $type}[] = $country . '-' . $isocode . ' ('. $total .') ' . ' </name><value>' . $isocode . '</value></option>';
+ @file_put_contents($pfb['ccdir'] . '/' . $isocode . '_v' . $type . '.txt', $xml_data, LOCK_EX);
+ unset($total, $xml_data);
+ }
+ $keycount++;
+ }
+ unset ($ips, $convert);
+
+ // Sort IP Countries alphabetically and build XML <option> data for Continents tab
+ if (!empty (${'coptions' . $type})) {
+ sort(${'coptions' . $type}, SORT_STRING);
+ ${'ftotal' . $type} = count(${'coptions' . $type});
+ $count = 1;
+ ${'options' . $type} = "";
+
+ foreach (${'coptions' . $type} as $option) {
+ if ($count == 1) { ${'options' . $type} .= "\t" . '<option><name>' . $option . "\n"; $count++; continue;}
+ if (${'ftotal' . $type} == $count) {
+ ${'options' . $type} .= "\t\t\t\t" . '<option><name>' . $option;
+ } else {
+ ${'options' . $type} .= "\t\t\t\t" . '<option><name>' . $option . "\n";
+ }
+ $count++;
+ }
+ }
+ unset (${'coptions' . $type});
+ }
+
+$xml = <<<EOF
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* \$Id\$ */
+/* ========================================================================== */
+/*
+ pfblockerng_{$cont_name}.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS`` AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* ========================================================================== */
+]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockerng{$cont_name_lower}</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: {$cont}</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG: {$cont_name}</name>
+ <tooltiptext>Configure pfBlockerNG</tooltiptext>
+ <section>Firewall</section>
+ <url>pkg_edit.php?xml=pfblockerng_{$cont_name_lower}.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ {$active['Africa']}
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ {$active['Asia']}
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ {$active['Europe']}
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ {$active['North America']}
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ {$active['Oceania']}
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ {$active['South America']}
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ {$active['Proxy and Satellite']}
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <name><![CDATA[Continent {$cont}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Geolite Data by MaxMind Inc. - ISO 3166)]]></name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname></fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<br /><strong>IPv4</strong><br />Countries]]></fielddescr>
+ <fieldname>countries4</fieldname>
+ <description>
+ <![CDATA[Select IPv4 Countries you want to take an action on.<br />
+ <strong>Use CTRL + CLICK to unselect countries</strong>]]>
+ </description>
+ <type>select</type>
+ <options>
+ ${'options4'}
+ </options>
+ <size>${'ftotal4'}</size>
+ <multiple/>
+ </field>
+
+EOF;
+
+// Skip IPv6 when Null data found
+if (!empty (${'options6'})) {
+ $xml .= <<<EOF
+ <field>
+ <fielddescr><![CDATA[<br /><strong>IPv6</strong><br />Countries]]></fielddescr>
+ <fieldname>countries6</fieldname>
+ <description>
+ <![CDATA[Select IPv6 Countries you want to take an action on.<br />
+ <strong>Use CTRL + CLICK to unselect countries</strong>]]>
+ </description>
+ <type>select</type>
+ <options>
+ ${'options6'}
+ </options>
+ <size>${'ftotal6'}</size>
+ <multiple/>
+ </field>
+
+EOF;
+}
+
+$xml .= <<<EOF
+ <field>
+ <fielddescr>List Action</fielddescr>
+ <description><![CDATA[<br />Default : <strong>Disabled</strong><br /><br />
+ Select the <strong>Action</strong> for Firewall Rules on lists you have selected.<br /><br />
+ <strong><u>'Disabled' Rules:</u></strong> Disables selection and does nothing to selected Alias.<br /><br />
+
+ <strong><u>'Deny' Rules:</u></strong><br />
+ 'Deny' rules create high priority 'block' or 'reject' rules on the stated interfaces. They don't change the 'pass' rules on other
+ interfaces. Typical uses of 'Deny' rules are:<br />
+ <ul><li><strong>Deny Both</strong> - blocks all traffic in both directions, if the source or destination IP is in the block list</li>
+ <li><strong>Deny Inbound/Deny Outbound</strong> - blocks all traffic in one direction <u>unless</u> it is part of a session started by
+ traffic sent in the other direction. Does not affect traffic in the other direction. </li>
+ <li>One way 'Deny' rules can be used to selectively block <u>unsolicited</u> incoming (new session) packets in one direction, while
+ still allowing <u>deliberate</u> outgoing sessions to be created in the other direction.</li></ul>
+ <strong><u>'Permit' Rules:</u></strong><br />
+ 'Permit' rules create high priority 'pass' rules on the stated interfaces. They are the opposite of Deny rules, and don't create
+ any 'blocking' effect anywhere. They have priority over all Deny rules. Typical uses of 'Permit' rules are:<br />
+ <ul><li><strong>To ensure</strong> that traffic to/from the listed IPs will <u>always</u> be allowed in the stated directions. They
+ override <u>almost all other</u> Firewall rules on the stated interfaces.</li>
+ <li><strong>To act as a whitelist</strong> for Deny rule exceptions, for example if a large IP range or pre-created blocklist blocks a
+ few IPs that should be accessible.</li></ul>
+ <strong><u>'Match' Rules:</u></strong><br />
+ 'Match' or 'Log' only the traffic on the stated interfaces. This does not Block or Reject. It just Logs the traffic.
+ <ul><li><strong>Match Both</strong> - Matches all traffic in both directions, if the source or destination IP is in the list.</li>
+ <li><strong>Match Inbound/Match Outbound</strong> - Matches all traffic in one direction only.</li></ul>
+ <strong><u>'Alias' Rules:</u></strong><br />
+ <strong>'Alias'</strong> rules create an <a href="/firewall_aliases.php">alias</a> for the list (and do nothing else).
+ This enables a pfBlockerNG list to be used by name, in any firewall rule or pfSense function, as desired.
+ <ul><li><strong>Options &nbsp;&nbsp; - Alias Deny,&nbsp; Alias Permit,&nbsp; Alias Match,&nbsp; Alias Native</strong></li><br />
+ <li>'Alias Deny' can use De-Duplication and Reputation Processes if configured.</li><br />
+ <li>'Alias Permit' and 'Alias Match' will be saved in the Same folder as the other Permit/Match Auto-Rules</li><br />
+ <li>'Alias Native' lists are kept in their Native format without any modifications.</li></ul>
+ <strong>When using 'Alias' rules, change (pfB_) to ( pfb_ ) in the beginning of rule description and use the 'Exact' spelling of
+ the Alias (no trailing Whitespace)&nbsp;</strong> Custom 'Alias' rules with 'pfB_ xxx' description will be removed by package if
+ using Auto Rule Creation.<br /><br /><strong>Tip</strong>: You can create the Auto Rules and remove "<u>auto rule</u>" from the Rule
+ Descriptions, then disable Auto Rules. This method will 'KEEP' these rules from being 'Deleted' which will allow editing for a Custom
+ Alias Configuration<br />]]>
+ </description>
+ <fieldname>action</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Disabled</name><value>Disabled</value></option>
+ <option><name>Deny Inbound</name><value>Deny_Inbound</value></option>
+ <option><name>Deny Outbound</name><value>Deny_Outbound</value></option>
+ <option><name>Deny Both</name><value>Deny_Both</value></option>
+ <option><name>Permit Inbound</name><value>Permit_Inbound</value></option>
+ <option><name>Permit Outbound</name><value>Permit_Outbound</value></option>
+ <option><name>Permit Both</name><value>Permit_Both</value></option>
+ <option><name>Match Inbound</name><value>Match_Inbound</value></option>
+ <option><name>Match Outbound</name><value>Match_Outbound</value></option>
+ <option><name>Match Both</name><value>Match_Both</value></option>
+ <option><name>Alias Deny</name><value>Alias_Deny</value></option>
+ <option><name>Alias Permit</name><value>Alias_Permit</value></option>
+ <option><name>Alias Match</name><value>Alias_Match</value></option>
+ <option><name>Alias Native</name><value>Alias_Native</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ <description><![CDATA[Default:<strong>Enable</strong><br />
+ Select - Logging to Status: System Logs: FIREWALL ( Log )<br />
+ This can be overriden by the 'Global Logging' Option in the General Tab.]]></description>
+ <type>select</type>
+ <options>
+ <option><name>Enable</name><value>enabled</value></option>
+ <option><name>Disable</name><value>disabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Changes are Applied via CRON or
+ 'Force Update'</ul>]]>
+ </name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input(\$_POST, \$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global \$pfb;
+ \$pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui>
+EOF;
+
+ // Update Each Continent XML file.
+ @file_put_contents('/usr/local/pkg/pfblockerng/pfblockerng_'.$cont_name.'.xml',$xml,LOCK_EX);
+
+ // Unset Arrays
+ unset (${'options4'}, ${'options6'}, $xml);
+
+ } // End foreach 'Six Continents and Proxy/Satellite' Update XML Process
+
+ // Sort Countries IPv4 Alphabetically and Build XML <option> Data for Reputation Tab (IPv6 not used by ET IQRisk)
+
+ $type = "4";
+ sort(${'roptions' . $type}, SORT_STRING);
+ $eoa = count(${'roptions' . $type});
+ $count = 1;
+ $etoptions = "";
+
+ foreach (${'roptions' . $type} as $option4) {
+ if ($count == 1) { $et_options .= "\t" . '<option><name>' . $option4 . "\n"; $count++; continue; }
+ if ($eoa == $count) {
+ $et_options .= "\t\t\t\t" . '<option><name>' . $option4;
+ } else {
+ $et_options .= "\t\t\t\t" . '<option><name>' . $option4 . "\n";
+ }
+ $count++;
+ }
+
+// Update pfBlockerNG_Reputation.xml file with Country Code Changes
+
+$xmlrep = <<<EOF
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* \$Id\$ */
+/* ========================================================================== */
+/*
+ pfBlockerNG_Reputation.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockerngreputation</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: IPv4 Reputation</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <tooltiptext>Configure pfblockerNG</tooltiptext>
+ <section>Firewall</section>
+ <url>pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <name>IPv4 Reputation Preface</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname></fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Why Reputation Matters:</strong>]]></fielddescr>
+ <fieldname></fieldname>
+ <type>info</type>
+ <description><![CDATA[By Enabling '<strong>Reputation</strong>', each Blocklist will be analyzed for Repeat Offenders in each IP Range.
+ <ul>Example: &nbsp;&nbsp; x.x.x.1, x.x.x.2, x.x.x.3, x.x.x.4, x.x.x.5<br />
+ No. of <strong> Repeat Offending IPs </strong> [ &nbsp;<strong>5</strong>&nbsp; ], in a Blocklist within the same IP Range.</ul>
+ With '<strong>Reputation</strong> enabled, these 5 IPs will be removed and a single
+ <strong>x.x.x.0/24</strong> Block is used.<br />
+ This will completely Block/Reject this particular range from your Firewall.<br /><br />
+ Selecting Blocklists from various Threat Sources will help to highlight Repeat Offending IP Ranges,<br />
+ Its Important to select a Broad Range of Blocklists that cover different types of Malicious Activity.<br /><br />
+ You *may* experience some False Positives. Add any False Positive IPs manually to the<br />
+ <strong>pfBlockerNGSuppress Alias</strong> or use the "+" suppression Icon in the Alerts TAB<br /><br />
+ To help mitigate False Positives 'Countries' can be '<strong>Excluded</strong>' from this Process. (Refer to Country Code Settings)
+ <br /><br />Enabling <strong>De-Duplication</strong> is highly recommended before utilizing 'Reputation' processes.]]>
+ </description>
+ </field>
+ <field>
+ <name>Reputation Settings:</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fieldname></fieldname>
+ <fielddescr><![CDATA[<br /><strong>Individual List Reputation</strong><br /><br />]]></fielddescr>
+ <type>info</type>
+ <description></description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[Enable Max]]></fielddescr>
+ <fieldname>enable_rep</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[Enables Search for Repeat Offenders in a /24 Range on <strong>Each Individual Blocklist</strong>]]></description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[&nbsp;&nbsp;&nbsp;[ <strong>Max</strong> ] Setting]]></fielddescr>
+ <fieldname>p24_max_var</fieldname>
+ <description><![CDATA[Default: <strong>5</strong><br />
+ Maximum number of Repeat Offenders allowed in a Single IP Range]]></description>
+ <type>select</type>
+ <options>
+ <option><name>5</name><value>5</value></option>
+ <option><name>10</name><value>10</value></option>
+ <option><name>15</name><value>15</value></option>
+ <option><name>20</name><value>20</value></option>
+ <option><name>25</name><value>25</value></option>
+ <option><name>50</name><value>50</value></option>
+ </options>
+ </field>
+ <field>
+ <fieldname></fieldname>
+ <fielddescr><![CDATA[<br /><strong>Collective List Reputation</strong><br /><br />]]></fielddescr>
+ <type>info</type>
+ <description></description>
+ </field>
+ <field>
+ <fieldname></fieldname>
+ <type>info</type>
+ <description><![CDATA[Once all Blocklists are Downloaded, these two 'additional' processes <strong>[ pMax ] and [ dMax ]</strong><br />
+ Can be used to Further analyze for Repeat Offenders.<br />
+ <ul>Analyzing All Blocklists as a Whole:</ul>
+ <ul><strong>[ pMax ]</strong> will analyze for Repeat Offenders in each IP Range but will not use the Country Exclusion.<br />
+ Default is 50 IPs in any Range. Having 50 Repeat Offenders IPs in any Range will Block the entire Range.<br /><br /></ul>
+ <ul><strong>[ dMax ]</strong> will analyze for Repeat Offenders in each IP Range. Country Exclusions will be applied.<br />
+ Default is 5 IPs in any Range.</ul>
+ Note: <strong>MAX</strong> performs on individual Blocklists, while <strong>pMAX / dMAX</strong>
+ perform on all Lists together.<br />]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>Enable pMAX</fielddescr>
+ <fieldname>enable_pdup</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[Enables Search for Repeat Offenders in All BlockLists, <strong>Without</strong> Country Code Exclusion]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[&nbsp;&nbsp;&nbsp;[ <strong>pMax</strong> ] Setting]]></fielddescr>
+ <fieldname>p24_pmax_var</fieldname>
+ <description><![CDATA[Default: <strong>50</strong><br />Maximum number of Repeat Offenders]]></description>
+ <type>select</type>
+ <options>
+ <option><name>50</name><value>50</value></option>
+ <option><name>25</name><value>25</value></option>
+ <option><name>20</name><value>20</value></option>
+ <option><name>15</name><value>15</value></option>
+ <option><name>10</name><value>10</value></option>
+ <option><name>5</name><value>5</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable dMAX</fielddescr>
+ <fieldname>enable_dedup</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[Enables Search for Repeat Offenders in All BlockLists <strong>Using</strong> Country Code Exclusion]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[&nbsp;&nbsp;&nbsp;[ <strong>dMax</strong> ] Setting]]></fielddescr>
+ <fieldname>p24_dmax_var</fieldname>
+ <description><![CDATA[Default: <strong>5</strong><br />
+ Maximum number of Repeat Offenders]]></description>
+ <type>select</type>
+ <options>
+ <option><name>5</name><value>5</value></option>
+ <option><name>10</name><value>10</value></option>
+ <option><name>15</name><value>15</value></option>
+ <option><name>20</name><value>20</value></option>
+ <option><name>25</name><value>25</value></option>
+ <option><name>50</name><value>50</value></option>
+ </options>
+ </field>
+ <field>
+ <name>Country Code Settings</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fieldname>INFO</fieldname>
+ <type>info</type>
+ <description><![CDATA[When performing Queries for Repeat Offenders, you can choose to <strong>ignore</strong> Repeat Offenders in select
+ Countries. The Original Blocklisted IPs remain intact. All other Repeat Offending Country Ranges will be processed.<br /><br />
+ Define Repeat Offending Ranges [ <strong>Action</strong> ] Available settings are:<br />
+ <ul><strong>Ignore</strong>: Repeat Offenders that are in the 'ccwhite' category will be 'Ignored' (Default)</ul>
+ <ul><strong>Block:</strong> Repeat Offenders are set to Block the entire Repeat Offending Range(s)</ul>
+ <ul><strong>Match:</strong> Repeat Offenders are added to a 'Match' List which can be used in a Floating Match Rule<br />
+ Selecting 'Match' will consume more processing time, so only select this option if you enable Rules for it.</ul>
+ '<strong>ccwhite</strong>' are Countries that are Selected to be excluded from the Repeat Offenders Search.<br />
+ '<strong>ccblack</strong>' are all other Countries that are not selected.<br /><br />
+ To use '<strong>Match</strong>' Lists, Create a new 'Alias'
+ and select one of the <strong>Action 'Match'</strong> Formats and<br /> enter the 'Localfile' as:
+ <ul>/var/db/pfblockerng/match/matchdedup.txt</ul>]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>ccwhite Action:</fielddescr>
+ <fieldname>ccwhite</fieldname>
+ <description><![CDATA[Default: <strong>Ignore</strong><br />
+ Select the 'Action' format for ccwhite]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Ignore</name><value>ignore</value></option>
+ <option><name>Match</name><value>match</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>ccblack Action:</fielddescr>
+ <fieldname>ccblack</fieldname>
+ <description><![CDATA[Default: <strong>Block</strong><br />
+ Select the 'Action' format for ccblack]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Block</name><value>block</value></option>
+ <option><name>Match</name><value>match</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<br /><strong>IPv4</strong><br />Country Exclusion<br />
+ <br />Geolite Data by:<br />MaxMind Inc.&nbsp;&nbsp;(ISO 3166)]]></fielddescr>
+ <fieldname>ccexclude</fieldname>
+ <description>
+ <![CDATA[Select Countries you want to <strong>Exclude</strong> from the Reputation Process.<br />
+ <strong>Use CTRL + CLICK to unselect countries</strong>]]>
+ </description>
+ <type>select</type>
+ <options>
+ {$et_options}
+ </options>
+ <size>20</size>
+ <multiple/>
+ </field>
+ <field>
+ <name>Emerging Threats IQRISK IPv4 Reputation</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Subscription Pro. Blocklist</fielddescr>
+ <fieldname>ETINFO</fieldname>
+ <type>info</type>
+ <description><![CDATA[<strong>Emerging Threats IQRisk</strong> is a Subscription Professional Reputation List.<br /><br />
+ ET IQRisk Blocklist must be entered in the Lists Tab using the following example:
+ <ul>https://rules.emergingthreatspro.com/XXXXXXXXXXXXXXXX/reputation/iprepdata.txt.gz</ul>
+ Select the <strong>ET IQRisk'</strong> format. The URL should use the .gz File Type.<br />
+ Enter your "ETPRO" code in URL. Further information can be found @
+ <a target=_new href='http://emergingthreats.net/solutions/iqrisk-suite/'>ET IQRisk IP Reputation</a><br /><br />
+ To use <strong>'Match'</strong> Lists, Create a new 'Alias' and select one of the <strong>
+ Action 'Match'</strong> Formats and <br />
+ enter the 'Localfile' as: <ul>/var/db/pfblockerng/match/ETMatch.txt</ul>
+ ET IQRisk Individual Match Lists can be found in the following folder:<br />
+ <ul>/var/db/pfblockerng/ET</ul> ]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>ET IQRisk Header Name</fielddescr>
+ <fieldname>et_header</fieldname>
+ <type>input</type>
+ <description><![CDATA[Enter the 'Header Name' referenced in the IPv4 List TAB for ET IQRisk IPRep.<br />
+ This will be used to improve the Alerts TAB reporting for ET IPRep.]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>ET IQRISK BLOCK LISTS</fielddescr>
+ <fieldname>etblock</fieldname>
+ <description>
+ <![CDATA[Select Lists you want to BLOCK.<br />
+ <strong>Use CTRL + CLICK to unselect Categories</strong>
+ <br /><br />Any Changes will take effect at the Next Scheduled CRON Task]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>ET CNC</name><value>ET_Cnc</value></option>
+ <option><name>ET BOT</name><value>ET_Bot</value></option>
+ <option><name>ET SPAM</name><value>ET_Spam</value></option>
+ <option><name>ET DROP</name><value>ET_Drop</value></option>
+ <option><name>ET Spyware CNC</name><value>ET_Spywarecnc</value></option>
+ <option><name>ET Online Gaming</name><value>ET_Onlinegaming</value></option>
+ <option><name>ET DrivebySRC</name><value>ET_Drivebysrc</value></option>
+ <option><name>ET Chat Server</name><value>ET_Chatserver</value></option>
+ <option><name>ET TOR Node</name><value>ET_Tornode</value></option>
+ <option><name>ET Compromised</name><value>ET_Compromised</value></option>
+ <option><name>ET P2P</name><value>ET_P2P</value></option>
+ <option><name>ET Proxy</name><value>ET_Proxy</value></option>
+ <option><name>ET IP Check</name><value>ET_Ipcheck</value></option>
+ <option><name>ET Utility</name><value>ET_Utility</value></option>
+ <option><name>ET DOS</name><value>ET_DDos</value></option>
+ <option><name>ET Scanner</name><value>ET_Scanner</value></option>
+ <option><name>ET Brute</name><value>ET_Brute</value></option>
+ <option><name>ET Fake AV</name><value>ET_Fakeav</value></option>
+ <option><name>ET DYN DNS</name><value>ET_Dyndns</value></option>
+ <option><name>ET Undersireable</name><value>ET_Undesireable</value></option>
+ <option><name>ET Abuse TLD</name><value>ET_Abusedtld</value></option>
+ <option><name>ET SelfSigned SSL</name><value>ET_Selfsignedssl</value></option>
+ <option><name>ET Blackhole</name><value>ET_Blackhole</value></option>
+ <option><name>ET RAS</name><value>ET_RAS</value></option>
+ <option><name>ET P2P CNC</name><value>ET_P2Pcnc</value></option>
+ <option><name>ET Shared Hosting</name><value>ET_Sharedhosting</value></option>
+ <option><name>ET Parking</name><value>ET_Parking</value></option>
+ <option><name>ET VPN</name><value>ET_VPN</value></option>
+ <option><name>ET EXE Source</name><value>ET_Exesource</value></option>
+ <option><name>ET Mobile CNC</name><value>ET_Mobilecnc</value></option>
+ <option><name>ET Mobile Spyware</name><value>ET_Mobilespyware</value></option>
+ <option><name>ET Skype Node</name><value>ET_Skypenode</value></option>
+ <option><name>ET Bitcoin</name><value>ET_Bitcoin</value></option>
+ <option><name>ET DOS Attack</name><value>ET_DDosattack</value></option>
+ <option><name>Unknown</name><value>ET_Unknown</value></option>
+ </options>
+ <size>35</size>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>ET IQRISK Match LISTS</fielddescr>
+ <fieldname>etmatch</fieldname>
+ <description>
+ <![CDATA[Select Lists you want to MATCH.<br />
+ <strong>Use CTRL + CLICK to unselect Categories</strong>
+ <br /><br />Any Changes will take effect at the Next Scheduled CRON Task]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>ET CNC</name><value>ET_Cnc</value></option>
+ <option><name>ET BOT</name><value>ET_Bot</value></option>
+ <option><name>ET SPAM</name><value>ET_Spam</value></option>
+ <option><name>ET DROP</name><value>ET_Drop</value></option>
+ <option><name>ET Spyware CNC</name><value>ET_Spywarecnc</value></option>
+ <option><name>ET Online Gaming</name><value>ET_Onlinegaming</value></option>
+ <option><name>ET DrivebySRC</name><value>ET_Drivebysrc</value></option>
+ <option><name>ET Chat Server</name><value>ET_Chatserver</value></option>
+ <option><name>ET TOR Node</name><value>ET_Tornode</value></option>
+ <option><name>ET Compromised</name><value>ET_Compromised</value></option>
+ <option><name>ET P2P</name><value>ET_P2P</value></option>
+ <option><name>ET Proxy</name><value>ET_Proxy</value></option>
+ <option><name>ET IP Check</name><value>ET_Ipcheck</value></option>
+ <option><name>ET Utility</name><value>ET_Utility</value></option>
+ <option><name>ET DOS</name><value>ET_DDos</value></option>
+ <option><name>ET Scanner</name><value>ET_Scanner</value></option>
+ <option><name>ET Brute</name><value>ET_Brute</value></option>
+ <option><name>ET Fake AV</name><value>ET_Fakeav</value></option>
+ <option><name>ET DYN DNS</name><value>ET_Dyndns</value></option>
+ <option><name>ET Undersireable</name><value>ET_Undesireable</value></option>
+ <option><name>ET Abuse TLD</name><value>ET_Abusedtld</value></option>
+ <option><name>ET SelfSigned SSL</name><value>ET_Selfsignedssl</value></option>
+ <option><name>ET Blackhole</name><value>ET_Blackhole</value></option>
+ <option><name>ET RAS</name><value>ET_RAS</value></option>
+ <option><name>ET P2P CNC</name><value>ET_P2Pcnc</value></option>
+ <option><name>ET Shared Hosting</name><value>ET_Sharedhosting</value></option>
+ <option><name>ET Parking</name><value>ET_Parking</value></option>
+ <option><name>ET VPN</name><value>ET_VPN</value></option>
+ <option><name>ET EXE Source</name><value>ET_Exesource</value></option>
+ <option><name>ET Mobile CNC</name><value>ET_Mobilecnc</value></option>
+ <option><name>ET Mobile Spyware</name><value>ET_Mobilespyware</value></option>
+ <option><name>ET Skype Node</name><value>ET_Skypenode</value></option>
+ <option><name>ET Bitcoin</name><value>ET_Bitcoin</value></option>
+ <option><name>ET DOS Attack</name><value>ET_DDosattack</value></option>
+ <option><name>Unknown</name><value>ET_Unknown</value></option>
+ </options>
+ <size>35</size>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>Update ET Categories</fielddescr>
+ <fieldname>et_update</fieldname>
+ <description><![CDATA[Default:<strong>Disable</strong><br />
+ Select - Enable ET Update if Category Changes are Made.<br />
+ You can perform a 'Force Update' to enable these changes.<br />
+ Cron will also resync this list at the next Scheduled Update.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Disable</name><value>disabled</value></option>
+ <option><name>Enable</name><value>enabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]></name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input(\$_POST, \$input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global \$pfb;
+ \$pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui>
+EOF;
+ $log = "Saving pfBlockerNG Reputation TAB \n";
+ print $log;
+ pfb_logger("{$log}","3");
+
+ // Save pfBlockerng_reputation.xml file
+ @file_put_contents('/usr/local/pkg/pfblockerng/pfblockerng_reputation.xml', $xmlrep, LOCK_EX);
+
+ $log = "\n Country Code - XML File Update completed.\n";
+ print $log;
+ pfb_logger("{$log}","3");
+ $now = date("m/d/y G.i:s", time());
+ $log = "Country Code Update Ended - [ NOW ]\n";
+ print "Country Code Update Ended - [ $now ]\n";
+ pfb_logger("{$log}","3");
+
+ // Unset Arrays
+ unset ($et_options, $xmlrep);
+}
+?> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.priv.inc b/config/pfblockerng/pfblockerng.priv.inc
new file mode 100644
index 00000000..970ab25f
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.priv.inc
@@ -0,0 +1,30 @@
+<?php
+
+global $priv_list;
+
+$priv_list['page-firewall-pfblockerng'] = array();
+$priv_list['page-firewall-pfblockerng']['name'] = "WebCfg - Firewall: pfBlockerNG";
+$priv_list['page-firewall-pfblockerng']['descr'] = "Allow access to pfBlockerNG package gui";
+$priv_list['page-firewall-pfblockerng']['match'] = array();
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_reputation.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_v4lists.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_v6lists.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_top20.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_Africa.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_Asia.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_Europe.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_NorthAmerica.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_Oceania.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_SouthAmerica.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_ProxyandSatellite.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pkg_edit.php?xml=pfblockerng/pfblockerng_sync.xml*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pfblockerng/pfblockerng_update.php*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pfblockerng/pfblockerng_alerts.php*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pfblockerng/pfblockerng_log.php*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pfblockerng/pfblockerng_diag_dns.php*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "widgets/javascript/pfblockerng.js*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "widgets/include/widget-pfblockerng.inc*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "widgets/widgets/pfblockerng.widget.php*";
+$priv_list['page-firewall-pfblockerng']['match'][] = "pfblockerng/pfblockerng.inc*";
+?> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.sh b/config/pfblockerng/pfblockerng.sh
new file mode 100644
index 00000000..cc11be6b
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.sh
@@ -0,0 +1,927 @@
+#!/bin/sh
+# pfBlockerNG IP Reputation Script - By BBcan177@gmail.com - 04-12-14
+# Copyright (C) 2014 BBcan177@gmail.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License Version 2 as
+# published by the Free Software Foundation. You may not use, modify or
+# distribute this program under any other version of the GNU General
+# Public License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+now=$(/bin/date +%m/%d/%y' '%T)
+mtype=$(/usr/bin/uname -m);
+
+# Application Paths
+pathgrepcidr="/usr/pbi/pfblockerng-$mtype/bin/grepcidr"
+pathgeoip="/usr/pbi/pfblockerng-$mtype/bin/geoiplookup"
+
+pathtar=/usr/bin/tar
+pathgunzip=/usr/bin/gunzip
+pathpfctl=/sbin/pfctl
+
+# Script Arguments
+alias=$2
+max=$3
+dedup=$4
+cc=$(echo $5 | sed 's/,/, /g')
+ccwhite=$(echo $6 | tr '[A-Z]' '[a-z]')
+ccblack=$(echo $7 | tr '[A-Z]' '[a-z]')
+etblock=$(echo $8 | sed 's/,/, /g')
+etmatch=$(echo $9 | sed 's/,/, /g')
+
+# File Locations
+pathgeoipdat=/usr/pbi/pfblockerng-$mtype/share/GeoIP/GeoIP.dat
+pfbsuppression=/var/db/pfblockerng/pfbsuppression.txt
+masterfile=/var/db/pfblockerng/masterfile
+mastercat=/var/db/pfblockerng/mastercat
+geoiplog=/var/log/pfblockerng/geoip.log
+errorlog=/var/log/pfblockerng/error.log
+
+# Folder Locations
+etdir=/var/db/pfblockerng/ET
+tmpxlsx=/tmp/xlsx/
+
+pfbdeny=/var/db/pfblockerng/deny/
+pfborig=/var/db/pfblockerng/original/
+pfbmatch=/var/db/pfblockerng/match/
+pfbpermit=/var/db/pfblockerng/permit/
+pfbnative=/var/db/pfblockerng/native/
+pfsense_alias_dir=/var/db/aliastables/
+
+# Store "Match" d-dedups in matchdedup.txt file
+matchdedup=matchdedup.txt
+
+tempfile=/tmp/pfbtempfile
+tempfile2=/tmp/pfbtempfile2
+dupfile=/tmp//pfbduptemp
+dedupfile=/tmp/pfbdeduptemp
+addfile=/tmp/pfBaddfile
+syncfile=/tmp/pfbsyncfile
+matchfile=/tmp/pfbmatchfile
+tempmatchfile=/tmp/pfbtempmatchfile
+
+if [ ! -f $masterfile ]; then touch $masterfile; fi
+if [ ! -f $mastercat ]; then touch $mastercat; fi
+if [ ! -f $tempfile ]; then touch $tempfile; fi
+if [ ! -f $tempfile2 ]; then touch $tempfile2; fi
+if [ ! -f $dupfile ]; then touch $dupfile; fi
+if [ ! -f $dedupfile ]; then touch $dedupfile; fi
+if [ ! -f $addfile ]; then touch $addfile; fi
+if [ ! -f $syncfile ]; then touch $syncfile; fi
+if [ ! -f $matchfile ]; then touch $matchfile; fi
+if [ ! -f $tempmatchfile ]; then touch $tempmatchfile; fi
+if [ ! -d $pfbmatch ]; then mkdir $pfbmatch; fi
+if [ ! -d $etdir ]; then mkdir $etdir; fi
+if [ ! -d $tmpxlsx ]; then mkdir $tmpxlsx; fi
+
+##########
+# Process to condense an IP range if a "Max" amount of IP addresses are found in a /24 range per Alias Group.
+process24() {
+
+if [ ! -x $pathgeoip ]; then
+ echo "Process24 - Application [ GeoIP ] Not found. Can't proceed."
+ echo "Process24 - Application [ GeoIP ] Not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+# Download MaxMind GeoIP.dat Binary on first Install.
+if [ ! -f $pathgeoipdat ]; then
+ echo "Downloading [ MaxMind GeoIP.dat ] [ $now ]" >> $geoiplog
+ /usr/local/pkg/pfblockerng/geoipupdate.sh bu
+fi
+# Exit if GeoIP.dat is not found.
+if [ ! -f $pathgeoipdat ]; then
+ echo "Process24 - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed."
+ echo "Process24 - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+count=$(grep -c ^ $pfbdeny$alias".txt")
+echo; echo "Original File Count [ $count ]"
+
+grep -Ev "^(#|$)" $pfbdeny$alias".txt" | sort | uniq > $tempfile
+> $dupfile; > $tempfile2; > $matchfile; > $tempmatchfile
+data="$(cut -d '.' -f 1-3 $tempfile | awk -v max="$max" '{a[$0]++}END{for(i in a){if(a[i] > max){print i}}}')"
+count=$(echo "$data" | grep -c ^); mcount=0; dcount=0; safe=0
+if [ "$data" == "" ]; then count=0; fi
+matchoutfile="match"$header".txt"
+# Classify Repeat Offenders by Country Code
+if [ -f $pathgeoipdat ]; then
+ for ip in $data; do
+ ccheck=$($pathgeoip -f $pathgeoipdat "$ip.1" | cut -c 24-25)
+ case "$cc" in
+ *$ccheck*)
+ safe=$(($safe + 1))
+ if [ "$ccwhite" == "match" -o "$ccblack" == "match" ]; then
+ echo "$ip." >> $matchfile
+ fi
+ ;;
+ *)
+ echo "$ip." >> $dupfile
+ ;;
+ esac
+ done
+else
+ echo; echo "MaxMind Binary Database Missing [ $pathgeoipdat ], skipping p24 Process"; echo
+ echo "MaxMind Binary Database Missing [ $pathgeoipdat ], skipping p24 Process [ $now ]" >> $errorlog
+fi
+# Collect Match File Details
+if [ -s "$matchfile" -a ! "$dedup" == "on" -a "$ccwhite" == "match" ]; then
+ mon=$(sed -e 's/^/^/' -e 's/\./\\\./g' $matchfile)
+ for ip in $mon; do
+ grep $ip $tempfile >> $tempfile2
+ done
+ mcount=$(grep -c ^ $tempfile2)
+ if [ "$ccwhite" == "match" ]; then
+ sed 's/$/0\/24/' $matchfile >> $tempmatchfile
+ sed 's/^/\!/' $tempfile2 >> $tempmatchfile
+ fi
+fi
+
+# If no Matches found remove previous Matchoutfile if exists.
+if [ ! -s "$tempmatchfile" -a -f $matchoutfile ]; then rm -r $matchoutfile; fi
+# Move Match File to the Match Folder by Individual Blocklist Name
+if [ -s "$tempmatchfile" ]; then mv -f $tempmatchfile $pfbmatch$matchoutfile; fi
+
+# Find Repeat Offenders in each individual Blocklist Outfile
+if [ -s "$dupfile" ]; then
+ > $tempfile2
+ dup=$(sed -e 's/^/^/' -e 's/\./\\\./g' $dupfile)
+ for ip in $dup; do
+ grep $ip $tempfile >> $tempfile2
+ done
+ dcount=$(grep -c ^ $tempfile2)
+ if [ "$ccblack" == "block" ]; then
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile2 $tempfile > $pfbdeny$alias".txt"
+ sed 's/$/0\/24/' $dupfile >> $pfbdeny$alias".txt"
+ elif [ "$ccblack" == "match" ]; then
+ sed 's/$/0\/24/' $dupfile >> $tempmatchfile
+ sed 's/^/\!/' $tempfile2 >> $tempmatchfile
+ else
+ :
+ fi
+fi
+if [ "$count" == "0" -a "$safe" == "0" ]; then echo; echo " Process /24 Stats [ $alias ] [ $now ] "; echo "------------------------------------------------"; fi
+if [ "$count" == "0" ]; then echo "Found [ 0 ] IP range(s) over the threshold of [ $max ] p24 - CC Blacklist"; fi
+if [ "$safe" == "0" ]; then echo "Found [ 0 ] IP range(s) over the threshold of [ $max ] p24 - CC Whitelist"; fi
+
+if [ -s "$dupfile" -o -s "$matchfile" ]; then
+echo
+echo " Process /24 Stats [ $alias ] [ $now ]"
+echo "--------------------------------------------------------"
+echo "Found [ $count ] IP range(s) over the threshold of [ $max ] on the CC Blacklist"
+echo "Found [ $safe ] IP range(s) over the threshold of [ $max ] on the CC Whitelist"
+echo
+echo "Found [ $dcount ] CC Blacklisted IP Address(es) are being set to [ $ccblack ]"
+# Skip Match Process if dedup=yes as it will create duplicates
+if [ "$dedup" == "on" ]; then mcount=Skipped; fi
+echo "Found [ $mcount ] CC Whitelisted IP Address(es) are being set to [ $ccwhite ]"
+if [ "$ccblack" == "block" ]; then
+ echo; echo "Removed the following IP Ranges"
+ cat $dupfile | tr '\n' '|'; echo
+else
+ echo "Skipped, CCBlack set to [ $ccblack ]"
+fi
+sort $pfbdeny$alias".txt" | uniq > $tempfile; mv -f $tempfile $pfbdeny$alias".txt"
+echo "-------------------------------------------------------"
+cocount=$(grep -cv "^1\.1\.1\.1" $pfbdeny$alias".txt")
+echo "Post /24 Count [ $cocount ]"; echo
+fi
+}
+
+
+##########
+process255() {
+# Remove IPs if exists over 255 IPs in a Range and replace with a single /24 Block
+cp $pfbdeny$alias".txt" $tempfile; > $dedupfile
+
+data255="$(cut -d '.' -f 1-3 $tempfile | awk '{a[$0]++}END{for(i in a){if(a[i] > 255){print i}}}')"
+if [ ! -z "$data255" ]; then
+ for ip in $data255; do
+ ii=$(echo "^$ip" | sed 's/\./\\\./g')
+ grep $ii $tempfile >> $dedupfile
+ done
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $dedupfile $tempfile > $pfbdeny$alias".txt"
+ for ip in $data255; do echo $ip"0/24" >> $pfbdeny$alias".txt"; done
+fi
+}
+
+
+##########
+continent() {
+
+dupcheck=yes
+# Check if Masterfile is Empty
+hcheck=$(grep -c ^ $masterfile); if [ "$hcheck" -eq "0" ]; then dupcheck=no; fi
+# Check if Alias exists in Masterfile
+lcheck=$(grep -m 1 "$alias " $masterfile ); if [ "$lcheck" == "" ]; then dupcheck=no; fi
+
+if [ "$dupcheck" == "yes" ]; then
+ # Grep Alias with a trailing Space character
+ grep "$alias[[:space:]]" $masterfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+fi
+
+grep -Ev "^(#|$)" $pfbdeny$alias".txt" | sort | uniq > $tempfile
+
+if [ ! "$hcheck" -eq "0" ]; then
+ $pathgrepcidr -vf $mastercat $pfbdeny$alias".txt" > $tempfile; mv -f $tempfile $pfbdeny$alias".txt"
+fi
+
+sed -e 's/^/'$alias' /' $pfbdeny$alias".txt" >> $masterfile
+cut -d' ' -f2 $masterfile > $mastercat
+
+countg=$(grep -c ^ $pfborig$alias".orig")
+countm=$(grep -c "$alias " $masterfile); counto=$(grep -c ^ $pfbdeny$alias".txt")
+if [ "$countm" == "$counto" ]; then sanity="Passed"; else sanity=" ==> FAILED <== "; fi
+echo "----------------------------------------------------------"
+echo; echo " Post Duplication count [ $now ]"
+echo "----------------------------------------------------------"
+printf "%-10s %-10s %-10s %-30s\n" "Original" "Masterfile" "Outfile" "Sanity Check"
+echo "----------------------------------------------------------"
+printf "%-10s %-10s %-10s %-30s\n" "$countg" "$countm" "$counto" " [ $sanity ]"
+echo "----------------------------------------------------------"
+}
+
+
+##########
+# Process to remove Suppressed Entries and RFC 1918 and Misc IPs on each downloaded Blocklist
+suppress() {
+
+if [ ! -x $pathgrepcidr ]; then
+ echo "Application [ Grepcidr ] Not found. Can't proceed. [ $now ]"
+ echo "Application [ Grepcidr ] Not found. Can't proceed. [ $now ]" >> errorlog
+ exit
+fi
+
+if [ -e "$pfbsuppression" ] && [ -s "$pfbsuppression" ]; then
+ # Find '/24' Blocked IPs that are single addresses in the Suppressed IP Address List.
+ # These '/24' Are converted to single Addresses excluding the Suppressed IPs.
+ data="$(cat $pfbsuppression)"
+ if [ ! -z "$data" -a ! -z "$cc" ]; then
+ # Loop thru each Updated List to remove Suppression and RFC1918 Addresses
+ if [ "$cc" == "suppressheader" ]; then
+ echo; echo "===[ Suppression Stats ]========================================"; echo
+ printf "%-20s %-10s %-10s %-10s %-10s\n" "List" "Pre" "RFC1918" "Suppress" "Masterfile"
+ echo "----------------------------------------------------------------"
+ exit
+ fi
+
+ for i in $cc; do
+ counter=0
+ > $dupfile
+ alias=$(echo "${i%|*}")
+ pfbfolder=$(echo "${i#*|}")
+
+ if [ ! "$alias" == "" ]; then
+ # Count (PRE)
+ countg=$(grep -c ^ $pfbfolder$alias".txt")
+
+ grep -Ev "^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|#|$)" $pfbfolder$alias".txt" |
+ sort | uniq > $tempfile
+ # Count (Post RFC1918)
+ countm=$(grep -c ^ $tempfile)
+
+ for ip in $data; do
+ found=""; ddcheck="";
+ iptrim=$(echo $ip | cut -d '.' -f 1-3)
+ mask=$(echo $ip | cut -d"/" -f2)
+ found=$(grep -m1 $iptrim".0/24" $tempfile)
+ # If a Suppression is '/32' and a Blocklist has a full '/24' Block execute the following.
+ if [ ! "$found" == "" -a "$mask" == "32" ]; then
+ echo " Suppression $alias: $iptrim.0/24"
+ octet4=$(echo $ip | cut -d '.' -f 4 | sed 's/\/.*//')
+ dcheck=$(grep $iptrim".0/24" $dupfile)
+ if [ "$dcheck" == "" ]; then
+ echo $iptrim".0" >> $tempfile
+ echo $iptrim".0/24" >> $dupfile
+ counter=$(($counter + 1))
+ # Add Individual IP addresses from Range excluding Suppressed IP
+ for i in $(/usr/bin/jot 255); do
+ if [ "$i" != "$octet4" ]; then
+ echo $iptrim"."$i >> $tempfile
+ counter=$(($counter + 1))
+ fi
+ done
+ fi
+ fi
+ done
+ if [ -s $dupfile ]; then
+ # Remove '/24' Suppressed Ranges
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $dupfile $tempfile > $tempfile2; mv -f $tempfile2 $tempfile
+ fi
+ # Remove All other Suppressions from Lists
+ $pathgrepcidr -vf $pfbsuppression $tempfile > $pfbfolder$alias".txt"
+ # Update Masterfiles. Don't execute if Duplication Process is Disabled
+ if [ "$dedup" == "x" ]; then
+ # Dont execute if Alias doesnt exist in Masterfile
+ lcheck=$(grep -m1 "$alias " $masterfile)
+ if [ ! "$lcheck" == "" ]; then
+ # Replace Masterfile with changes to List.
+ grep "$alias[[:space:]]" $masterfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ sed -e 's/^/'$alias' /' $pfbfolder$alias".txt" >> $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+ fi
+ fi
+ countk=$(grep -c ^ $masterfile)
+ countx=$(grep -c ^ $pfbfolder$alias".txt")
+ counto=$(($countx - $counter))
+ printf "%-20s %-10s %-10s %-10s %-10s\n" "$alias" "$countg" "$countm" "$counto" "$countk"
+ fi
+ done
+ fi
+else
+ if [ "$cc" == "suppressheader" ]; then
+ echo "===[ Suppression Stats ]========================================"; echo
+ printf "%-20s %-10s %-10s %-10s %-10s\n" "List" "Pre" "RFC1918" "Suppress" "Masterfile"
+ echo "----------------------------------------------------------------"
+ exit
+ fi
+ for i in $cc; do
+ alias=$(echo "${i%|*}")
+ pfbfolder=$(echo "${i#*|}")
+
+ if [ ! "$alias" == "" ]; then
+ countg=$(grep -c ^ $pfbfolder$alias".txt")
+ grep -Ev "^(192\.168|10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|#|$)" $pfbfolder$alias".txt" |
+ sort | uniq > $tempfile; mv -f $tempfile $pfbfolder$alias".txt"
+ countx=$(grep -c ^ $pfbfolder$alias".txt")
+ # Update Masterfiles. Don't execute if Duplication Process is Disabled or if No Suppression Changes Found
+ if [ "$dedup" == "x" -a "$countg" != "$countx" ]; then
+ # Dont execute if Alias doesnt exist in Masterfile
+ lcheck=$(grep -m1 "$alias " $masterfile)
+ if [ ! "$lcheck" == "" ]; then
+ # Replace Masterfile with changes to List.
+ grep "$alias[[:space:]]" $masterfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ sed -e 's/^/'$alias' /' $pfbfolder$alias".txt" >> $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+ fi
+ fi
+ countm=$(grep -c ^ $pfbfolder$alias".txt")
+ counto=" - "
+ countk=$(grep -c ^ $masterfile)
+ printf "%-20s %-10s %-10s %-10s %-10s\n" "$alias" "$countg" "$countm" "$counto" "$countk"
+ fi
+ done
+fi
+}
+
+
+##########
+# Process to remove Duplicate Entries on each downloaded Blocklist Individually
+duplicate() {
+
+if [ ! -x $pathgrepcidr ]; then
+ echo "Application [ Grepcidr ] Not found. Can't proceed. [ $now ]"
+ echo "Application [ Grepcidr ] Not found. Can't proceed. [ $now ]" >> errorlog
+ exit
+fi
+
+dupcheck=yes
+# Check if Masterfile is Empty
+hcheck=$(grep -cv "^$" $masterfile); if [ "$hcheck" -eq "0" ]; then dupcheck=no; fi
+# Check if Alias exists in Masterfile
+lcheck=$(grep -m1 "$alias " $masterfile); if [ "$lcheck" == "" ]; then dupcheck=no; fi
+
+if [ "$dupcheck" == "yes" ]; then
+ # Grep Alias with a trailing Space character
+ grep "$alias[[:space:]]" $masterfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+fi
+
+grep -Ev "^(#|$)" $pfbdeny$alias".txt" | sort | uniq > $tempfile; mv -f $tempfile $pfbdeny$alias".txt"
+
+if [ ! "$hcheck" -eq "0" ]; then
+ $pathgrepcidr -vf $mastercat $pfbdeny$alias".txt" > $tempfile; mv -f $tempfile $pfbdeny$alias".txt"
+fi
+
+sed -e 's/^/'$alias' /' $pfbdeny$alias".txt" >> $masterfile
+cut -d' ' -f2 $masterfile > $mastercat
+
+countg=$(grep -c ^ $pfborig$alias".orig")
+countm=$(grep -c "$alias " $masterfile); counto=$(grep -c ^ $pfbdeny$alias".txt")
+if [ "$countm" == "$counto" ]; then sanity="Passed"; else sanity=" ==> FAILED <== "; fi
+echo "----------------------------------------------------------"
+printf "%-10s %-10s %-10s %-30s\n" "Original" "Masterfile" "Outfile" " [ Post Duplication count ]"
+echo "----------------------------------------------------------"
+printf "%-10s %-10s %-10s %-30s\n" "$countg" "$countm" "$counto" " [ $sanity ]"
+echo "----------------------------------------------------------"
+}
+
+
+##########
+# De-Duplication utilizing MaxMind GeoIP Country Code Whitelisting ("dmax" variable)
+deduplication() {
+
+if [ ! -x $pathgeoip ]; then
+ echo "d-duplication - Application [ GeoIP ] Not found. Can't proceed."
+ echo "d-duplication - Application [ GeoIP ] Not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+# Download MaxMind GeoIP.dat on first Install.
+if [ ! -f $pathgeoipdat ]; then
+ echo "Downloading [ MaxMind GeoIP.dat ] [ $now ]" >> $geoiplog
+ /usr/local/pkg/pfblockerng/geoipupdate.sh bu
+fi
+
+# Exit if GeoIP.dat is not found
+if [ ! -f $pathgeoipdat ]; then
+ echo "d-duplication - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed."
+ echo "d-duplication - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+> $tempfile; > $tempfile2; > $dupfile; > $addfile; > $dedupfile; > $matchfile; > $tempmatchfile; count=0; dcount=0; mcount=0; mmcount=0
+echo; echo "Querying for Repeat Offenders"
+data="$(find $pfbdeny ! -name "pfB*.txt" ! -name "*_v6.txt" -type f | cut -d '.' -f 1-3 $pfbdeny*.txt |
+ awk -v max="$max" '{a[$0]++}END{for(i in a){if(a[i] > max){print i}}}' | grep -v "^1\.1\.1")"
+count=$(echo "$data" | grep -c ^)
+if [ "$data" == "" ]; then count=0; fi
+safe=0
+# Classify Repeat Offenders by Country Code
+if [ -f $pathgeoipdat ]; then
+ echo "Classifying Repeat Offenders by GeoIP"
+ for ip in $data; do
+ ccheck=$($pathgeoip -f $pathgeoipdat "$ip.1" | cut -c 24-25)
+ case "$cc" in
+ *$ccheck*)
+ safe=$(($safe + 1))
+ if [ "$ccwhite" == "match" -o "$ccblack" == "match" ]; then
+ echo "$ip." >> $matchfile
+ fi
+ ;;
+ *)
+ echo "$ip." >> $dupfile
+ ;;
+ esac
+ done
+else
+ echo; echo "MaxMind Binary Database Missing [ $pathgeoipdat ], skipping d-dedup Process"; echo
+ echo "MaxMind Binary Database Missing [ $pathgeoipdat ], skipping d-dedup Process [ $now ]" >> $errorlog
+fi
+if [ -s "$matchfile" -a "$ccwhite" == "match" ]; then
+ echo "Processing [ Match ] IPs"
+ match=$(sed -e 's/^/^/' -e 's/\./\\\./g' $matchfile)
+ for mfile in $match; do
+ grep $mfile $pfbdeny*.txt >> $tempfile
+ done
+ sed 's/$/0\/24/' $matchfile >> $tempmatchfile
+ sed -e 's/.*://' -e 's/^/\!/' $tempfile >> $tempmatchfile
+ mv -f $tempmatchfile $pfbmatch$matchdedup
+ mcount=$(grep -c ^ $tempfile)
+ mmcount=$(($mcount + $mmcount))
+fi
+# Find Repeat Offenders in each individual Blocklist Outfile
+if [ -s "$dupfile" ]; then
+ echo "Processing [ Block ] IPs"
+ dup=$(cat $dupfile)
+ for ip in $dup; do
+ pcount=1; ii=$(echo "^$ip" | sed 's/\./\\\./g')
+ list=$(find $pfbdeny ! -name "pfB*.txt" ! -name "*_v6.txt" -type f | xargs grep -al $ii)
+ for blfile in $list; do
+ header=$(echo "${blfile##*/}" | cut -d '.' -f1)
+ grep $ii $blfile > $tempfile
+ if [ "$ccblack" == "block" ]; then
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $blfile > $tempfile2; mv -f $tempfile2 $blfile
+ if [ "$pcount" -eq "1" ]; then
+ echo $ip"0/24" >> $blfile
+ echo $header" "$ip >> $dedupfile
+ echo $header" "$ip"0/24" >> $addfile
+ pcount=2
+ else
+ echo $header" "$ip >> $dedupfile
+ fi
+ else
+ if [ "$pcount" -eq "1" ]; then
+ matchoutfile="match"$header".txt"
+ echo $ip"0/24" >> $pfbmatch$matchoutfile
+ sed 's/^/\!/' $tempfile >> $pfbmatch$matchoutfile
+ mcount=$(grep -c ^ $pfbmatch$matchoutfile)
+ mmcount=$(($mcount + $mmcount))
+ pcount=2
+ fi
+ fi
+ done
+ done
+ # Remove Repeat Offenders in Masterfiles
+ if [ -s "$dedupfile" ]; then
+ echo "Removing [ Block ] IPs"
+ > $tempfile; > $tempfile2
+ sed 's/\./\\\./g' $dedupfile > $tempfile2
+ while IFS=' ' read -r ips; do grep "$ips" $masterfile >> $tempfile; done < $tempfile2
+ dcount=$(grep -c ^ $tempfile)
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ cat $addfile >> $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+ fi
+fi
+
+echo; echo "d-Duplication Process [ $now ]"; echo "------------------------------------------------"
+echo; echo "Found [ $count ] IP range(s) over the threshold of dmax= [ $max ]"
+echo "Found [ $safe ] IP range(s) classified as Whitelisted"
+echo; echo "Found [ $dcount ] CC Blacklisted IP Address(es) are being set to [ $ccblack ]"
+echo "Found [ $mmcount ] CC Whitelisted IP Address(es) are being set to [ $ccwhite ]"; echo
+if [ -s "$addfile" ]; then
+ echo; echo "Removed the following IP Ranges"
+ sed -e 's/^.* //' -e 's/0\/24//' $addfile | tr '\n' '|'; echo
+fi
+count=$(grep -c ^ $masterfile)
+echo " [ Post d-Deduplication count ] [ $count ]"; echo
+
+# Write "1.1.1.1" to empty Final Blocklist Files
+emptyfiles=$(find $pfbdeny -size 0)
+for i in $emptyfiles; do echo "1.1.1.1" > $i; done
+}
+
+
+##########
+# Process to perform a final De-Duplication on all of the BlockLists (Excluding Country Whitelist) ("pmax" variable).
+pdeduplication(){
+
+if [ ! -x $pathgeoip ]; then
+ echo "p-duplication - Application [ GeoIP ] Not found. Can't proceed."
+ echo "p-duplication - Application [ GeoIP ] Not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+# Download MaxMind GeoIP.dat on first Install.
+if [ ! -f $pathgeoipdat ]; then
+ echo "Downloading [ MaxMind GeoIP.dat ] [ $now ]" >> $geoiplog
+ /usr/local/pkg/pfblockerng/geoipupdate.sh bu
+fi
+# Exit if GeoIP.dat is not found.
+if [ ! -f $pathgeoipdat ]; then
+ echo "p-duplication - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed."
+ echo "p-duplication - Database GeoIP [ GeoIP.Dat ] not found. Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+> $tempfile; > $tempfile2; > $dupfile; > $addfile; > $dedupfile; count=0; dcount=0
+echo; echo "====================================================================="
+echo; echo "Querying for Repeat Offenders"
+data="$(find $pfbdeny ! -name "pfB*.txt" ! -name "*_v6.txt" -type f | cut -d '.' -f 1-3 $pfbdeny*.txt |
+ awk -v max="$max" '{a[$0]++}END{for(i in a){if(a[i] > max){print i}}}' | grep -v "^1\.1\.1")"
+count=$(echo "$data" | grep -c ^)
+if [ "$data" == "" ]; then count=0; fi
+# Find Repeat Offenders in each individual Blocklist Outfile
+echo "Processing [ Block ] IPs"
+for ip in $data; do
+ pcount=1; ii=$(echo "^$ip." | sed 's/\./\\\./g')
+ list=$(find $pfbdeny ! -name "pfB*.txt" ! -name "*_v6.txt" -type f | xargs grep -al $ii)
+ for blfile in $list; do
+ header=$(echo "${blfile##*/}" | cut -d '.' -f1)
+ grep $ii $blfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $blfile > $tempfile2; mv -f $tempfile2 $blfile
+ if [ "$pcount" -eq "1" ]; then
+ echo $ip".0/24" >> $blfile
+ echo $header" $ip." >> $dedupfile
+ echo $header" "$ip".0/24" >> $addfile
+ pcount=2
+ else
+ echo $header" $ip." >> $dedupfile
+ fi
+ done
+done
+# Remove Repeat Offenders in Masterfile
+if [ -s "$dedupfile" ]; then
+ echo "Removing [ Block ] IPs"
+ > $tempfile; > $tempfile2
+ sed 's/\./\\\./g' $dedupfile > $tempfile2
+ while IFS=' ' read -r ips; do grep "$ips" $masterfile >> $tempfile; done < $tempfile2
+ dcount=$(grep -c ^ $tempfile)
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ cat $addfile >> $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+fi
+
+echo; echo "p-Duplication Process [ $now ]"; echo "------------------------------------------------"
+echo "Found [ $dcount ] IP Address(es) are being set to [ block ]"
+if [ -s "$addfile" ]; then
+ echo; echo "Removed the following IP Ranges"
+ sed -e 's/^.* //' -e 's/0\/24//' $addfile | tr '\n' '|'; echo
+fi
+count=$(grep -c ^ $masterfile)
+echo; echo " [ Post p-Deduplication count ] [ $count ]"
+
+# Write "1.1.1.1" to empty Final Blocklist Files
+emptyfiles=$(find $pfbdeny -size 0)
+for i in $emptyfiles; do echo "1.1.1.1" > $i; done
+}
+
+
+##########
+# Process to Split ET Pro IPREP into Category Files and Compile selected Blocked categories into Outfile
+processet() {
+
+if [ ! -x $pathgunzip ]; then
+ echo "Application [ Gunzip ] Not found, Can't proceed."
+ echo "Application [ Gunzip ] Not found, Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+if [ -s $pfborig$alias".gz" ]; then
+ evar="ET_*"
+ # Remove Previous ET IPRep Files
+ [ -d $etdir ] && [ "$(ls -A $etdir)" ] && rm -r $etdir/$evar
+ > $tempfile; > $tempfile2
+
+ $pathgunzip -c $pfborig$alias".gz" > $pfborig$alias".raw"
+
+ # ET CSV Format (IP, Category, Score)
+ echo; echo "Processing [ $alias ]"
+ while IFS="," read a b c; do
+ # Some ET Categories are not in use (For Future Use)
+ case "$b" in
+ 1) echo $a >> $etdir/ET_Cnc;;
+ 2) echo $a >> $etdir/ET_Bot;;
+ 3) echo $a >> $etdir/ET_Spam;;
+ 4) echo $a >> $etdir/ET_Drop;;
+ 5) echo $a >> $etdir/ET_Spywarecnc;;
+ 6) echo $a >> $etdir/ET_Onlinegaming;;
+ 7) echo $a >> $etdir/ET_Drivebysrc;;
+ 8) echo $a >> $etdir/ET_Cat8;;
+ 9) echo $a >> $etdir/ET_Chatserver;;
+ 10) echo $a >> $etdir/ET_Tornode;;
+ 11) echo $a >> $etdir/ET_Cat11;;
+ 12) echo $a >> $etdir/ET_Cat12;;
+ 13) echo $a >> $etdir/ET_Compromised;;
+ 14) echo $a >> $etdir/ET_Cat14;;
+ 15) echo $a >> $etdir/ET_P2P;;
+ 16) echo $a >> $etdir/ET_Proxy;;
+ 17) echo $a >> $etdir/ET_Ipcheck;;
+ 18) echo $a >> $etdir/ET_Cat18;;
+ 19) echo $a >> $etdir/ET_Utility;;
+ 20) echo $a >> $etdir/ET_DDos;;
+ 21) echo $a >> $etdir/ET_Scanner;;
+ 22) echo $a >> $etdir/ET_Cat22;;
+ 23) echo $a >> $etdir/ET_Brute;;
+ 24) echo $a >> $etdir/ET_Fakeav;;
+ 25) echo $a >> $etdir/ET_Dyndns;;
+ 26) echo $a >> $etdir/ET_Undesireable;;
+ 27) echo $a >> $etdir/ET_Abusedtld;;
+ 28) echo $a >> $etdir/ET_Selfsignedssl;;
+ 29) echo $a >> $etdir/ET_Blackhole;;
+ 30) echo $a >> $etdir/ET_RAS;;
+ 31) echo $a >> $etdir/ET_P2Pcnc;;
+ 32) echo $a >> $etdir/ET_Sharedhosting;;
+ 33) echo $a >> $etdir/ET_Parking;;
+ 34) echo $a >> $etdir/ET_VPN;;
+ 35) echo $a >> $etdir/ET_Exesource;;
+ 36) echo $a >> $etdir/ET_Cat36;;
+ 37) echo $a >> $etdir/ET_Mobilecnc;;
+ 38) echo $a >> $etdir/ET_Mobilespyware;;
+ 39) echo $a >> $etdir/ET_Skypenode;;
+ 40) echo $a >> $etdir/ET_Bitcoin;;
+ 41) echo $a >> $etdir/ET_DDosattack;;
+ *) echo $a >> $etdir/ET_Unknown;;
+ esac
+ done <"$pfborig$alias.raw"
+ data=$(ls $etdir)
+ echo "Compiling ET IP IQRisk REP Lists based upon User Selected Categories"
+ printf "%-10s %-25s\n" " Action" "Category"
+ echo "-------------------------------------------"
+
+ for list in $data; do
+ case "$etblock" in
+ *$list*)
+ printf "%-10s %-25s\n" " Block: " "$list"
+ cat $etdir/$list >> $tempfile
+ ;;
+ esac
+ case "$etmatch" in
+ *$list*)
+ printf "%-10s %-25s\n" " Match: " "$list"
+ cat $etdir/$list >> $tempfile2
+ ;;
+ esac
+ done
+ echo "-------------------------------------------"
+
+ if [ -f $tempfile ]; then mv -f $tempfile $pfborig$alias".orig"; fi
+ if [ "$etmatch" != "x" ]; then mv -f $tempfile2 $pfbmatch/ETMatch.txt; fi
+ cicount=$(cat $etdir/$evar | grep -cv '^#\|^$'); cocount=$(grep -cv "^1\.1\.1\.1" $pfborig$alias".orig")
+ echo; echo "ET Folder count [ $cicount ] Outfile count [ $cocount ]"
+else
+ echo; echo "No ET .GZ File Found!"
+fi
+}
+
+# Process to extract IP addresses from XLSX Files
+processxlsx() {
+
+if [ ! -x $pathtar ]; then
+ echo "Application [ TAR ] Not found, Can't proceed."
+ echo "Application [ TAR ] Not found, Can't proceed. [ $now ]" >> $errorlog
+ exit
+fi
+
+if [ -s $pfborig$alias".zip" ]; then
+
+ $pathtar -xf $pfborig$alias".zip" -C $tmpxlsx
+ $pathtar -xOf $tmpxlsx*.[xX][lL][sS][xX] xl/sharedStrings.xml |
+ grep -aoEw "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" | sort | uniq > $pfborig$alias".orig"
+ rm -r $tmpxlsx*
+
+ cocount=$(grep -cv "^1\.1\.1\.1" $pfborig$alias".orig")
+ echo; echo "Download file count [ ZIP file ] Outfile count [ $cocount ]"
+else
+ echo "XLSX Download File Missing"
+ echo " [ $alias ] XLSX Download File Missing [ $now ]" >> $errorlog
+fi
+}
+
+closingprocess() {
+
+# Write "1.1.1.1" to empty Final Blocklist Files
+emptyfiles=$(find $pfbdeny -size 0)
+for i in $emptyfiles; do echo "1.1.1.1" > $i; done
+
+if [ -d "$pfborig" ] && [ "$(ls -A $pfborig)" ]; then
+ fcount=$(find $pfborig*.orig | xargs cat | grep -cv '^#\|^$')
+else
+ fcount=0
+fi
+
+if [ "$alias" == "on" ]; then
+ sort -o $masterfile $masterfile
+ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n $mastercat > $tempfile; mv -f $tempfile $mastercat
+
+ echo; echo; echo "===[ FINAL Processing ]====================================="; echo
+ echo " [ Original count ] [ $fcount ]"
+ count=$(grep -c ^ $masterfile)
+ echo; echo " [ Processed Count ] [ $count ]"; echo
+
+ s1=$(grep -cv "1\.1\.1\.1" $masterfile)
+ s2=$(find $pfbdeny ! -name "*_v6.txt" -type f | xargs cat | grep -cv "^1\.1\.1\.1")
+ s3=$(sort $mastercat | uniq -d | tail -30)
+ s4=$(find $pfbdeny ! -name "*_v6.txt" -type f | xargs cat | sort | uniq -d | tail -30 | grep -v "^1\.1\.1\.1")
+
+ if [ -d "$pfbpermit" ] && [ "$(ls -A $pfbpermit)" ]; then
+ echo; echo "===[ Permit List IP Counts ]========================="; echo
+ wc -l $pfbpermit* | sort -n -r
+ fi
+ if [ -d "$pfbmatch" ] && [ "$(ls -A $pfbmatch)" ]; then
+ echo; echo "===[ Match List IP Counts ]=========================="; echo
+ wc -l $pfbmatch* | sort -n -r
+ fi
+ if [ -d "$pfbdeny" ] && [ "$(ls -A $pfbdeny)" ]; then
+ echo; echo "===[ Deny List IP Counts ]==========================="; echo
+ wc -l $pfbdeny* | sort -n -r
+ fi
+ if [ -d "$pfbnative" ] && [ "$(ls -A $pfbnative)" ]; then
+ echo; echo "===[ Native List IP Counts ] ==================================="; echo
+ wc -l $pfbnative* | sort -n -r
+ fi
+ if [ -d "$pfbdeny" ] && [ "$(ls -A $pfbdeny)" ]; then
+ emptylists=$(grep "1\.1\.1\.1" $pfbdeny* | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:1.1.1.1/ /')
+ if [ ! -z "$emptylists" ]; then
+ echo; echo "====================[ Empty Lists w/1.1.1.1 ]=================="; echo
+ for list in $emptylists; do
+ echo $list
+ done
+ fi
+ fi
+ if [ -d "$pfborig" ] && [ "$(ls -A $pfborig)" ]; then
+ echo; echo "====================[ Last Updated List Summary ]=============="; echo
+ ls -lahtr $pfborig* | sed -e 's/\/.*\// /' -e 's/.orig//' | awk -v OFS='\t' '{print $6" "$7,$8,$9}'
+ fi
+ echo "==============================================================="; echo
+ echo "Sanity Check (Not Including IPv6) ** These two Counts should Match! **"
+ echo "------------"
+ echo "Masterfile Count [ $s1 ]"
+ echo "Deny folder Count [ $s2 ]"; echo
+ echo "Duplication Sanity Check (Pass=No IPs reported)"
+ echo "------------------------"
+ echo "Masterfile/Deny Folder Uniq check"
+ if [ ! -z "$s3" ]; then echo $s3; fi
+ echo "Deny Folder/Masterfile Uniq check"
+ if [ ! -z "$s4" ]; then echo $s4; fi
+ echo; echo "Sync Check (Pass=No IPs reported)"
+ echo "----------"
+else
+ echo; echo "===[ FINAL Processing ]============================================="; echo
+ echo " [ Original count ] [ $fcount ]"
+ if [ -d "$pfbpermit" ] && [ "$(ls -A $pfbpermit)" ]; then
+ echo; echo "===[ Permit List IP Counts ]========================="; echo
+ wc -l $pfbpermit* | sort -n -r
+ fi
+ if [ -d "$pfbmatch" ] && [ "$(ls -A $pfbmatch)" ]; then
+ echo; echo "===[ Match List IP Counts ]=========================="; echo
+ wc -l $pfbmatch* | sort -n -r
+ fi
+ if [ -d "$pfbdeny" ] && [ "$(ls -A $pfbdeny)" ]; then
+ echo; echo "===[ Deny List IP Counts ]==========================="; echo
+ wc -l $pfbdeny* | sort -n -r
+ fi
+ if [ -d "$pfbnative" ] && [ "$(ls -A $pfbnative)" ]; then
+ echo; echo "===[ Native List IP Counts ] ==================================="; echo
+ wc -l $pfbnative* | sort -n -r
+ fi
+ if [ -d "$pfbdeny" ] && [ "$(ls -A $pfbdeny)" ]; then
+ emptylists=$(grep "1\.1\.1\.1" $pfbdeny* | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:1.1.1.1/ /')
+ if [ ! -z "$emptylists" ]; then
+ echo; echo "====================[ Empty Lists w/1.1.1.1 ]=================="; echo
+ for list in $emptylists; do
+ echo $list
+ done
+ fi
+ fi
+ if [ -d "$pfborig" ] && [ "$(ls -A $pfborig)" ]; then
+ echo; echo "====================[ Last Updated List Summary ]=============="; echo
+ ls -lahtr $pfborig* | sed -e 's/\/.*\// /' -e 's/.orig//' | awk -v OFS='\t' '{print $6" "$7,$8,$9}'
+ echo "==============================================================="
+ fi
+fi
+
+echo; echo "IPv4 Alias Table IP Total"; echo "-----------------------------"
+find $pfsense_alias_dir ! -name "*_v6.txt" -type f | xargs cat | grep -c ^
+
+echo; echo "IPv6 Alias Table IP Total"; echo "-----------------------------"
+find $pfsense_alias_dir -name "*_v6.txt" -type f | xargs cat | grep -c ^
+
+echo; echo "Alias Table IP Counts"; echo "-----------------------------"
+wc -l $pfsense_alias_dir*.txt | sort -n -r
+
+echo; echo "pfSense Table Stats"; echo "-------------------"
+$pathpfctl -s memory | grep "table-entries"
+pfctlcount=$($pathpfctl -vvsTables | awk '/Addresses/ {s+=$2}; END {print s}')
+echo "Table Usage Count " $pfctlcount
+}
+
+remove() {
+# Remove Lists from Masterfiles and Delete Associated Files
+echo
+for i in $cc; do
+ header=$(echo "${i%*,}")
+ if [ ! "$header" == "" ]; then
+ # Make sure that Alias Exists in Masterfile before removal.
+ masterchk=$(grep -m1 "$header[[:space:]]" $masterfile)
+ if [ ! -z "$masterchk" ]; then
+ # Grep Header with a Trailing Space character
+ grep "$header[[:space:]]" $masterfile > $tempfile
+ awk 'FNR==NR{a[$0];next}!($0 in a)' $tempfile $masterfile > $tempfile2; mv -f $tempfile2 $masterfile
+ cut -d' ' -f2 $masterfile > $mastercat
+ fi
+ rm -rf $pfborig$header*; rm -rf $pfbdeny$header*; rm -rf $pfbmatch$header*; rm -rf $pfbpermit$header*; rm -rf $pfbnative$header*
+ echo "The Following list has been REMOVED [ $header ]"
+ fi
+ echo
+done
+
+# Delete Masterfiles if they are empty
+emptychk=$(find $masterfile -size 0)
+if [ ! "$emptychk" == "" ]; then
+ rm -r $masterfile; rm -r $mastercat
+fi
+}
+
+
+##########
+# CALL APPROPRIATE PROCESSES using Script Argument $1
+case $1 in
+ continent)
+ continent
+ ;;
+ duplicate)
+ process255
+ duplicate
+ ;;
+ suppress)
+ suppress
+ ;;
+ p24)
+ process24
+ ;;
+ dedup)
+ deduplication
+ ;;
+ pdup)
+ pdeduplication
+ ;;
+ et)
+ processet
+ ;;
+ xlsx)
+ processxlsx
+ ;;
+ closing)
+ closingprocess
+ ;;
+ remove)
+ remove
+ ;;
+ *)
+ exit
+ ;;
+esac
+exit \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.widget.php b/config/pfblockerng/pfblockerng.widget.php
new file mode 100644
index 00000000..647017ff
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.widget.php
@@ -0,0 +1,280 @@
+<?php
+/*
+ pfBlockerNG.widget.php
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based Upon pfblocker :
+ Copyright 2011 Thomas Schaefer - Tomschaefer.org
+ Copyright 2011 Marcello Coutinho
+ Part of pfSense widgets (www.pfsense.org)
+
+ Adapted From:
+ snort_alerts.widget.php
+ Copyright (C) 2009 Jim Pingle
+ mod 24-07-2012
+ mod 28-02-2014 by Bill Meeks
+
+ Javascript and Integration modifications by J. Nieuwenhuizen
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+@require_once("/usr/local/www/widgets/include/widget-pfblockerng.inc");
+@require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+@require_once("guiconfig.inc");
+@require_once("globals.inc");
+@require_once("pfsense-utils.inc");
+@require_once("functions.inc");
+
+pfb_global();
+
+// Ackwnowlege Failed Downloads
+if (isset($_POST['pfblockerngack'])) {
+ $clear = exec("/usr/bin/sed -i '' 's/FAIL/Fail/g' {$pfb['errlog']}");
+ header("Location: ../../index.php");
+}
+
+// This function will create the counts
+function pfBlockerNG_get_counts() {
+ global $config, $g, $pfb;
+
+ // Collect Alias Count and Update Date/Time
+ $pfb_table = array();
+ $out = "<img src ='/themes/{$g['theme']}/images/icons/icon_interface_down.gif' title=\"No Rules are Defined using this Alias\" alt=\"\" />";
+ $in = "<img src ='/themes/{$g['theme']}/images/icons/icon_interface_up.gif' title=\"Rules are Defined using this Alias\" alt=\"\" />";
+ if (is_array($config['aliases']['alias'])) {
+ foreach ($config['aliases']['alias'] as $cbalias) {
+ if (preg_match("/pfB_/", $cbalias['name'])) {
+ if (file_exists("{$pfb['aliasdir']}/{$cbalias['name']}.txt")) {
+ preg_match("/(\d+)/", exec("/usr/bin/grep -cv \"^1\.1\.1\.1\" {$pfb['aliasdir']}/{$cbalias['name']}.txt"), $matches);
+ $pfb_table[$cbalias['name']] = array("count" => $matches[1], "img" => $out);
+ $updates = exec("ls -ld {$pfb['aliasdir']}/{$cbalias['name']}.txt | awk '{ print $6,$7,$8 }'", $update);
+ $pfb_table[$cbalias['name']]['up'] = $updates;
+ }
+ }
+ }
+ }
+
+ // Collect if Rules are defined using pfBlockerNG Aliases.
+ if (is_array($config['filter']['rule'])) {
+ foreach ($config['filter']['rule'] as $rule) {
+ if (preg_match("/pfB_/",$rule['source']['address']) || preg_match("/pfb_/",$rule['source']['address'])) {
+ $pfb_table[$rule['source']['address']]['img'] = $in;
+ }
+ if (preg_match("/pfB_/",$rule['destination']['address']) || preg_match("/pfb_/",$rule['destination']['address'])) {
+ $pfb_table[$rule['destination']['address']]['img'] = $in;
+ }
+ }
+ return $pfb_table;
+ }
+}
+
+// Status Indicator if pfBlockerNG is Enabled/Disabled
+if ("{$pfb['enable']}" == "on") {
+ $pfb_status = "/themes/{$g['theme']}/images/icons/icon_pass.gif";
+ $pfb_msg = "pfBlockerNG is Active.";
+} else {
+ $pfb_status = "/themes/{$g['theme']}/images/icons/icon_block.gif";
+ $pfb_msg = "pfBlockerNG is Disabled.";
+}
+
+// Collect Total IP/Cidr Counts
+$dcount = exec("cat {$pfb['denydir']}/*.txt | grep -cv '^#\|^$\|^1\.1\.1\.1'");
+$pcount = exec("cat {$pfb['permitdir']}/*.txt | grep -cv '^#\|^$\|^1\.1\.1\.1'");
+$mcount = exec("cat {$pfb['matchdir']}/*.txt | grep -cv '^#\|^$\|^1\.1\.1\.1'");
+$ncount = exec("cat {$pfb['nativedir']}/*.txt | grep -cv '^#\|^$\|^1\.1\.1\.1'");
+
+// Collect Number of Suppressed Hosts
+if (file_exists("{$pfb['supptxt']}")) {
+ $pfbsupp_cnt = exec ("/usr/bin/grep -c ^ {$pfb['supptxt']}");
+} else {
+ $pfbsupp_cnt = 0;
+}
+
+#check rule count
+#(label, evaluations,packets total, bytes total, packets in, bytes in,packets out, bytes out)
+$packets = exec("/sbin/pfctl -s labels", $debug);
+if (!empty($debug)) {
+ foreach ($debug as $line) {
+ // Auto-Rules start with 'pfB_', Alias Rules should start with 'pfb_' and exact spelling of Alias Name.
+ $line = str_replace("pfb_","pfB_",$line);
+ if ("{$pfb['pfsenseversion']}" >= '2.2') {
+ #USER_RULE: pfB_Top auto rule 8494 17 900 17 900 0 0 0
+ if (preg_match("/USER_RULE: (\w+).*\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+/", $line, $matches)) {
+ if (isset($matches)) {
+ ${$matches[1]}+=$matches[2];
+ } else {
+ ${$matches[1]} = 'Err';
+ }
+ }
+ } else {
+ #USER_RULE: pfB_Top auto rule 1656 0 0 0 0 0 0
+ if (preg_match("/USER_RULE: (\w+).*\s+\d+\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+/", $line, $matches)) {
+ if (isset($matches)) {
+ ${$matches[1]}+=$matches[2];
+ } else {
+ ${$matches[1]} = 'Err';
+ }
+ }
+ }
+ }
+}
+
+// Called by Ajax to update alerts table contents
+if (isset($_GET['getNewCounts'])) {
+ $response = "";
+ $pfb_table = pfBlockerNG_get_counts();
+ if (!empty($pfb_table)) {
+ foreach ($pfb_table as $alias => $values){
+ if (!isset(${$alias})) { ${$alias} = "-";}
+ $response .= $alias . "||" . $values['count'] . "||" . ${$alias} . "||" . $values['up'] . "||" . $values['img'] . "\n";
+ }
+ echo $response;
+ return;
+ }
+}
+
+// Report any Failed Downloads
+$results = array();
+$fails = exec("grep $(date +%m/%d/%y) {$pfb['errlog']} | grep 'FAIL'", $results);
+
+// Print widget Status Bar Items
+?>
+ <div class="marinarea">
+ <table border="0" cellspacing="0" cellpadding="0">
+ <thead>
+ <tr>
+ <td valign="middle">&nbsp;<img src="<?= $pfb_status ?>" width="13" height="13" border="0" title="<?=gettext($pfb_msg) ?>" alt="" /></td>
+ <td valign="middle">&nbsp;&nbsp;</td>
+ <td valign="middle" p style="font-size:10px">
+ <?php if ($dcount != 0): ?>
+ <?=gettext("Deny:"); echo("&nbsp;<strong>" . $dcount . "</strong>") ?>
+ <?php endif; ?>
+ <?php if ($pcount != 0): ?>
+ <?=gettext("&nbsp;Permit:"); echo("&nbsp;<strong>" . $pcount . "</strong>") ?>
+ <?php endif; ?>
+ <?php if ($mcount != 0): ?>
+ <?=gettext("&nbsp;Match:"); echo("&nbsp;<strong>" . $mcount . "</strong>"); ?>
+ <?php endif; ?>
+ <?php if ($ncount != 0): ?>
+ <?=gettext("&nbsp;Native:"); echo("&nbsp;<strong>" . $ncount . "</strong>"); ?>
+ <?php endif; ?>
+ <?php if ($pfbsupp_cnt != 0): ?>
+ <?=gettext("&nbsp;Supp:"); echo("&nbsp;<strong>" . $pfbsupp_cnt . "</strong>"); ?>
+ <?php endif; ?></td>
+ <td valign="middle">&nbsp;&nbsp;</td>
+ <td valign="top"><a href="pfblockerng/pfblockerng_log.php"><img src="/themes/<?=$g['theme']; ?>/images/icons/icon_logs.gif" width="13" height="13" border="0" title="<?=gettext("View pfBlockerNG Logs TAB") ?>" alt="" /></a>&nbsp;
+ <td valign="top">
+ <?php if (!empty($results)): ?> <!--Hide "Ack" Button when Failed Downloads are Empty-->
+ <form action="/widgets/widgets/pfblockerng.widget.php" method="post" name="widget_pfblockerng_ack">
+ <input type="hidden" value="clearack" name="pfblockerngack" />
+ <input class="vexpl" type="image" name="pfblockerng_ackbutton" src="/themes/<?=$g['theme']; ?>/images/icons/icon_x.gif" width="14" height="14" border="0" title="<?=gettext("Clear Failed Downloads") ?>"/>
+ </form>
+ <?php endif; ?>
+ </td>
+ </tr>
+ </thead>
+ </table>
+ </div>
+
+ <table id="pfb-tblfails" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tbody id="pfb-fails">
+<?php
+
+if ("{$pfb['pfsenseversion']}" > '2.0') {
+ $alertRowEvenClass = "listMReven";
+ $alertRowOddClass = "listMRodd";
+ $alertColClass = "listMRr";
+} else {
+ $alertRowEvenClass = "listr";
+ $alertRowOddClass = "listr";
+ $alertColClass = "listr";
+}
+
+# Last errors first
+$results = array_reverse($results);
+
+$counter = 0;
+# Max errors to display
+$maxfailcount = 3;
+if (!empty($results)) {
+ foreach ($results as $result) {
+ $alertRowClass = $counter % 2 ? $alertRowEvenClass : $alertRowOddClass;
+ if (!isset(${$alias})) { ${$alias} = "-";}
+ echo(" <tr class='" . $alertRowClass . "'><td class='" . $alertColClass . "'>" . $result . "</td><tr>");
+ $counter++;
+ if ($counter > $maxfailcount) {
+ # To many errors stop displaying
+ echo(" <tr class='" . $alertRowClass . "'><td class='" . $alertColClass . "'>" . (count($results) - $maxfailcount) . " more error(s)...</td><tr>");
+ break;
+ }
+ }
+}
+
+// Print Main Table Header
+?>
+ </tbody>
+ </table>
+ <table id="pfb-tbl" width="100%" border="0" cellspacing="0" cellpadding="0">
+ <thead>
+ <tr>
+ <th class="widgetsubheader" align="center"><?=gettext("Alias");?></th>
+ <th title="The count can be a mixture of Single IPs or CIDR values" class="widgetsubheader" align="center"><?=gettext("Count");?></th>
+ <th title="Packet Counts can be cleared by the pfSense filter_configure() function. Make sure Rule Descriptions start with 'pfB_'" class="widgetsubheader" align="center"><?=gettext("Packets");?></th>
+ <th title="Last Update (Date/Time) of the Alias " class="widgetsubheader" align="center"><?=gettext("Updated");?></th>
+ <th class="widgetsubheader" align="center"><?php echo $out; ?><?php echo $in; ?></th>
+ </tr>
+ </thead>
+ <tbody id="pfbNG-entries">
+<?php
+// Print Main Table Body
+$pfb_table = pfBlockerNG_get_counts();
+$counter=0;
+if (is_array($pfb_table)) {
+ foreach ($pfb_table as $alias => $values) {
+ $evenRowClass = $counter % 2 ? " listMReven" : " listMRodd";
+ if (!isset(${$alias})) { ${$alias} = "-";}
+ echo(" <tr class='" . $evenRowClass . "'>
+ <td class='listMRr ellipsis'>{$alias}</td>
+ <td class='listMRr' align='center'>{$values['count']}</td>
+ <td class='listMRr' align='center'>{${$alias}}</td>
+ <td class='listMRr' align='center'>{$values['up']}</td>
+ <td class='listMRr' align='center'>{$values['img']}</td>
+ </tr>");
+ $counter++;
+ }
+}
+
+?>
+</tbody>
+</table>
+
+<script type="text/javascript">
+//<![CDATA[
+ var pfBlockerNGupdateDelay = 10000; // update every 10000 ms
+//]]>
+</script> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng.xml b/config/pfblockerng/pfblockerng.xml
new file mode 100644
index 00000000..e2f4b508
--- /dev/null
+++ b/config/pfblockerng/pfblockerng.xml
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ======================================================================================= */
+/*
+ pfBlockerNG.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+/*
+/* ====================================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+/*
+/* ====================================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockerng</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: General Settings</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <configfile>pfblockerng.xml</configfile>
+ <tooltiptext>Configure pfBlockerNG</tooltiptext>
+ <section>Firewall</section>
+ <url>/pkg_edit.php?xml=pfblockerng.xml</url>
+ </menu>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.priv.inc</item>
+ <prefix>/etc/inc/priv/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.inc</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.php</item>
+ <prefix>/usr/local/www/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_alerts.php</item>
+ <prefix>/usr/local/www/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_update.php</item>
+ <prefix>/usr/local/www/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_log.php</item>
+ <prefix>/usr/local/www/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_diag_dns.php</item>
+ <prefix>/usr/local/www/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.widget.php</item>
+ <prefix>/usr/local/www/widgets/widgets/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/widget-pfblockerng.inc</item>
+ <prefix>/usr/local/www/widgets/include/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.js</item>
+ <prefix>/usr/local/www/widgets/javascript/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_top20.xml</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_v4lists.xml</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_v6lists.xml</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng_sync.xml</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0644</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/countrycodes.tar.bz2</item>
+ <prefix>/var/db/pfblockerng/cc/</prefix>
+ <chmod>0444</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/pfblockerng.sh</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <additional_files_needed>
+ <item>https://packages.pfsense.org/packages/config/pfblockerng/geoipupdate.sh</item>
+ <prefix>/usr/local/pkg/pfblockerng/</prefix>
+ <chmod>0755</chmod>
+ </additional_files_needed>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <name>pfBlockerNG General Settings</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname></fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]></description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Enable pfBlockerNG</strong>]]></fielddescr>
+ <fieldname>enable_cb</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[Note - with "Keep settings" enabled, pfBlockerNG will maintain run state on Installation/Upgrade<br />
+ If "Keep Settings" is not "enabled" on pkg Install/De-Install, all Settings will be Wiped!]]></description>
+ </field>
+ <field>
+ <fielddescr>CRON MIN Start Time</fielddescr>
+ <fieldname>pfb_min</fieldname>
+ <description><![CDATA[Default: <strong> : 00</strong><br />
+ Select Cron Update Minute ]]></description>
+ <type>select</type>
+ <options>
+ <option><name> : 00</name><value>0</value></option>
+ <option><name> : 15</name><value>15</value></option>
+ <option><name> : 30</name><value>30</value></option>
+ <option><name> : 45</name><value>45</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>CRON Base Hour Start Time</fielddescr>
+ <fieldname>pfb_hour</fieldname>
+ <description><![CDATA[Default: <strong> 1 </strong><br />
+ Select Cron Base Start Hour ]]></description>
+ <type>select</type>
+ <options>
+ <option><name>1</name><value>0</value></option>
+ <option><name>0</name><value>1</value></option>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ <option><name>4</name><value>4</value></option>
+ <option><name>5</name><value>5</value></option>
+ <option><name>6</name><value>6</value></option>
+ <option><name>7</name><value>7</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>9</name><value>9</value></option>
+ <option><name>10</name><value>10</value></option>
+ <option><name>11</name><value>11</value></option>
+ <option><name>12</name><value>12</value></option>
+ <option><name>13</name><value>13</value></option>
+ <option><name>14</name><value>14</value></option>
+ <option><name>15</name><value>15</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>17</name><value>17</value></option>
+ <option><name>18</name><value>18</value></option>
+ <option><name>19</name><value>19</value></option>
+ <option><name>20</name><value>20</value></option>
+ <option><name>21</name><value>21</value></option>
+ <option><name>22</name><value>22</value></option>
+ <option><name>23</name><value>23</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>'Daily/Weekly' Start Hour</fielddescr>
+ <fieldname>pfb_dailystart</fieldname>
+ <description><![CDATA[Default: <strong> 1 </strong><br />
+ Select 'Daily' Schedule Start Hour <br />
+ This is used for the 'Daily/Weekly' Scheduler Only.]]></description>
+ <type>select</type>
+ <options>
+ <option><name>1</name><value>0</value></option>
+ <option><name>0</name><value>1</value></option>
+ <option><name>2</name><value>2</value></option>
+ <option><name>3</name><value>3</value></option>
+ <option><name>4</name><value>4</value></option>
+ <option><name>5</name><value>5</value></option>
+ <option><name>6</name><value>6</value></option>
+ <option><name>7</name><value>7</value></option>
+ <option><name>8</name><value>8</value></option>
+ <option><name>9</name><value>9</value></option>
+ <option><name>10</name><value>10</value></option>
+ <option><name>11</name><value>11</value></option>
+ <option><name>12</name><value>12</value></option>
+ <option><name>13</name><value>13</value></option>
+ <option><name>14</name><value>14</value></option>
+ <option><name>15</name><value>15</value></option>
+ <option><name>16</name><value>16</value></option>
+ <option><name>17</name><value>17</value></option>
+ <option><name>18</name><value>18</value></option>
+ <option><name>19</name><value>19</value></option>
+ <option><name>20</name><value>20</value></option>
+ <option><name>21</name><value>21</value></option>
+ <option><name>22</name><value>22</value></option>
+ <option><name>23</name><value>23</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable De-Duplication</fielddescr>
+ <fieldname>enable_dup</fieldname>
+ <type>checkbox</type>
+ <description>Only for IPv4 Lists</description>
+ </field>
+ <field>
+ <fielddescr>Enable Suppression</fielddescr>
+ <fieldname>suppression</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[This will prevent Selected IPs from being Blocked. Only for IPv4 Lists (/32 and /24).<br />
+ Country Blocking Lists cannot be Suppressed.<br />
+ This will also remove any RFC1918 addresses from all Lists.<br /><br />
+ Alerts can be Suppressed using the '+' icon in the Alerts Tab and IPs added to the 'pfBlockerNGSuppress' Alias<br />
+ A Blocked IP in a CIDR other than /24 will need to be Suppressed by an 'Permit Outbound' Firewall Rule]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Keep Settings</strong>/Lists After Disable/Re-Install/De-Install]]></fielddescr>
+ <fieldname>pfb_keep</fieldname>
+ <type>checkbox</type>
+ <description>Keep Settings and Lists intact when pfBlockerNG is Disabled or After pfBlockerNG Re-Install/De-Install</description>
+ </field>
+ <field>
+ <fielddescr>Global Enable Logging</fielddescr>
+ <fieldname>enable_log</fieldname>
+ <type>checkbox</type>
+ <description>Enable Global Logging to Status: System Logs: FIREWALL ( Log ). This overrides any Log Settings in the Alias Tabs.</description>
+ </field>
+ <field>
+ <fielddescr>Disable MaxMind Country Database CRON Updates</fielddescr>
+ <fieldname>database_cc</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[This will Disable the MaxMind Monthly Country Database Cron Update.<br />
+ This does not affect the MaxMind Binary Cron Task]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr>Logfile Size</fielddescr>
+ <fieldname>log_maxlines</fieldname>
+ <description><![CDATA[Default:<strong>20000</strong><br />
+ Select number of Lines to Keep in Log File]]></description>
+ <type>select</type>
+ <options>
+ <option><name>20000</name><value>20000</value></option>
+ <option><name>40000</name><value>40000</value></option>
+ <option><name>60000</name><value>60000</value></option>
+ <option><name>80000</name><value>80000</value></option>
+ <option><name>100000</name><value>100000</value></option>
+ <option><name>No Limit</name><value>nolimit</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[Interface/Rules Configuration]]> </name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Inbound Interface(s)</fielddescr>
+ <fieldname>inbound_interface</fieldname>
+ <description>Select the Inbound interface(s) you want to Apply Auto Rules to</description>
+ <type>interfaces_selection</type>
+ <hideinterfaceregex>loopback</hideinterfaceregex>
+ <required/>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr> - Rule Action</fielddescr>
+ <fieldname>inbound_deny_action</fieldname>
+ <description><![CDATA[Default:<strong>Block</strong><br />
+ Select 'Rule Action' for Inbound Rules]]></description>
+ <type>select</type>
+ <options>
+ <option><name>Block</name><value>block</value></option>
+ <option><name>Reject</name><value>reject</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Outbound Interface(s)</fielddescr>
+ <fieldname>outbound_interface</fieldname>
+ <description>Select the Outbound interface(s) you want to Apply Auto Rules to</description>
+ <type>interfaces_selection</type>
+ <hideinterfaceregex>loopback</hideinterfaceregex>
+ <required/>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr> - Rule Action</fielddescr>
+ <fieldname>outbound_deny_action</fieldname>
+ <description><![CDATA[Default:<strong>Reject</strong><br />
+ Select 'Rule Action' for Outbound rules]]></description>
+ <type>select</type>
+ <options>
+ <option><name>Reject</name><value>reject</value></option>
+ <option><name>Block</name><value>block</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>OpenVPN Interface</strong>]]></fielddescr>
+ <fieldname>openvpn_action</fieldname>
+ <type>checkbox</type>
+ <description>Select to add Auto-Rules for OpenVPN. These will be added to 'Floating Rules' or OpenVPN Rules Tab.</description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Floating Rules</strong>]]></fielddescr>
+ <fieldname>enable_float</fieldname>
+ <type>checkbox</type>
+ <description><![CDATA[<strong>Enabled:&nbsp;</strong> Auto-Rules will be generated in the 'Floating Rules' Tab<br /><br />
+ <strong>Disabled:</strong> Auto-Rules will be generated in the Selected Inbound/Outbound Interfaces<br /><br />
+ <strong>Rules will be ordered by the selection below.</strong>]]></description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Rule Order</strong>]]></fielddescr>
+ <fieldname>pass_order</fieldname>
+ <description><![CDATA[<br />Default Order: <strong> | pfB_Block/Reject | All other Rules | (original format)<br /></strong><br />
+ Select The '<strong>Order</strong>' of the Rules<br />
+ &nbsp;&nbsp;Selecting 'original format', sets pfBlockerNG rules at the top of the Firewall TAB.<br />
+ &nbsp;&nbsp;Selecting any other 'Order' will re-order <strong>all the Rules to the format indicated!</strong>]]></description>
+ <type>select</type>
+ <options>
+ <option><name>| pfB_Block/Reject | All other Rules | (original format)</name><value>order_0</value></option>
+ <option><name>| pfSense Pass/Match | pfB_Pass/Match | pfB_Block/Reject |</name><value>order_1</value></option>
+ <option><name>| pfB_Pass/Match | pfSense Pass/Match | pfB_Block/Reject |</name><value>order_2</value></option>
+ <option><name>| pfB_Pass/Match | pfB_Block/Reject | pfSense Pass/Match |</name><value>order_3</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>Auto Rule Suffix</strong>]]></fielddescr>
+ <fieldname>autorule_suffix</fieldname>
+ <description><![CDATA[Default:<strong>auto rule</strong><br />
+ Select 'Auto Rule' Description Suffix for Auto Defined rules. pfBlockerNG Must be Disabled to Modify Suffix]]></description>
+ <type>select</type>
+ <options>
+ <option><name>auto rule</name><value>autorule</value></option>
+ <option><name>Null (no suffix)</name><value>standard</value></option>
+ <option><name>AR</name><value>ar</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[Acknowledgements]]> </name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Credits</fielddescr>
+ <fieldname>credits</fieldname>
+ <type>info</type>
+ <description><![CDATA[<strong>
+ pfBlockerNG</strong> Created in 2014 by <a target=_new href='https://forum.pfsense.org/index.php?action=profile;u=238481'>BBcan177.</a>
+ <br /><br />Based upon pfBlocker by Marcello Coutinho and Tom Schaefer.<br />
+ Country Database GeoLite distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License by:
+ MaxMind Inc. @ <a target=_new href='http://www.maxmind.com'>MaxMind.com</a>.
+ The Database is Automatically Updated the First Tuesday of Each Month]]></description>
+ </field>
+ <field>
+ <fielddescr>pfBlocker Validation Check</fielddescr>
+ <fieldname>pfblocker_cb</fieldname>
+ <type>checkbox</type>
+ <description>Disable pfBlockerNG if the pfBlocker package is Enabled. Click to Disable this validation check.</description>
+ </field>
+ <field>
+ <fielddescr>Gold Membership</fielddescr>
+ <type>info</type>
+ <description><![CDATA[If you like this package, please Support pfSense by subscribing to a <a target=_new href='https://portal.pfsense.org/gold-subscription.php'>Gold Membership</a><br /> or support the developer @ BBCan177@gmail.com]]></description>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]></name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input($_POST, $input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global $pfb;
+ $pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_alerts.php b/config/pfblockerng/pfblockerng_alerts.php
new file mode 100644
index 00000000..7b84bca8
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_alerts.php
@@ -0,0 +1,769 @@
+<?php
+/*
+ pfBlockerNG_Alerts.php
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Portions of this code are based on original work done for
+ pfSense from the following contributors:
+
+ Parts based on works from Snort_alerts.php
+ Copyright (C) 2014 Bill Meeks
+ All rights reserved.
+
+ Javascript Hostname Lookup modifications by J. Nieuwenhuizen
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("util.inc");
+require_once("guiconfig.inc");
+require_once("globals.inc");
+require_once("filter_log.inc");
+require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+
+pfb_global();
+
+// Application Paths
+$pathgeoip = "/usr/pbi/pfblockerng-" . php_uname("m") . "/bin/geoiplookup";
+$pathgeoip6 = "/usr/pbi/pfblockerng-" . php_uname("m") . "/bin/geoiplookup6";
+
+// Define File Locations
+$filter_logfile = "{$g['varlog_path']}/filter.log";
+$pathgeoipdat = "/usr/pbi/pfblockerng-" . php_uname("m") . "/share/GeoIP/GeoIP.dat";
+$pathgeoipdat6 = "/usr/pbi/pfblockerng-" . php_uname("m") . "/share/GeoIP/GeoIPv6.dat";
+
+// Emerging Threats IQRisk Header Name Reference
+$pfb['et_header'] = TRUE;
+$et_header = $config['installedpackages']['pfblockerngreputation']['config'][0]['et_header'];
+if (empty($et_header))
+ $pfb['et_header'] = FALSE;
+
+// Collect pfBlockerNGSuppress Alias and Create pfbsuppression.txt
+if ($pfb['supp'] == "on")
+ pfb_create_suppression_file();
+
+// Collect Number of Suppressed Hosts
+if (file_exists("{$pfb['supptxt']}")) {
+ $pfbsupp_cnt = exec ("/usr/bin/grep -c ^ {$pfb['supptxt']}");
+} else {
+ $pfbsupp_cnt = 0;
+}
+
+// Collect pfBlockerNG Rule Names and Number
+$rule_list = array();
+$results = array();
+$data = exec ("/sbin/pfctl -vv -sr | grep 'pfB_'", $results);
+
+if (empty($config['installedpackages']['pfblockerngglobal']['pfbdenycnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbdenycnt'] = '25';
+if (empty($config['installedpackages']['pfblockerngglobal']['pfbpermitcnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbpermitcnt'] = '5';
+if (empty($config['installedpackages']['pfblockerngglobal']['pfbmatchcnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbmatchcnt'] = '5';
+if (empty($config['installedpackages']['pfblockerngglobal']['alertrefresh']))
+ $config['installedpackages']['pfblockerngglobal']['alertrefresh'] = 'off';
+if (empty($config['installedpackages']['pfblockerngglobal']['hostlookup']))
+ $config['installedpackages']['pfblockerngglobal']['hostlookup'] = 'off';
+
+if (isset($_POST['save'])) {
+ if (!is_array($config['installedpackages']['pfblockerngglobal']))
+ $config['installedpackages']['pfblockerngglobal'] = array();
+ $config['installedpackages']['pfblockerngglobal']['alertrefresh'] = $_POST['alertrefresh'] ? 'on' : 'off';
+ $config['installedpackages']['pfblockerngglobal']['hostlookup'] = $_POST['hostlookup'] ? 'on' : 'off';
+ if (is_numeric($_POST['pfbdenycnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbdenycnt'] = $_POST['pfbdenycnt'];
+ if (is_numeric($_POST['pfbpermitcnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbpermitcnt'] = $_POST['pfbpermitcnt'];
+ if (is_numeric($_POST['pfbmatchcnt']))
+ $config['installedpackages']['pfblockerngglobal']['pfbmatchcnt'] = $_POST['pfbmatchcnt'];
+
+ write_config("pfBlockerNG pkg: updated ALERTS tab settings.");
+ header("Location: " . $_SERVER['PHP_SELF']);
+ exit;
+}
+
+if (is_array($config['installedpackages']['pfblockerngglobal'])) {
+ $alertrefresh = $config['installedpackages']['pfblockerngglobal']['alertrefresh'];
+ $hostlookup = $config['installedpackages']['pfblockerngglobal']['hostlookup'];
+ $pfbdenycnt = $config['installedpackages']['pfblockerngglobal']['pfbdenycnt'];
+ $pfbpermitcnt = $config['installedpackages']['pfblockerngglobal']['pfbpermitcnt'];
+ $pfbmatchcnt = $config['installedpackages']['pfblockerngglobal']['pfbmatchcnt'];
+}
+
+// Collect pfBlockerNG Firewall Rules
+if (!empty($results)) {
+ foreach ($results as $result) {
+
+ # Find Rule Descriptions
+ $descr = "";
+ if (preg_match("/USER_RULE: (\w+)/",$result,$desc))
+ $descr = $desc[1];
+
+ if ($pfb['pfsenseversion'] >= '2.2') {
+ preg_match ("/@(\d+)\(/",$result, $rule);
+ } else {
+ preg_match ("/@(\d+)\s/",$result, $rule);
+ }
+
+ $id = $rule[1];
+ # Create array of Rule Description and pfctl Rule Number
+ $rule_list['id'][] = $id;
+ $rule_list[$id]['name'] = $descr;
+ }
+}
+
+// Add IP to the Suppression Alias
+if (isset($_POST['addsuppress'])) {
+ $ip = "";
+ if (isset($_POST['ip'])) {
+ $ip = $_POST['ip'];
+ $table = $_POST['table'];
+ $descr = $_POST['descr'];
+ $cidr = $_POST['cidr'];
+
+ // If Description or CIDR field is empty, exit.
+ if (empty($descr) || empty($cidr)) {
+ header("Location: " . $_SERVER['PHP_SELF']);
+ exit;
+ }
+
+ if (is_ipaddr($ip)) {
+
+ $savemsg1 = "Host IP address {$ip}";
+ if (is_ipaddrv4($ip)) {
+ $iptrim1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '$1.$2.$3.0/24', $ip);
+ $iptrim2 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '$1.$2.$3.', $ip);
+ $iptrim3 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '$4', $ip);
+
+ if ($cidr == "32") {
+ $pfb_pfctl = exec ("/sbin/pfctl -t {$table} -T show | grep {$iptrim1} 2>&1");
+
+ if ($pfb_pfctl == "") {
+ $savemsg2 = " : Removed /32 entry";
+ exec ("/sbin/pfctl -t {$table} -T delete {$ip}");
+ } else {
+ $savemsg2 = " : Removed /24 entry, added 254 addr";
+ exec ("/sbin/pfctl -t {$table} -T delete {$iptrim1}");
+ for ($add_ip=0; $add_ip <= 255; $add_ip++){
+ if ($add_ip != $iptrim3) {
+ exec ("/sbin/pfctl -t {$table} -T add {$iptrim2}{$add_ip}");
+ }
+ }
+ }
+ } else {
+ $cidr = 24;
+ $savemsg2 = " : Removed /24 entry";
+ exec ("/sbin/pfctl -t {$table} -T delete {$iptrim1} 2>&1", $pfb_pfctl);
+ if (!preg_grep("/1\/1 addresses deleted/", $pfb_pfctl)) {
+ $savemsg2 = " : Removed all entries";
+ // Remove 0-255 IP Address from Alias Table
+ for ($del_ip=0; $del_ip <= 255; $del_ip++){
+ exec ("/sbin/pfctl -t {$table} -T delete {$iptrim2}{$del_ip}");
+ }
+ }
+ }
+ }
+
+ // Collect pfBlockerNGSuppress Alias Contents
+ $pfb_sup_list = array();
+ $pfb_sup_array = array();
+ $pfb['found'] = FALSE;
+ $pfb['update'] = FALSE;
+ if (is_array($config['aliases']['alias'])) {
+ foreach ($config['aliases']['alias'] as $alias) {
+ if ($alias['name'] == "pfBlockerNGSuppress") {
+ $data = $alias['address'];
+ $data2 = $alias['detail'];
+ $arr1 = explode(" ",$data);
+ $arr2 = explode("||",$data2);
+
+ if (!empty($data)) {
+ $row = 0;
+ foreach ($arr1 as $host) {
+ $pfb_sup_list[] = $host;
+ $pfb_sup_array[$row]['host'] = $host;
+ $row++;
+ }
+ $row = 0;
+ foreach ($arr2 as $detail) {
+ $pfb_sup_array[$row]['detail'] = $detail;
+ $row++;
+ }
+ }
+ $pfb['found'] = TRUE;
+ }
+ }
+ }
+
+ // Call Function to Create Suppression Alias if not found.
+ if (!$pfb['found'])
+ pfb_create_suppression_alias();
+
+ // Save New Suppress IP to pfBlockerNGSuppress Alias
+ if (in_array($ip . '/' . $cidr, $pfb_sup_list)) {
+ $savemsg = gettext("Host IP address {$ip} already exists in the pfBlockerNG Suppress Table.");
+ } else {
+ if (!$pfb['found'] && empty($pfb_sup_list)) {
+ $next_id = 0;
+ } else {
+ $next_id = count($pfb_sup_list);
+ }
+ $pfb_sup_array[$next_id]['host'] = $ip . '/' . $cidr;
+ $pfb_sup_array[$next_id]['detail'] = $descr;
+
+ $address = "";
+ $detail = "";
+ foreach ($pfb_sup_array as $pfb_sup) {
+ $address .= $pfb_sup['host'] . " ";
+ $detail .= $pfb_sup['detail'] . "||";
+ }
+
+ // Find pfBlockerNGSuppress Array ID Number
+ if (is_array($config['aliases']['alias'])) {
+ $pfb_id = 0;
+ foreach ($config['aliases']['alias'] as $alias) {
+ if ($alias['name'] == "pfBlockerNGSuppress") {
+ break;
+ }
+ $pfb_id++;
+ }
+ }
+
+ $config['aliases']['alias'][$pfb_id]['address'] = rtrim($address, " ");
+ $config['aliases']['alias'][$pfb_id]['detail'] = rtrim($detail, "||");
+ $savemsg = gettext($savemsg1) . gettext($savemsg2) . gettext(" and added Host to the pfBlockerNG Suppress Table.");
+ $pfb['update'] = TRUE;
+ }
+
+ if ($pfb['found'] || $pfb['update']) {
+ // Save all Changes to pfsense config file
+ write_config();
+ }
+ }
+ }
+}
+
+// Auto-Resolve Hostnames
+if (isset($_REQUEST['getpfhostname'])) {
+ $getpfhostname = htmlspecialchars($_REQUEST['getpfhostname']);
+ $hostname = htmlspecialchars(gethostbyaddr($getpfhostname), ENT_QUOTES);
+ if ($hostname == $getpfhostname) {
+ $hostname = 'unknown';
+ }
+ echo $hostname;
+ die;
+}
+
+
+// Host Resolve Function lookup
+function getpfbhostname($type = 'src', $hostip, $countme = 0) {
+ $hostnames['src'] = '';
+ $hostnames['dst'] = '';
+ $hostnames[$type] = '<div id="gethostname_' . $countme . '" name="' . $hostip . '"></div>';
+ return $hostnames;
+}
+
+
+// Determine if Alert Host 'Dest' is within the Local Lan IP Range.
+function check_lan_dest($lan_ip,$lan_mask,$dest_ip,$dest_mask="32") {
+ $result = check_subnets_overlap($lan_ip, $lan_mask, $dest_ip, $dest_mask);
+ return $result;
+}
+
+
+$pgtitle = gettext("pfBlockerNG: Alerts");
+include_once("head.inc");
+?>
+<body link="#000000" vlink="#0000CC" alink="#000000">
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<input type="hidden" name="ip" id="ip" value=""/>
+<input type="hidden" name="table" id="table" value=""/>
+<input type="hidden" name="descr" id="descr" value=""/>
+<input type="hidden" name="cidr" id="cidr" value=""/>
+<?php
+
+include_once("fbegin.inc");
+
+/* refresh every 60 secs */
+if ($alertrefresh == 'on')
+ echo "<meta http-equiv=\"refresh\" content=\"60;url={$_SERVER['PHP_SELF']}\" />\n";
+if ($savemsg) {
+ print_info_box($savemsg);
+}
+
+?>
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=pfblockerng.xml&amp;id=0");
+ $tab_array[] = array(gettext("Update"), false, "/pfblockerng/pfblockerng_update.php");
+ $tab_array[] = array(gettext("Alerts"), true, "/pfblockerng/pfblockerng_alerts.php");
+ $tab_array[] = array(gettext("Reputation"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&id=0");
+ $tab_array[] = array(gettext("IPv4"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml");
+ $tab_array[] = array(gettext("IPv6"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml");
+ $tab_array[] = array(gettext("Top 20"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&id=0");
+ $tab_array[] = array(gettext("Africa"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&id=0");
+ $tab_array[] = array(gettext("Asia"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&id=0");
+ $tab_array[] = array(gettext("Europe"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&id=0");
+ $tab_array[] = array(gettext("N.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("Oceania"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&id=0");
+ $tab_array[] = array(gettext("S.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("P.S."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&id=0");
+ $tab_array[] = array(gettext("Logs"), false, "/pfblockerng/pfblockerng_log.php");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&id=0");
+ display_top_tabs($tab_array, true);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td><div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6">
+ <tr>
+ <td colspan="3" class="vncell" align="left"><?php echo gettext("LINKS :"); ?>&nbsp;
+ <a href='/firewall_aliases.php' target="_blank"><?php echo gettext("Firewall Alias"); ?></a>&nbsp;
+ <a href='/firewall_rules.php' target="_blank"><?php echo gettext("Firewall Rules"); ?></a>&nbsp;
+ <a href='/diag_logs_filter.php' target="_blank"><?php echo gettext("Firewall Logs"); ?></a><br /></td>
+ </tr>
+ <tr>
+ <td width="10%" class="vncell"><?php echo gettext('Alert Settings'); ?></td>
+ <td width="90%" class="vtable">
+ <input name="pfbdenycnt" type="text" class="formfld unknown" id="pdbdenycnt" size="1" title="Enter the number of 'Deny' Alerts to Show" value="<?=htmlspecialchars($pfbdenycnt);?>"/>
+ <?php printf(gettext('%sDeny%s.&nbsp;&nbsp;') , '<strong>', '</strong>'); ?>
+ <input name="pfbpermitcnt" type="text" class="formfld unknown" id="pdbpermitcnt" size="1" title="Enter the number of 'Permit' Alerts to Show" value="<?=htmlspecialchars($pfbpermitcnt);?>"/>
+ <?php printf(gettext('%sPermit%s.&nbsp;&nbsp;'), '<strong>', '</strong>'); ?>
+ <input name="pfbmatchcnt" type="text" class="formfld unknown" id="pdbmatchcnt" size="1" title="Enter the number of 'Match' Alerts to Show" value="<?=htmlspecialchars($pfbmatchcnt); ?>"/>
+ <?php printf(gettext('%sMatch%s.'), '<strong>', '</strong>'); ?>
+
+ <?php echo gettext('&nbsp;&nbsp;&nbsp;&nbsp;Click to Auto-Refresh');?>&nbsp;&nbsp;<input name="alertrefresh" type="checkbox" value="on" title="Click to enable Auto-Refresh of this Tab once per minute"
+ <?php if ($config['installedpackages']['pfblockerngglobal']['alertrefresh']=="on") echo "checked"; ?>/>&nbsp;
+
+ <?php echo gettext('&nbsp;Click to Auto-Resolve');?>&nbsp;&nbsp;<input name="hostlookup" type="checkbox" value="on" title="Click to enable Auto-Resolve of Hostnames. Country Blocks/Permit/Match Lists will not auto-resolve"
+ <?php if ($config['installedpackages']['pfblockerngglobal']['hostlookup']=="on") echo "checked"; ?>/>&nbsp;&nbsp;&nbsp;
+ <input name="save" type="submit" class="formbtns" value="Save" title="<?=gettext('Save settings');?>"/><br />
+
+ <?php printf(gettext('Enter number of log entries to view.')); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <?php printf(gettext("Currently Suppressing &nbsp; %s$pfbsupp_cnt%s &nbsp; Hosts."), '<strong>', '</strong>');?>
+ </td>
+ </tr>
+<!--Create Three Output Windows 'Deny', 'Permit' and 'Match'-->
+<?php foreach (array ("Deny" => $pfb['denydir'] . " " . $pfb['nativedir'], "Permit" => $pfb['permitdir'], "Match" => $pfb['matchdir']) as $type => $pfbfolder ):
+ switch($type) {
+ case "Deny":
+ $rtype = "block";
+ $pfbentries = "{$pfbdenycnt}";
+ break;
+ case "Permit":
+ $rtype = "pass";
+ $pfbentries = "{$pfbpermitcnt}";
+ break;
+ case "Match":
+ if ($pfb['pfsenseversion'] >= '2.2') {
+ $rtype = "unkn(%u)";
+ } else {
+ $rtype = "unkn(11)";
+ }
+ $pfbentries = "{$pfbmatchcnt}";
+ break;
+ }
+
+?>
+ <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6">
+ <tr>
+ <!--Print Table Info-->
+ <td colspan="2" class="listtopic"><?php printf(gettext("&nbsp;{$type}&nbsp;&nbsp; - &nbsp; Last %s Alert Entries."), "{$pfbentries}"); ?>
+ <?php if ($pfb['pfsenseversion'] >= '2.2'): ?>
+ <?php if (!is_array($config['syslog']) || !array_key_exists("reverse", $config['syslog'])): ?>
+ &nbsp;&nbsp;<?php echo gettext("Firewall Logs must be in Reverse Order."); ?>
+ <?php endif; ?>
+ <?php else: ?>
+ &nbsp;&nbsp;<?php echo gettext("Firewall Rule changes can unsync these Alerts."); ?>
+ <?php if (!is_array($config['syslog']) || !array_key_exists("reverse", $config['syslog'])): ?>
+ &nbsp;&nbsp;<?php echo gettext("Firewall Logs must be in Reverse Order."); ?>
+ <?php endif; ?>
+ <?php endif; ?>
+ </td>
+ </tr>
+
+<td width="100%" colspan="2">
+<table id="pfbAlertsTable" style="table-layout: fixed;" width="100%" class="sortable" border="0" cellpadding="0" cellspacing="0">
+ <colgroup>
+ <col width="8%" align="center" axis="date">
+ <col width="6%" align="center" axis="string">
+ <col width="16%" align="center" axis="string">
+ <col width="6%" align="center" axis="string">
+ <col width="20%" align="center" axis="string">
+ <col width="20%" align="center" axis="string">
+ <col width="3%" align="center" axis="string">
+ <col width="13%" align="center" axis="string">
+ </colgroup>
+ <thead>
+ <tr class="sortableHeaderRowIdentifier">
+ <th class="listhdrr" axis="date"><?php echo gettext("Date"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("IF"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("Rule"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("Proto"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("Source"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("Destination"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("CC"); ?></th>
+ <th class="listhdrr" axis="string"><?php echo gettext("List"); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+<?php
+
+$pfb['runonce'] = TRUE;
+if (isset($pfb['load']))
+ $pfb['runonce'] = FALSE;
+
+// Execute the following once per refresh
+if ($pfb['runonce']) {
+ $pfb['load'] = TRUE;
+ $fields_array = array();
+
+ // pfSense versions below 2.2 have the Logfiles in two lines.
+ if ($pfb['pfsenseversion'] >= '2.2') {
+ $pfblines = exec("/usr/bin/grep -c ^ {$filter_logfile}");
+ } else {
+ $pfblines = (exec("/usr/bin/grep -c ^ {$filter_logfile}") /2 );
+ }
+ $fields_array = conv_log_filter($filter_logfile, $pfblines, $pfblines);
+
+ $continents = array('pfB_Africa','pfB_Antartica','pfB_Asia','pfB_Europe','pfB_NAmerica','pfB_Oceania','pfB_SAmerica','pfB_Top');
+
+ $supp_ip_txt .= "Clicking this Suppression Icon, will immediately remove the Block.\n\nSuppressing a /32 CIDR is better than Suppressing the full /24";
+ $supp_ip_txt .= " CIDR.\nThe Host will be added to the pfBlockerNG Suppress Alias Table.\n\nOnly 32 or 24 CIDR IPs can be Suppressed with the '+' Icon.";
+ $supp_ip_txt .= "\nTo manually add Host(s), edit the 'pfBlockerNGSuppress' Alias in the Alias Tab.\nManual entries will not remove existing Blocked Hosts";
+
+ // Array of all Local IPs for Alert Analysis
+ $pfb_local = array();
+
+ // Collect Gateway IP Addresses for Inbound/Outbound List matching
+ $int_gateway = get_interfaces_with_gateway();
+ if (is_array($int_gateway)) {
+ foreach ($int_gateway as $gateway) {
+ $convert = get_interface_ip($gateway);
+ $pfb_local[] = $convert;
+ }
+ }
+
+ // Collect Virtual IP Aliases for Inbound/Outbound List Matching
+ if (is_array($config['virtualip']['vip'])) {
+ foreach ($config['virtualip']['vip'] as $list) {
+ $pfb_local[] = $list['subnet'];
+ }
+ }
+ // Collect NAT IP Addresses for Inbound/Outbound List Matching
+ if (is_array($config['nat']['rule'])) {
+ foreach ($config['nat']['rule'] as $natent) {
+ $pfb_local[] = $natent['target'];
+ }
+ }
+
+ // Collect 1:1 NAT IP Addresses for Inbound/Outbound List Matching
+ if(is_array($config['nat']['onetoone'])) {
+ foreach ($config['nat']['onetoone'] as $onetoone) {
+ $pfb_local[] = $onetoone['source']['address'];
+ }
+ }
+
+ // Convert any 'Firewall Aliases' to IP Address Format
+ if (is_array($config['aliases']['alias'])) {
+ for ($cnt = 0; $cnt <= count($pfb_local); $cnt++) {
+ foreach ($config['aliases']['alias'] as $i=> $alias) {
+ if (isset($alias['name']) && isset($pfb_local[$cnt])) {
+ if ($alias['name'] == $pfb_local[$cnt]) {
+ $pfb_local[$cnt] = $alias['address'];
+ }
+ }
+ }
+ }
+ }
+ // Remove any Duplicate IPs
+ $pfb_local = array_unique($pfb_local);
+
+ // Determine Lan IP Address and Mask
+ if (is_array($config['interfaces']['lan'])) {
+ $lan_ip = $config['interfaces']['lan']['ipaddr'];
+ $lan_mask = $config['interfaces']['lan']['subnet'];
+ }
+}
+
+$counter = 0;
+// Process Fields_array and generate Output
+if (!empty($fields_array)) {
+ foreach ($fields_array as $fields) {
+ $rulenum = "";
+ $alert_ip = "";
+ $supp_ip = "";
+ $pfb_query = "";
+
+ $rulenum = $fields['rulenum'];
+ if ($fields['act'] == $rtype && !empty($rule_list) && in_array($rulenum, $rule_list['id']) && $counter < $pfbentries) {
+
+ // Skip Repeated Events
+ if (($fields['dstip'] . $fields['dstport']) == $previous_dstip || ($fields['srcip'] . $fields['srcport']) == $previous_srcip) {
+ continue;
+ }
+
+ $proto = str_replace("TCP", "TCP-", $fields['proto']) . $fields['tcpflags'];
+
+ // Cleanup Port Output
+ if ($fields['proto'] == "ICMP") {
+ $srcport = $fields['srcport'];
+ $dstport = $fields['dstport'];
+ } else {
+ $srcport = " :" . $fields['srcport'];
+ $dstport = " :" . $fields['dstport'];
+ }
+
+ // Don't add Suppress Icon to Country Block Lines
+ if (in_array(substr($rule_list[$rulenum]['name'], 0, -3), $continents)) {
+ $pfb_query = "Country";
+ }
+
+ // Add DNS Resolve and Suppression Icons to External IPs only. GeoIP Code to External IPs only.
+ if (in_array($fields['dstip'], $pfb_local) || check_lan_dest($lan_ip,$lan_mask,$fields['dstip'],"32")) {
+ // Destination is Gateway/NAT/VIP
+ $rule = $rule_list[$rulenum]['name'] . "<br />(" . $rulenum .")";
+ $host = $fields['srcip'];
+
+ if (is_ipaddrv4($host)) {
+ $country = substr(exec("$pathgeoip -f $pathgeoipdat $host"),23,2);
+ } else {
+ $country = substr(exec("$pathgeoip6 -f $pathgeoipdat6 $host"),26,2);
+ }
+
+ $alert_ip .= "<a href='/pfblockerng/pfblockerng_diag_dns.php?host={$host}' title=\" " . gettext("Resolve host via Rev. DNS lookup");
+ $alert_ip .= "\"> <img src=\"/themes/{$g['theme']}/images/icons/icon_log.gif\" width=\"11\" height=\"11\" border=\"0\" ";
+ $alert_ip .= "alt=\"Icon Reverse Resolve with DNS\" style=\"cursor: pointer;\"/></a>";
+
+ if ($pfb_query != "Country" && $rtype == "block" && $pfb['supp'] == "on") {
+ $supp_ip .= "<input type='image' name='addsuppress[]' onclick=\"hostruleid('{$host}','{$rule_list[$rulenum]['name']}');\" ";
+ $supp_ip .= "src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" title=\"";
+ $supp_ip .= gettext($supp_ip_txt) . "\" border=\"0\" width='11' height='11'/>";
+ }
+
+ if ($pfb_query != "Country" && $rtype == "block" && $hostlookup == "on") {
+ $hostname = getpfbhostname('src', $fields['srcip'], $counter);
+ } else {
+ $hostname = "";
+ }
+
+ $src_icons = $alert_ip . "&nbsp;" . $supp_ip . "&nbsp;";
+ $dst_icons = "";
+ $scc = $country;
+ $dcc = "";
+ } else {
+ // Outbound
+ $rule = $rule_list[$rulenum]['name'] . "<br />(" . $rulenum .")";
+ $host = $fields['dstip'];
+
+ if (is_ipaddrv4($host)) {
+ $country = substr(exec("$pathgeoip -f $pathgeoipdat $host"),23,2);
+ } else {
+ $country = substr(exec("$pathgeoip6 -f $pathgeoipdat6 $host"),26,2);
+ }
+
+ $alert_ip .= "<a href='/pfblockerng/pfblockerng_diag_dns.php?host={$host}' title=\"" . gettext("Resolve host via Rev. DNS lookup");
+ $alert_ip .= "\"> <img src=\"/themes/{$g['theme']}/images/icons/icon_log.gif\" width=\"11\" height=\"11\" border=\"0\" ";
+ $alert_ip .= "alt=\"Icon Reverse Resolve with DNS\" style=\"cursor: pointer;\"/></a>";
+
+ if ($pfb_query != "Country" && $rtype == "block" && $pfb['supp'] == "on") {
+ $supp_ip .= "<input type='image' name='addsuppress[]' onclick=\"hostruleid('{$host}','{$rule_list[$rulenum]['name']}');\" ";
+ $supp_ip .= "src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" title=\"";
+ $supp_ip .= gettext($supp_ip_txt) . "\" border=\"0\" width='11' height='11'/>";
+ }
+
+ if ($pfb_query != "Country" && $rtype == "block" && $hostlookup == "on") {
+ $hostname = getpfbhostname('dst', $fields['dstip'], $counter);
+ } else {
+ $hostname = "";
+ }
+
+ $src_icons = "";
+ $dst_icons = $alert_ip . "&nbsp;" . $supp_ip . "&nbsp;";
+ $scc = "";
+ $dcc = $country;
+ }
+
+ # IP Query Grep Exclusion
+ $pfb_ex1 = "grep -v 'pfB\_\|\_v6\.txt'";
+ $pfb_ex2 = "grep -v 'pfB\_\|/32\|/24\|\_v6\.txt' | grep -m1 '/'";
+
+ // Find List which contains Blocked IP Host
+ if ($pfb_query == "Country") {
+ # Skip
+ } else {
+ // Search for exact IP Match
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'$1\.$2\.$3\.$4\'', $host);
+ $pfb_query = exec("grep -rHm1 {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/:.*//' -e 's/\..*/ /' | {$pfb_ex1}");
+ // Search for IP in /24 CIDR
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'$1\.$2\.$3\.0/24\'', $host);
+ $pfb_query = exec("grep -rHm1 {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex1}");
+ }
+ // Search for First Two IP Octets in CIDR Matches Only. Skip any pfB (Country Lists) or /32,/24 Addresses.
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'^$1\.$2\.\'', $host);
+ $pfb_query = exec("grep -rH {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex2}");
+ }
+ // Search for First Two IP Octets in CIDR Matches Only (Subtract 1 from second Octet on each loop).
+ // Skip (Country Lists) or /32,/24 Addresses.
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'^$1\.', $host);
+ $host2 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '$2', $host);
+ for ($cnt = 1; $cnt <= 5; $cnt++) {
+ $host3 = $host2 - $cnt . '\'';
+ $pfb_query = exec("grep -rH {$host1}{$host3} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex2}");
+ // Break out of loop if found.
+ if (!empty($pfb_query))
+ $cnt = 6;
+ }
+ }
+ // Search for First Three Octets
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'^$1\.$2\.$3\.\'', $host);
+ $pfb_query = exec("grep -rH {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex2}");
+ }
+ // Search for First Two Octets
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'^$1\.$2\.\'', $host);
+ $pfb_query = exec("grep -rH {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex2}");
+ }
+ // Report Specific ET IQRisk Details
+ if ($pfb['et_header'] && preg_match("/{$et_header}/", $pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'$1\.$2\.$3\.$4\'', $host);
+ $pfb_query = exec("grep -Hm1 {$host1} {$pfb['etdir']}/* | sed -e 's/^.*[a-zA-Z]\///' -e 's/:.*//' -e 's/\..*/ /' -e 's/ET_/ET IPrep /' ");
+ if (empty($pfb_query)) {
+ $host1 = preg_replace("/(\d{1,3})\.(\d{1,3}).(\d{1,3}).(\d{1,3})/", '\'$1.$2.$3.0/24\'', $host);
+ $pfb_query = exec("grep -rHm1 {$host1} {$pfbfolder} | sed -e 's/^.*[a-zA-Z]\///' -e 's/\.txt:/ /' | {$pfb_ex1}");
+ }
+ }
+ // Default to "No Match" if not found.
+ if (empty($pfb_query))
+ $pfb_query = "No Match";
+ }
+
+ # Split List Column into Two lines.
+ unset ($pfb_match);
+ if ($pfb_query == "No Match") {
+ $pfb_match[1] = "{$pfb_query}";
+ $pfb_match[2] = "";
+ } else {
+ preg_match ("/(.*)\s(.*)/", $pfb_query, $pfb_match);
+ if ($pfb_match[1] == "") {
+ $pfb_match[1] = "{$pfb_query}";
+ $pfb_match[2] = "";
+ }
+ }
+
+ // Print Alternating Line Shading
+ if ($pfb['pfsenseversion'] > '2.0') {
+ $alertRowEvenClass = "listMReven";
+ $alertRowOddClass = "listMRodd";
+ } else {
+ $alertRowEvenClass = "listr";
+ $alertRowOddClass = "listr";
+ }
+
+ // Collect Details for Repeated Alert Comparison
+ $previous_srcip = $fields['srcip'] . $fields['srcport'];
+ $previous_dstip = $fields['dstip'] . $fields['dstport'];
+ $countrycode = trim($scc . $dcc);
+
+ $alertRowClass = $counter % 2 ? $alertRowEvenClass : $alertRowOddClass;
+ echo "<tr class='{$alertRowClass}'>
+ <td class='listMRr' align='center'>{$fields['time']}</td>
+ <td class='listMRr' align='center'>{$fields['interface']}</td>
+ <td class='listMRr' align='center' title='The pfBlockerNG Rule that Blocked this Host.'>{$rule}</td>
+ <td class='listMRr' align='center'>{$proto}</td>
+ <td nowrap='nowrap' class='listMRr' align='center' style='sorttable_customkey:{$fields['srcip']};' sorttable_customkey='{$fields['srcip']}'>{$src_icons}{$fields['srcip']}{$srcport}<br /><small>{$hostname['src']}</small></td>
+ <td nowrap='nowrap' class='listMRr' align='center' style='sorttable_customkey:{$fields['dstip']};' sorttable_customkey='{$fields['dstip']}'>{$dst_icons}{$fields['dstip']}{$dstport}<br /><small>{$hostname['dst']}</small></td>
+ <td class='listMRr' align='center'>{$countrycode}</td>
+ <td class='listbg' align='center' title='Country Block Rules cannot be suppressed.\n\nTo allow a particular Country IP, either remove the particular Country or add the Host\nto a Permit Alias in the Firewall Tab.\n\nIf the IP is not listed beside the List, this means that the Block is a /32 entry.\nOnly /32 or /24 CIDR Hosts can be suppressed.\n\nIf (Duplication) Checking is not enabled. You may see /24 and /32 CIDR Blocks for a given blocked Host' style=\"font-size: 10px word-wrap:break-word;\">{$pfb_match[1]}<br />{$pfb_match[2]}</td></tr>";
+ $counter++;
+ if ($counter > 0 && $rtype == "block") {
+ $mycounter = $counter;
+ }
+ }
+ }
+}
+?>
+ </tbody>
+ </table>
+ </table>
+<?php endforeach; ?> <!--End - Create Three Output Windows 'Deny', 'Permit' and 'Match'-->
+</td></tr>
+</table>
+
+</div>
+</td>
+
+<script type="text/javascript">
+//<![CDATA[
+
+// This function stuffs the passed HOST, Table values into hidden Form Fields for postback.
+function hostruleid(host,table) {
+ document.getElementById("ip").value = host;
+ document.getElementById("table").value = table;
+
+ var description = prompt("Please enter Suppression Description");
+ document.getElementById("descr").value = description;
+
+ if (description.value != "") {
+ var cidr = prompt("Please enter CIDR [ 32 or 24 CIDR only supported ]","32");
+ document.getElementById("cidr").value = cidr;
+ }
+}
+
+// Auto-Resolve of Alerted Hostnames
+function findhostnames(counter) {
+ getip = jQuery('#gethostname_' + counter).attr('name');
+ geturl = "<?php echo $_SERVER['PHP_SELF']; ?>";
+ jQuery.get( geturl, { "getpfhostname": getip } )
+ .done(function( data ) {
+ jQuery('#gethostname_' + counter).prop('title' , data );
+ var str = data;
+ if(str.length > 32) str = str.substring(0,29)+"...";
+ jQuery('#gethostname_' + counter).html( str );
+ }
+ )
+}
+
+ var lines = <?php echo $mycounter; ?>;
+ for (i = 0; i < lines; i++) {
+ findhostnames(i);
+ }
+
+//]]>
+</script>
+<?php include("fend.inc"); ?>
+</form>
+</body>
+</html> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_diag_dns.php b/config/pfblockerng/pfblockerng_diag_dns.php
new file mode 100644
index 00000000..b2f07464
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_diag_dns.php
@@ -0,0 +1,318 @@
+<?php
+/*
+ pfBlockerNG_diag_dns.php
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Original Code by:
+ Copyright (C) 2009 Jim Pingle (jpingle@gmail.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+$pgtitle = array(gettext("pfBlockerNG"),gettext("DNS/Threat Source Lookup"));
+require("guiconfig.inc");
+
+$host = trim($_REQUEST['host'], " \t\n\r\0\x0B[];\"'");
+$host_esc = escapeshellarg($host);
+
+if (is_array($config['aliases']['alias'])) {
+ $a_aliases = &$config['aliases']['alias'];
+} else {
+ $a_aliases = array();
+}
+$aliasname = str_replace(array(".","-"), "_", $host);
+$alias_exists = false;
+$counter=0;
+foreach($a_aliases as $a) {
+ if($a['name'] == $aliasname) {
+ $alias_exists = true;
+ $id=$counter;
+ }
+ $counter++;
+}
+
+# Collect pfSense Version
+$pfs_version = substr(trim(file_get_contents("/etc/version")), 0, 3);
+
+if ($pfs_version > '2.2') {
+ $cmd = '/usr/bin/drill';
+} else {
+ $cmd = '/usr/bin/dig';
+}
+
+
+if(isset($_POST['create_alias']) && (is_hostname($host) || is_ipaddr($host))) {
+ if($_POST['override'])
+ $override = true;
+ $resolved = gethostbyname($host);
+ $type = "hostname";
+ if($resolved) {
+ $resolved = array();
+ exec("{$cmd} {$host_esc} A | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved);
+ $isfirst = true;
+ foreach($resolved as $re) {
+ if($re <> "") {
+ if(!$isfirst)
+ $addresses .= " ";
+ $addresses .= rtrim($re) . "/32";
+ $isfirst = false;
+ }
+ }
+ $newalias = array();
+ if($override)
+ $alias_exists = false;
+ if($alias_exists == false) {
+ $newalias['name'] = $aliasname;
+ $newalias['type'] = "network";
+ $newalias['address'] = $addresses;
+ $newalias['descr'] = "Created from Diagnostics-> DNS Lookup";
+ if($override)
+ $a_aliases[$id] = $newalias;
+ else
+ $a_aliases[] = $newalias;
+ write_config();
+ $createdalias = true;
+ }
+ }
+}
+
+if ($_POST) {
+ unset($input_errors);
+
+ $reqdfields = explode(" ", "host");
+ $reqdfieldsn = explode(",", "Host");
+
+ do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
+
+ if (!is_hostname($host) && !is_ipaddr($host)) {
+ $input_errors[] = gettext("Host must be a valid hostname or IP address.");
+ } else {
+ // Test resolution speed of each DNS server.
+ $dns_speeds = array();
+ $dns_servers = array();
+ exec("/usr/bin/grep nameserver /etc/resolv.conf | /usr/bin/cut -f2 -d' '", $dns_servers);
+ foreach ($dns_servers as $dns_server) {
+ $query_time = exec("{$cmd} {$host_esc} " . escapeshellarg("@" . trim($dns_server)) . " | /usr/bin/grep Query | /usr/bin/cut -d':' -f2");
+ if($query_time == "")
+ $query_time = gettext("No response");
+ $new_qt = array();
+ $new_qt['dns_server'] = $dns_server;
+ $new_qt['query_time'] = $query_time;
+ $dns_speeds[] = $new_qt;
+ unset($new_qt);
+ }
+ }
+
+ $type = "unknown";
+ $resolved = "";
+ $ipaddr = "";
+ $hostname = "";
+ if (!$input_errors) {
+ if (is_ipaddr($host)) {
+ $type = "ip";
+ $resolved = gethostbyaddr($host);
+ $ipaddr = $host;
+ if ($host != $resolved)
+ $hostname = $resolved;
+ } elseif (is_hostname($host)) {
+ $type = "hostname";
+ $resolved = gethostbyname($host);
+ if($resolved) {
+ $resolved = array();
+ exec("{$cmd} {$host_esc} A | /usr/bin/grep {$host_esc} | /usr/bin/grep -v ';' | /usr/bin/awk '{ print $5 }'", $resolved);
+ }
+ $hostname = $host;
+ if ($host != $resolved)
+ $ipaddr = $resolved[0];
+ }
+
+ if ($host == $resolved) {
+ $resolved = gettext("No record found");
+ }
+ }
+}
+
+function display_host_results ($address,$hostname,$dns_speeds) {
+ $map_lengths = function($element) { return strlen($element[0]); };
+
+ echo gettext("IP Address") . ": {$address} \n";
+ echo gettext("Host Name") . ": {$hostname} \n";
+ echo "\n";
+ $text_table = array();
+ $text_table[] = array(gettext("Server"), gettext("Query Time"));
+ if (is_array($dns_speeds)) {
+ foreach ($dns_speeds as $qt) {
+ $text_table[] = array(trim($qt['dns_server']), trim($qt['query_time']));
+ }
+ }
+ $col0_padlength = max(array_map($map_lengths, $text_table)) + 4;
+ foreach ($text_table as $text_row) {
+ echo str_pad($text_row[0], $col0_padlength) . $text_row[1] . "\n";
+ }
+}
+
+include("head.inc"); ?>
+<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
+<?php include("fbegin.inc"); ?>
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+<?php if ($input_errors) print_input_errors($input_errors); ?>
+ <form action="/pfblockerng/pfblockerng_diag_dns.php" method="post" name="iform" id="iform">
+ <table width="100%" border="0" cellpadding="6" cellspacing="0">
+ <tr>
+ <td colspan="2" valign="top" class="listtopic"> <?=gettext("Resolve DNS hostname or IP");?></td>
+ </tr>
+ <tr>
+ <td width="22%" valign="top" class="vncellreq"><?=gettext("Hostname or IP");?></td>
+ <td width="78%" class="vtable">
+ <?=$mandfldhtml;?>
+ <table>
+ <tr><td valign="top">
+ <input name="host" type="text" class="formfld" id="host" size="20" value="<?=htmlspecialchars($host);?>">
+ </td>
+ <td>
+ <?php if ($resolved && $type) { ?>
+ = <font size="+1">
+<?php
+ $found = 0;
+ if(is_array($resolved)) {
+ foreach($resolved as $hostitem) {
+ if($hostitem <> "") {
+ echo $hostitem . "<br/>";
+ $found++;
+ }
+ }
+ } else {
+ echo $resolved;
+ }
+ if($found > 0) { ?>
+ <br/><font size='-2'>
+ <?PHP if($alias_exists) { ?>
+ An alias already exists for the hostname <?= htmlspecialchars($host) ?>. <br />
+ <input type="hidden" name="override" value="true"/>
+ <input type="submit" name="create_alias" value="Overwrite Alias"/>
+ <?PHP } else {
+ if(!$createdalias) { ?>
+ <input type="submit" name="create_alias" value="Create Alias from These Entries"/>
+ <?PHP } else { ?>
+ Alias created with name <?= htmlspecialchars($newalias['name']) ?>
+ <?PHP }
+ }
+ }
+?>
+ <font size="-1">
+
+ <? } ?>
+ </td></tr></table>
+ </td>
+ </tr>
+<?php if($_POST): ?>
+ <tr>
+ <td width="22%" valign="top" class="vncell"><?=gettext("Resolution time per server");?></td>
+ <td width="78%" class="vtable">
+ <table width="170" border="1" cellpadding="2" style="border-width: 1px 1px 1px 1px; border-collapse: collapse;">
+ <tr>
+ <td>
+ <b><?=gettext("Server");?></b>
+ </td>
+ <td>
+ <b><?=gettext("Query time");?></b>
+ </td>
+ </tr>
+<?php
+ if(is_array($dns_speeds))
+ foreach($dns_speeds as $qt):
+?>
+ <tr>
+ <td>
+ <?=$qt['dns_server']?>
+ </td>
+ <td>
+ <?=$qt['query_time']?>
+ </td>
+ </tr>
+<?php
+ endforeach;
+?>
+ </table>
+ </td>
+ </tr>
+ <?php endif; ?>
+ <?php if (!$input_errors && $ipaddr) { ?>
+ <tr>
+
+ <td width="22%" valign="top" class="vncell"><?=gettext("More Information:");?></td>
+ <td width="78%" class="vtable">
+ <a target="_new" href ="/diag_ping.php?host=<?=htmlspecialchars($host)?>&interface=wan&count=3"><?=gettext("Ping");?></a> <br/>
+ <a target="_new" href ="/diag_traceroute.php?host=<?=htmlspecialchars($host)?>&ttl=18"><?=gettext("Traceroute");?></a>
+ <p/>
+ <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br/><br/>
+ <a target="_new" href="http://private.dnsstuff.com/tools/whois.ch?ip=<?php echo $ipaddr; ?>"><?=gettext("IP WHOIS @ DNS Stuff");?></a><br />
+ <a target="_new" href="http://private.dnsstuff.com/tools/ipall.ch?ip=<?php echo $ipaddr; ?>"><?=gettext("IP Info @ DNS Stuff");?></a>
+
+ <?=gettext("NOTE: The following links are to external services, so their reliability cannot be guaranteed.");?><br/><br/>
+ <a target="_new" href="http://kb.bothunter.net/ipInfo/nowait.php?IP=<?php echo $ipaddr; ?>"><?=gettext("BOTHunter");?></a><br/>
+ <a target="_new" href="http://www.ipvoid.com/scan/<?php echo $ipaddr; ?>/"><?=gettext("IPVOID");?></a><br/>
+ <a target="_new" href="http://www.tcpiputils.com/browse/ip-address/<?php echo $ipaddr; ?>/"><?=gettext("TCPUtils");?></a><br/>
+ <a target="_new" href="https://www.herdprotect.com/ip-address-<?php echo $ipaddr; ?>.aspx"><?=gettext("Herd Protect");?></a><br/>
+ <a target="_new" href="https://www.senderbase.org/lookup/ip/?search_string=<?php echo $ipaddr; ?>"><?=gettext("SenderBase");?></a><br/>
+ <a target="_new" href="http://www.ip-tracker.org/locator/ip-lookup.php?ip=<?php echo $ipaddr; ?>"><?=gettext("IP Tracker");?></a><br/>
+
+ <a target="_new" href="https://www.fortiguard.com/ip_rep/index.php?data=/<?php echo $ipaddr; ?>?"><?=gettext("FortiGuard");?></a><br/>
+ <a target="_new" href="https://www.projecthoneypot.org/ip_<?php echo $ipaddr; ?>"><?=gettext("Project HoneyPot");?></a><br/>
+ <a target="_new" href="https://www.virustotal.com/en/ip-address/<?php echo $ipaddr; ?>/information"><?=gettext("VirusTotal Info");?></a><br/>
+ <a target="_new" href="https://www.mcafee.com/threat-intelligence/ip/default.aspx?ip=<?php echo $ipaddr; ?>"><?=gettext("McAfee Threat Center");?></a><br/>
+ <a target="_new" href="http://sitecheck2.sucuri.net/results/<?php echo $ipaddr; ?>"><?=gettext("Securi SiteCheck");?></a><br/>
+ <a target="_new" href="https://www.dshield.org/ipinfo.html?IP=<?php echo $ipaddr; ?>"><?=gettext("DShield Threat Lookup");?></a><br/>
+ <a target="_new" href="https://isc.sans.edu/ipinfo.html?ip=<?php echo $ipaddr; ?>"><?=gettext("Internet Storm Center");?></a><br/>
+ <a target="_new" href="https://www.mywot.com/en/scorecard/<?php echo $ipaddr; ?>"><?=gettext("Web of Trust (WOT) Scorecard");?></a><br/>
+ <a target="_new" href="https://quttera.com/sitescan/<?php echo $ipaddr; ?>"><?=gettext("Quattera");?></a><br/>
+ <a target="_new" href="https://www.iblocklist.com/search.php?string=<?php echo $ipaddr; ?>"><?=gettext("I-Block List");?></a><br/>
+ <p/>
+ <?=gettext("NOTE: Mail Server DNSRBL Lookups");?><br/><br/>
+ <a target="_new" href="https://senderscore.org/lookup.php?lookup=<?php echo $ipaddr; ?>&ipLookup=Go"><?=gettext("SenderScore");?></a><br/>
+ <a target="_new" href="http://www.spamhaus.org/query/bl?ip=<?php echo $ipaddr; ?>"><?=gettext("Spamhaus Blocklist");?></a><br/>
+ <a target="_new" href="http://www.spamcop.net/w3m?action=checkblock&ip=<?php echo $ipaddr; ?>"><?=gettext("SPAMcop Blocklist");?></a><br/>
+ <a target="_new" href="http://multirbl.valli.org/lookup/<?php echo $ipaddr; ?>.html"><?=gettext("multirbl RBL Lookup");?></a><br/>
+ <a target="_new" href="http://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a<?php echo $ipaddr; ?>&run=toolpage"><?=gettext("MXToolbox");?></a><br/>
+
+ </td>
+ </tr>
+ <?php } ?>
+ <tr>
+ <td width="22%" valign="top">&nbsp;</td>
+ <td width="78%">
+ <br/>&nbsp;
+ <input name="Submit" type="submit" class="formbtn" value="<?=gettext("DNS Lookup");?>">
+ </td>
+ </tr>
+ </table>
+</td></tr></table>
+</form>
+<?php include("fend.inc"); ?> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_log.php b/config/pfblockerng/pfblockerng_log.php
new file mode 100644
index 00000000..74f513a2
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_log.php
@@ -0,0 +1,428 @@
+<?php
+/*
+ pfBlockerNG_Log.php
+
+ pfBlockerNG
+ Copyright (c) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Portions of this code are based on original work done for the
+ Snort package for pfSense from the following contributors:
+
+ Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>.
+ Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
+ Copyright (C) 2006 Scott Ullrich
+ Copyright (C) 2009 Robert Zelaya Sr. Developer
+ Copyright (C) 2012 Ermal Luci
+ All rights reserved.
+
+ Adapted for Suricata by:
+ Copyright (C) 2014 Bill Meeks
+ All rights reserved.
+
+ Javascript and Integration modifications by J. Nieuwenhuizen
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("guiconfig.inc");
+require_once("globals.inc");
+require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+
+pfb_global();
+
+# Get log files from directory
+function getlogs($logdir, $log_extentions = array('log')) {
+ if (!is_array($log_extentions)) {
+ $log_extentions = array($log_extentions);
+ }
+
+ # Get logfiles
+ $log_filenames = array();
+ foreach ($log_extentions as $extention) {
+ if ($extention <> '*') {
+ $log_filenames = array_merge($log_filenames, glob($logdir . "*." . $extention));
+ } else {
+ $log_filenames = array_merge($log_filenames, glob($logdir . "*"));
+ }
+ }
+
+ # Convert to filenames only
+ if (count($log_filenames) > 0) {
+ $log_totalfiles = count($log_filenames);
+ for ($cnt = 0; $cnt < $log_totalfiles; $cnt++) {
+ $log_filenames[$cnt] = basename($log_filenames[$cnt]);
+ }
+ }
+
+ # Sort the filename
+ asort($log_filenames);
+
+ # Done
+ return $log_filenames;
+}
+
+# Define logtypes
+# name => Displayname of the type
+# ext => Log extentions (array for multiple extentions)
+# logdir=> Log directory
+# clear => Add clear button (TRUE/FALSE)
+$pfb_logtypes = array( 'defaultlogs' => array('name' => 'Log Files',
+ 'logdir' => "{$pfb['logdir']}/",
+ 'logs' => array("pfblockerng.log", "error.log", "geoip.log", "maxmind_ver"),
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'masterfiles' => array('name' => 'Masterfiles',
+ 'logdir' => "{$pfb['dbdir']}/",
+ 'logs' => array("masterfile", "mastercat"),
+ 'download' => TRUE,
+ 'clear' => FALSE
+ ),
+ 'originallogs' => array('name' => 'Original Files',
+ 'ext' => array('orig', 'raw'),
+ 'logdir' => "{$pfb['origdir']}/",
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'denylogs' => array('name' => 'Deny Files',
+ 'ext' => 'txt',
+ 'txt' => 'deny',
+ 'logdir' => "{$pfb['denydir']}/",
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'permitlogs' => array('name' => 'Permit Files',
+ 'ext' => 'txt',
+ 'txt' => 'permit',
+ 'logdir' => "{$pfb['permitdir']}/",
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'matchlogs' => array('name' => 'Match Files',
+ 'ext' => 'txt',
+ 'txt' => 'match',
+ 'logdir' => "{$pfb['matchdir']}/",
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'nativelogs' => array('name' => 'Native Files',
+ 'ext' => 'txt',
+ 'logdir' => "{$pfb['nativedir']}/",
+ 'download' => TRUE,
+ 'clear' => TRUE
+ ),
+ 'aliaslogs' => array('name' => 'Alias Files',
+ 'ext' => 'txt',
+ 'logdir' => "{$pfb['aliasdir']}/",
+ 'download' => TRUE,
+ 'clear' => FALSE
+ ),
+ 'etiprep' => array('name' => 'ET IPRep Files',
+ 'ext' => '*',
+ 'logdir' => "{$pfb['etdir']}/",
+ 'download' => TRUE,
+ 'clear' => FALSE
+ ),
+ 'country' => array('name' => 'Country Files',
+ 'ext' => 'txt',
+ 'logdir' => "{$pfb['ccdir']}/",
+ 'download' => TRUE,
+ 'clear' => FALSE
+ )
+ );
+
+# Check logtypes
+$logtypeid = 'defaultlogs';
+if (isset($_POST['logtype'])) {
+ $logtypeid = $_POST['logtype'];
+} elseif (isset($_GET['logtype'])) {
+ $logtypeid = htmlspecialchars($_GET['logtype']);
+}
+
+# Check if POST has been set
+if (isset($_POST['file'])) {
+ clearstatcache();
+ $pfb_logfilename = $_POST['file'];
+ $pfb_ext = pathinfo($pfb_logfilename, PATHINFO_EXTENSION);
+
+ # Load log
+ if ($_POST['action'] == 'load') {
+ if (!is_file($pfb_logfilename)) {
+ echo "|3|" . gettext("Log file is empty or does not exist") . ".|";
+ } else {
+ $data = file_get_contents($pfb_logfilename);
+ if ($data === false) {
+ echo "|1|" . gettext("Failed to read log file") . ".|";
+ } else {
+ $data = base64_encode($data);
+ echo "|0|" . $pfb_logfilename . "|" . $data . "|";
+ }
+ }
+ exit;
+ }
+}
+
+if (isset($_POST['logFile'])) {
+ $s_logfile = $_POST['logFile'];
+
+ # Clear selected file
+ if (isset($_POST['clear'])) {
+ unlink_if_exists($s_logfile);
+ }
+
+ # Download log
+ if (isset($_POST['download'])) {
+ if (file_exists($s_logfile)) {
+ ob_start(); //important or other posts will fail
+ if (isset($_SERVER['HTTPS'])) {
+ header('Pragma: ');
+ header('Cache-Control: ');
+ } else {
+ header("Pragma: private");
+ header("Cache-Control: private, must-revalidate");
+ }
+ header("Content-Type: application/octet-stream");
+ header("Content-length: " . filesize($s_logfile));
+ header("Content-disposition: attachment; filename = " . basename($s_logfile));
+ ob_end_clean(); //important or other post will fail
+ readfile($s_logfile);
+ }
+ }
+} else {
+ $s_logfile = "";
+}
+
+$pgtitle = gettext("pfBlockerNG: Log Browser");
+include_once("head.inc");
+?>
+
+<body link="#000000" vlink="#0000CC" alink="#000000">
+
+<?php
+include_once("fbegin.inc");
+if ($input_errors) {
+ print_input_errors($input_errors);
+}
+?>
+<script type="text/javascript" src="/javascript/base64.js"></script>
+<script type="text/javascript">
+//<![CDATA[
+
+ function loadFile() {
+ jQuery("#fileStatus").html("<?=gettext("Loading file"); ?> ...");
+ jQuery("#fileStatusBox").show(250);
+ jQuery("#filePathBox").show(250);
+ jQuery("#fbTarget").html("");
+
+ jQuery.ajax(
+ "<?=$_SERVER['SCRIPT_NAME'];?>", {
+ type: 'POST',
+ data: "instance=" + jQuery("#instance").val() + "&action=load&file=" + jQuery("#logFile").val(),
+ complete: loadComplete
+ }
+ )
+ }
+
+ function loadComplete(req) {
+ jQuery("#fileContent").show(250);
+ var values = req.responseText.split("|");
+ values.shift(); values.pop();
+
+ if(values.shift() == "0") {
+ var file = values.shift();
+ var fileContent = Base64.decode(values.join("|"));
+ jQuery("#fileStatus").html("<?=gettext("File successfully loaded"); ?>.");
+ jQuery("#fbTarget").html(file);
+ jQuery("#fileRefreshBtn").show();
+ jQuery("#fileContent").prop("disabled", false);
+ jQuery("#fileContent").val(fileContent);
+ } else {
+ jQuery("#fileStatus").html(values[0]);
+ jQuery("#fbTarget").html("");
+ jQuery("#fileRefreshBtn").hide();
+ jQuery("#fileContent").val("");
+ jQuery("#fileContent").prop("disabled", true);
+ }
+ }
+//]]>
+</script>
+
+<?php
+echo("<form action='" . $_SERVER['PHP_SELF'] . "' method='post' id='formbrowse'>");
+if ($savemsg) {
+ print_info_box($savemsg);
+}
+?>
+
+<table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=pfblockerng.xml&amp;id=0");
+ $tab_array[] = array(gettext("Update"), false, "/pfblockerng/pfblockerng_update.php");
+ $tab_array[] = array(gettext("Alerts"), false, "/pfblockerng/pfblockerng_alerts.php");
+ $tab_array[] = array(gettext("Reputation"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&id=0");
+ $tab_array[] = array(gettext("IPv4"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml");
+ $tab_array[] = array(gettext("IPv6"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml");
+ $tab_array[] = array(gettext("Top 20"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&id=0");
+ $tab_array[] = array(gettext("Africa"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&id=0");
+ $tab_array[] = array(gettext("Asia"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&id=0");
+ $tab_array[] = array(gettext("Europe"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&id=0");
+ $tab_array[] = array(gettext("N.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("Oceania"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&id=0");
+ $tab_array[] = array(gettext("S.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("P.S."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&id=0");
+ $tab_array[] = array(gettext("Logs"), true, "/pfblockerng/pfblockerng_log.php");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&id=0");
+ display_top_tabs($tab_array, true);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="mainarea">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6">
+ <tbody>
+ <tr>
+ <td colspan="2" class="listtopic"><?php echo gettext("Log/File Browser Selections"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="3" class="vncell" align="left"><?php echo gettext("LINKS :"); ?> &nbsp;
+ <a href='/firewall_aliases.php' target="_blank"><?php echo gettext("Firewall Alias"); ?></a> &nbsp;
+ <a href='/firewall_rules.php' target="_blank"><?php echo gettext("Firewall Rules"); ?></a> &nbsp;
+ <a href='/diag_logs_filter.php' target="_blank"><?php echo gettext("Firewall Logs"); ?></a><br /></td>
+ </tr>
+ <tr>
+ <td width="22%" class="vncell"><?php echo gettext('Log/File type:'); ?></td>
+ <td width="78%" class="vtable">
+ <select name="logtype" id="logtype" class="formselect" onChange="document.getElementById('formbrowse').method='post';document.getElementById('formbrowse').submit()">
+ <?php
+ $clearable = FALSE;
+ $downloadable = FALSE;
+ foreach ($pfb_logtypes as $id => $logtype) {
+ $selected = "";
+ if ($id == $logtypeid) {
+ $selected = " selected";
+ $clearable = $logtype['clear'];
+ $downloadable = $logtype['download'];
+ }
+ echo("<option value='" . $id . "'" . $selected . ">" . $logtype['name'] . "</option>\n");
+ }
+ ?>
+ </select>&nbsp;&nbsp;<?php echo gettext('Choose which type of log/file you want to view.'); ?>
+ </td>
+ </tr>
+ <tr>
+ <td width="22%" class="vncell"><?php echo gettext('Log/File selection:'); ?></td>
+ <td width="78%" class="vtable">
+ <select name="logFile" id="logFile" class="formselect" onChange="loadFile();">
+ <?php
+ if (isset($pfb_logtypes[$logtypeid]['logs'])) {
+ $logs = $pfb_logtypes[$logtypeid]['logs'];
+ } else {
+ $logs = getlogs($pfb_logtypes[$logtypeid]['logdir'], $pfb_logtypes[$logtypeid]['ext']);
+ }
+ foreach ($logs as $log) {
+ $selected = "";
+ if ($log == $pfb_logfilename) {
+ $selected = " selected";
+ }
+ echo("<option value='" . $pfb_logtypes[$logtypeid]['logdir'] . $log . "'" . $selected . ">" . $log . "</option>\n");
+ }
+ ?>
+ </select>&nbsp;&nbsp;<?php echo gettext('Choose which log/file you want to view.'); ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?php echo gettext("Log/File Contents"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table width="100%">
+ <tbody>
+ <tr>
+ <td width="75%">
+ <div style="display:none; " id="fileStatusBox">
+ <div class="list" style="padding-left:15px;">
+ <strong id="fileStatus"></strong>
+ </div>
+ </div>
+ <div style="padding-left:15px; display:none;" id="filePathBox">
+ <strong><?=gettext("Log/File Path"); ?>:</strong>
+ <div class="list" style="display:inline;" id="fbTarget"></div>
+ </div>
+ </td>
+ <td align="right">
+ <div style="padding-right:15px; display:none;" id="fileRefreshBtn">
+ <?php
+ echo("<img src='../tree/page-file.png' onclick='loadFile()' title='" . gettext("Refresh current display") . "' alt='refresh' width='17' height='17' border='0' /> &nbsp;");
+ if ($downloadable) {
+ echo("<input type='image' src='../tree/page-file_play.gif' name='download[]' id='download' value='Download' title='" . gettext("Download current logfile") . "' alt='download' width='17' height='17' border='0' /> &nbsp;");
+ }
+ if ($clearable) {
+ echo("<input type='image' src='../tree/page-file_x.gif' name='clear[]' id='clear' value='Clear' title='" . gettext("Clear current logfile") . "' alt='clear' width='17' height='17' border='0' />");
+ }
+ ?>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table width="100%">
+ <tbody>
+ <tr>
+ <td valign="top" class="label">
+ <div style="background:#eeeeee;" id="fileOutput">
+ <textarea id="fileContent" name="fileContent" style="width:100%;" rows="30" wrap="off" disabled></textarea>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </td>
+ </tr>
+</table>
+</form>
+
+<?php if (!isset($_POST['file'])): ?>
+<script type="text/javascript">
+//<![CDATA[
+ document.getElementById("logFile").selectedIndex=-1;
+//]]>
+</script>
+<?php endif; ?>
+<?php include("fend.inc"); ?>
+</body>
+</html> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_sync.xml b/config/pfblockerng/pfblockerng_sync.xml
new file mode 100644
index 00000000..00186af8
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_sync.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ pfBlockerNG_sync.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockerngsync</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: XMLRPC Sync</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <tooltiptext>Configure pfBlockerNG</tooltiptext>
+ <section>Services</section>
+ <url>pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <name>pfBlockerNG XMLRPC Sync Settings</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr>Enable Sync</fielddescr>
+ <fieldname>varsynconchanges</fieldname>
+ <description><![CDATA[When enabled, this will sync all configuration settings to the Replication Targets.<br /><br />
+ <b>Important:</b> While using "Sync to hosts defined below", only sync from host A to B, A to C
+ <br /> but <b>do not</b> enable XMLRPC sync <b>to</b> A. This will result in a loop!]]>
+ </description>
+ <type>select</type>
+ <required/>
+ <default_value>disabled</default_value>
+ <options>
+ <option><name>Do not sync this package configuration</name><value>disabled</value></option>
+ <option><name>Sync to configured system backup server</name><value>auto</value></option>
+ <option><name>Sync to host(s) defined below</name><value>manual</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>XMLRPC Timeout</fielddescr>
+ <fieldname>varsynctimeout</fieldname>
+ <description><![CDATA[Timeout in seconds for the XMLRPC timeout. Default: 150]]></description>
+ <type>input</type>
+ <default_value>150</default_value>
+ <size>5</size>
+ </field>
+ <field>
+ <fielddescr><![CDATA[Disable 'General Tab' sync]]></fielddescr>
+ <fieldname>syncinterfaces</fieldname>
+ <description>When selected, the 'General' Tab Customizations will not be sync'd</description>
+ <type>checkbox</type>
+ </field>
+ <field>
+ <name>pfBlockerNG XMLRPC Replication Targets</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>Replication Targets</fielddescr>
+ <fieldname>none</fieldname>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Enable</fielddescr>
+ <fieldname>varsyncdestinenable</fieldname>
+ <description><![CDATA[Enable this host as a replication target]]></description>
+ <type>checkbox</type>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Protocol</fielddescr>
+ <fieldname>varsyncprotocol</fieldname>
+ <description><![CDATA[Choose the protocol of the destination host. Probably <b>http</b> or <b>https</b>]]></description>
+ <type>select</type>
+ <default_value>HTTP</default_value>
+ <options>
+ <option><name>HTTP</name><value>http</value></option>
+ <option><name>HTTPS</name><value>https</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Target IP Address</fielddescr>
+ <fieldname>varsyncipaddress</fieldname>
+ <description><![CDATA[IP Address of the destination host.]]></description>
+ <type>input</type>
+ <size>15</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Target Port</fielddescr>
+ <fieldname>varsyncport</fieldname>
+ <description><![CDATA[Choose the sync port of the destination host.]]></description>
+ <type>input</type>
+ <size>3</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Target Username (admin)</fielddescr>
+ <fieldname>varsyncusername</fieldname>
+ <description><![CDATA[Enter the Username Account for Authentication]]></description>
+ <type>input</type>
+ <size>15</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Target Password</fielddescr>
+ <fieldname>varsyncpassword</fieldname>
+ <description><![CDATA[Password of the user "admin" on the destination host.]]></description>
+ <type>password</type>
+ <size>20</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]></name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input($_POST, $input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+ write_config("[pfBlockerNG] XMLRPC sync configurations saved.");
+ pfblockerng_sync_on_changes();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_top20.xml b/config/pfblockerng/pfblockerng_top20.xml
new file mode 100644
index 00000000..ccaf68a0
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_top20.xml
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* $Id$ */
+/* ========================================================================== */
+/*
+ pfBlockerNG_Top20.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockerngtopspammers</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: Top 20 Spammer Countries</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <tooltiptext>Configure pfblockerNG</tooltiptext>
+ <section>Firewall</section>
+ <url>pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <fields>
+ <field>
+ <name><![CDATA[TOP 20 - Spammer Countries&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Geolite Data by Maxmind Inc. - ISO 3166)]]></name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<br /><strong>Top 20 IPv4</strong><br />Spammer Countries]]></fielddescr>
+ <fieldname>countries4</fieldname>
+ <description>
+ <![CDATA[Select Top IPv4 Spammer Countries you want to take an action on.<br />
+ <strong>Use CTRL + CLICK to unselect countries</strong>]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>China-CN</name><value>CN</value></option>
+ <option><name>Russia-RU</name><value>RU</value></option>
+ <option><name>Japan-JP</name><value>JP</value></option>
+ <option><name>Ukraine-UA</name><value>UA</value></option>
+ <option><name>United Kingdom-GB</name><value>GB</value></option>
+ <option><name>Germany-DE</name><value>DE</value></option>
+ <option><name>Brazil-BR</name><value>BR</value></option>
+ <option><name>France-FR</name><value>FR</value></option>
+ <option><name>India-IN</name><value>IN</value></option>
+ <option><name>Turkey-TR</name><value>TR</value></option>
+ <option><name>Italy-IT</name><value>IT</value></option>
+ <option><name>South Korea-KR</name><value>KR</value></option>
+ <option><name>Poland-PL</name><value>PL</value></option>
+ <option><name>Spain-ES</name><value>ES</value></option>
+ <option><name>Vietnam-VN</name><value>VN</value></option>
+ <option><name>Argentina-AR</name><value>AR</value></option>
+ <option><name>Columbia-CO</name><value>CO</value></option>
+ <option><name>Taiwan-TW</name><value>TW</value></option>
+ <option><name>Mexico-MX</name><value>MX</value></option>
+ <option><name>Chilie-CL</name><value>CL</value></option>
+ </options>
+ <size>20</size>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<br /><strong>Top 20 IPv6</strong><br />Spammer Countries]]></fielddescr>
+ <fieldname>countries6</fieldname>
+ <description>
+ <![CDATA[Select Top IPv6 Spammer Countries you want to take an action on.<br />
+ <strong>Use CTRL + CLICK to unselect countries</strong>]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>China-CN</name><value>CN</value></option>
+ <option><name>Russia-RU</name><value>RU</value></option>
+ <option><name>Japan-JP</name><value>JP</value></option>
+ <option><name>Ukraine-UA</name><value>UA</value></option>
+ <option><name>United Kingdom-GB</name><value>GB</value></option>
+ <option><name>Germany-DE</name><value>DE</value></option>
+ <option><name>Brazil-BR</name><value>BR</value></option>
+ <option><name>France-FR</name><value>FR</value></option>
+ <option><name>India-IN</name><value>IN</value></option>
+ <option><name>Turkey-TR</name><value>TR</value></option>
+ <option><name>Italy-IT</name><value>IT</value></option>
+ <option><name>South Korea-KR</name><value>KR</value></option>
+ <option><name>Poland-PL</name><value>PL</value></option>
+ <option><name>Spain-ES</name><value>ES</value></option>
+ <option><name>Vietnam-VN</name><value>VN</value></option>
+ <option><name>Argentina-AR</name><value>AR</value></option>
+ <option><name>Columbia-CO</name><value>CO</value></option>
+ <option><name>Taiwan-TW</name><value>TW</value></option>
+ <option><name>Mexico-MX</name><value>MX</value></option>
+ <option><name>Chilie-CL</name><value>CL</value></option>
+ </options>
+ <size>20</size>
+ <multiple/>
+ </field>
+ <field>
+ <fielddescr>List Action</fielddescr>
+ <description><![CDATA[<br />Default : <strong>Disabled</strong><br /><br />
+ Select the <strong>Action</strong> for Firewall Rules on lists you have selected.<br /><br />
+ <strong><u>'Disabled' Rules:</u></strong> Disables selection and does nothing to selected Alias.<br /><br />
+
+ <strong><u>'Deny' Rules:</u></strong><br />
+ 'Deny' rules create high priority 'block' or 'reject' rules on the stated interfaces. They don't change the 'pass' rules on other
+ interfaces. Typical uses of 'Deny' rules are:<br />
+ <ul><li><strong>Deny Both</strong> - blocks all traffic in both directions, if the source or destination IP is in the block list</li>
+ <li><strong>Deny Inbound/Deny Outbound</strong> - blocks all traffic in one direction <u>unless</u> it is part of a session started by
+ traffic sent in the other direction. Does not affect traffic in the other direction. </li>
+ <li>One way 'Deny' rules can be used to selectively block <u>unsolicited</u> incoming (new session) packets in one direction, while
+ still allowing <u>deliberate</u> outgoing sessions to be created in the other direction.</li></ul>
+ <strong><u>'Permit' Rules:</u></strong><br />
+ 'Permit' rules create high priority 'pass' rules on the stated interfaces. They are the opposite of Deny rules, and don't create
+ any 'blocking' effect anywhere. They have priority over all Deny rules. Typical uses of 'Permit' rules are:<br />
+ <ul><li><strong>To ensure</strong> that traffic to/from the listed IPs will <u>always</u> be allowed in the stated directions. They
+ override <u>almost all other</u> Firewall rules on the stated interfaces.</li>
+ <li><strong>To act as a whitelist</strong> for Deny rule exceptions, for example if a large IP range or pre-created blocklist blocks a
+ few IPs that should be accessible.</li></ul>
+ <strong><u>'Match' Rules:</u></strong><br />
+ 'Match' or 'Log' only the traffic on the stated interfaces. This does not Block or Reject. It just Logs the traffic.
+ <ul><li><strong>Match Both</strong> - Matches all traffic in both directions, if the source or destination IP is in the list.</li>
+ <li><strong>Match Inbound/Match Outbound</strong> - Matches all traffic in one direction only.</li></ul>
+ <strong><u>'Alias' Rules:</u></strong><br />
+ <strong>'Alias'</strong> rules create an <a href="/firewall_aliases.php">alias</a> for the list (and do nothing else).
+ This enables a pfBlockerNG list to be used by name, in any firewall rule or pfSense function, as desired.
+ <ul><li><strong>Options &nbsp;&nbsp; - Alias Deny,&nbsp; Alias Permit,&nbsp; Alias Match,&nbsp; Alias Native</strong></li><br />
+ <li>'Alias Deny' can use De-Duplication and Reputation Processes if configured.</li><br />
+ <li>'Alias Permit' and 'Alias Match' will be saved in the Same folder as the other Permit/Match Auto-Rules</li><br />
+ <li>'Alias Native' lists are kept in their Native format without any modifications.</li></ul>
+ <strong>When using 'Alias' rules, change (pfB_) to ( pfb_ ) in the beginning of rule description and Use the 'Exact' spelling of
+ the Alias (no trailing Whitespace)&nbsp;</strong> Custom 'Alias' rules with 'pfB_ xxx' description will be removed by package if
+ using Auto Rule Creation.<br /><br /><strong>Tip</strong>: You can create the Auto Rules and remove "<u>auto rule</u>" from the Rule
+ Descriptions, then disable Auto Rules. This method will 'KEEP' these rules from being 'Deleted' which will allow editing for a Custom
+ Alias Configuration<br />]]>
+ </description>
+ <fieldname>action</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Disabled</name><value>Disabled</value></option>
+ <option><name>Deny Inbound</name><value>Deny_Inbound</value></option>
+ <option><name>Deny Outbound</name><value>Deny_Outbound</value></option>
+ <option><name>Deny Both</name><value>Deny_Both</value></option>
+ <option><name>Permit Inbound</name><value>Permit_Inbound</value></option>
+ <option><name>Permit Outbound</name><value>Permit_Outbound</value></option>
+ <option><name>Permit Both</name><value>Permit_Both</value></option>
+ <option><name>Match Inbound</name><value>Match_Inbound</value></option>
+ <option><name>Match Outbound</name><value>Match_Outbound</value></option>
+ <option><name>Match Both</name><value>Match_Both</value></option>
+ <option><name>Alias Deny</name><value>Alias_Deny</value></option>
+ <option><name>Alias Permit</name><value>Alias_Permit</value></option>
+ <option><name>Alias Match</name><value>Alias_Match</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ <description><![CDATA[Default:<strong>Enable</strong><br />
+ Select - Logging to Status: System Logs: FIREWALL ( Log )]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Enable</name><value>enabled</value></option>
+ <option><name>Disable</name><value>disabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]> </name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input($_POST, $input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global $pfb;
+ $pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_update.php b/config/pfblockerng/pfblockerng_update.php
new file mode 100644
index 00000000..99480900
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_update.php
@@ -0,0 +1,426 @@
+<?php
+
+/* pfBlockerNG_Update.php
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Portions of this code are based on original work done for
+ pfSense from the following contributors:
+
+ pkg_mgr_install.php
+ Part of pfSense (https://www.pfsense.org)
+ Copyright (C) 2004-2010 Scott Ullrich <sullrich@gmail.com>
+ Copyright (C) 2005 Colin Smith
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+
+require_once("guiconfig.inc");
+require_once("globals.inc");
+require_once("pfsense-utils.inc");
+require_once("functions.inc");
+require_once("util.inc");
+require_once("/usr/local/pkg/pfblockerng/pfblockerng.inc");
+
+pfb_global();
+
+// Collect pfBlockerNG log file and post Live output to Terminal window.
+function pfbupdate_output($text) {
+ $text = preg_replace("/\n/", "\\n", $text);
+ echo "\n<script type=\"text/javascript\">";
+ echo "\n//<![CDATA[";
+ echo "\nthis.document.forms[0].pfb_output.value = \"" . $text . "\";";
+ echo "\nthis.document.forms[0].pfb_output.scrollTop = this.document.forms[0].pfb_output.scrollHeight;";
+ echo "\n//]]>";
+ echo "\n</script>";
+ /* ensure that contents are written out */
+ ob_flush();
+}
+
+// Post Status Message to Terminal window.
+function pfbupdate_status($status) {
+ $status = preg_replace("/\n/", "\\n", $status);
+ echo "\n<script type=\"text/javascript\">";
+ echo "\n//<![CDATA[";
+ echo "\nthis.document.forms[0].pfb_status.value=\"" . $status . "\";";
+ echo "\n//]]>";
+ echo "\n</script>";
+ /* ensure that contents are written out */
+ ob_flush();
+}
+
+
+// Function to perform a Force Update, Cron or Reload
+function pfb_cron_update($type) {
+
+ global $pfb;
+
+ // Query for any Active pfBlockerNG CRON Jobs
+ $result_cron = array();
+ $cron_event = exec ("/bin/ps -wx", $result_cron);
+ if (preg_grep("/pfblockerng[.]php\s+cron/", $result_cron) || preg_grep("/pfblockerng[.]php\s+update/", $result_cron)) {
+ pfbupdate_status(gettext("Force {$type} Terminated - Failed due to Active Running Task"));
+ exit;
+ }
+
+ if (!file_exists("{$pfb['log']}"))
+ touch("{$pfb['log']}");
+
+ // Update Status Window with correct Task
+ if ($type == "update") {
+ pfbupdate_status(gettext("Running Force Update Task"));
+ } elseif ($type == "reload") {
+ pfbupdate_status(gettext("Running Force Reload Task"));
+ $type = "update";
+ } else {
+ pfbupdate_status(gettext("Running Force CRON Task"));
+ }
+
+ // Remove any existing pfBlockerNG CRON Jobs
+ install_cron_job("pfblockerng.php cron", false);
+ write_config();
+
+ // Execute PHP Process in the Background
+ mwexec_bg("/usr/local/bin/php /usr/local/www/pfblockerng/pfblockerng.php {$type} >> {$pfb['log']} 2>&1");
+
+ // Start at EOF
+ $lastpos_old = "";
+ $len = filesize("{$pfb['log']}");
+ $lastpos = $len;
+
+ while (true) {
+ usleep(300000); //0.3s
+ clearstatcache(false,$pfb['log']);
+ $len = filesize("{$pfb['log']}");
+ if ($len < $lastpos) {
+ //file deleted or reset
+ $lastpos = $len;
+ } else {
+ $f = fopen($pfb['log'], "rb");
+ if ($f === false)
+ die();
+ fseek($f, $lastpos);
+
+ while (!feof($f)) {
+
+ $pfb_buffer = fread($f, 2048);
+ $pfb_output .= str_replace( array ("\r", "\")"), "", $pfb_buffer);
+
+ // Refresh on new lines only. This allows Scrolling.
+ if ($lastpos != $lastpos_old)
+ pfbupdate_output($pfb_output);
+ $lastpos_old = $lastpos;
+ ob_flush();
+ flush();
+ }
+ $lastpos = ftell($f);
+ fclose($f);
+ }
+ // Capture Remaining Output before closing File
+ if (preg_match("/(UPDATE PROCESS ENDED)/",$pfb_output)) {
+ $f = fopen($pfb['log'], "rb");
+ fseek($f, $lastpos);
+ $pfb_buffer = fread($f, 2048);
+ $pfb_output .= str_replace( "\r", "", $pfb_buffer);
+ pfbupdate_output($pfb_output);
+ clearstatcache(false,$pfb['log']);
+ ob_flush();
+ flush();
+ fclose($f);
+ # Call Log Mgmt Function
+ pfb_log_mgmt();
+ die();
+ }
+ }
+}
+
+
+$pgtitle = gettext("pfBlockerNG: Update");
+include_once("head.inc");
+?>
+<body link="#000000" vlink="#0000CC" alink="#000000">
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<?php include_once("fbegin.inc"); ?>
+
+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
+ <tr>
+ <td>
+ <?php
+ $tab_array = array();
+ $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=pfblockerng.xml&amp;id=0");
+ $tab_array[] = array(gettext("Update"), true, "/pfblockerng/pfblockerng_update.php");
+ $tab_array[] = array(gettext("Alerts"), false, "/pfblockerng/pfblockerng_alerts.php");
+ $tab_array[] = array(gettext("Reputation"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&id=0");
+ $tab_array[] = array(gettext("IPv4"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml");
+ $tab_array[] = array(gettext("IPv6"), false, "/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml");
+ $tab_array[] = array(gettext("Top 20"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&id=0");
+ $tab_array[] = array(gettext("Africa"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&id=0");
+ $tab_array[] = array(gettext("Asia"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&id=0");
+ $tab_array[] = array(gettext("Europe"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&id=0");
+ $tab_array[] = array(gettext("N.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("Oceania"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&id=0");
+ $tab_array[] = array(gettext("S.A."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&id=0");
+ $tab_array[] = array(gettext("P.S."), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&id=0");
+ $tab_array[] = array(gettext("Logs"), false, "/pfblockerng/pfblockerng_log.php");
+ $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&id=0");
+ display_top_tabs($tab_array, true);
+ ?>
+ </td>
+ </tr>
+ </table>
+ <div id="mainareapkg">
+ <table id="maintable" class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="2">
+ <tr>
+ <td colspan="2" class="vncell" align="left"><?php echo gettext("LINKS :"); ?>&nbsp;
+ <a href='/firewall_aliases.php' target="_blank"><?php echo gettext("Firewall Alias"); ?></a>&nbsp;
+ <a href='/firewall_rules.php' target="_blank"><?php echo gettext("Firewall Rules"); ?></a>&nbsp;
+ <a href='/diag_logs_filter.php' target="_blank"><?php echo gettext("Firewall Logs"); ?></a><br />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?php echo gettext("CRON Status"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listr">
+ <?php
+ // Collect Existing CRON settings
+ if (is_array($config['cron']['item'])) {
+ foreach ($config['cron']['item'] as $cron) {
+ if (preg_match("/usr.local.www.pfblockerng.pfblockerng.php cron/",$cron["command"])) {
+ $pfb_min = "{$cron['minute']}";
+ break;
+ }
+ }
+ }
+ // Calculate Minutes Remaining till next CRON Event.
+ $currentmin = date('i');
+ switch ($pfb_min) {
+ case "0":
+ $min_remain = (60 - $currentmin);
+ break;
+ case "15":
+ if ($currentmin < 15) {
+ $min_remain = (15 - $currentmin);
+ } else {
+ $min_remain = (75 - $currentmin);
+ }
+ break;
+ case "30":
+ if ($currentmin < 30) {
+ $min_remain = (30 - $currentmin);
+ } else {
+ $min_remain = (90 - $currentmin);
+ }
+ break;
+ case "45":
+ if ($currentmin < 45) {
+ $min_remain = (45 - $currentmin);
+ } else {
+ $min_remain = (105 - $currentmin);
+ }
+ break;
+ }
+
+ // Default to "< 1 minute" if empty
+ if (empty($min_remain))
+ $min_remain = "< 1";
+
+ // Next Scheduled Cron Time
+ if ($pfb_min == "0")
+ $pfb_min = "00";
+ $nextcron = (date('H') +1) . ":{$pfb_min}";
+
+ // If pfBlockerNG is Disabled or Cron Task is Missing
+ if (empty($pfb['enable']) || empty($pfb_min)) {
+ $min_remain = " -- ";
+ $nextcron = " [ Disabled ] ";
+ }
+
+ echo "NEXT Scheduled CRON Event will run at <font size=\"3\">&nbsp;{$nextcron}</font>&nbsp; in<font size=\"3\">
+ <span class=\"red\">&nbsp;{$min_remain}&nbsp;</span></font> Minutes.";
+
+ // Query for any Active pfBlockerNG CRON Jobs
+ $result_cron = array();
+ $cron_event = exec ("/bin/ps -wax", $result_cron);
+ if (preg_grep("/pfblockerng[.]php\s+cron/", $result_cron)) {
+ echo "<font size=\"2\"><span class=\"red\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Active pfBlockerNG CRON Job </span></font>&nbsp;&nbsp;";
+ echo "<img src = '/themes/{$g['theme']}/images/icons/icon_pass.gif' width='15' height='15'
+ border='0' title='pfBockerNG Cron Task is Running.'/>";
+ }
+ echo "<br /><font size=\"3\"><span class=\"red\">Refresh</span></font> to update current Status and Minute(s) remaining";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="vncell"><?php echo gettext("<br />"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?php echo gettext("Update Options"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listr">
+ <!-- Update Option Text -->
+ <?php echo "<span class='red'><strong>" . gettext("** AVOID ** ") . "&nbsp;" . "</strong></span>" .
+ gettext("Running these Options - when CRON is expected to RUN!") . gettext("<br /><br />") .
+ "<strong>" . gettext("Force Update") . "</strong>" . gettext(" will download any new Alias/Lists.") .
+ gettext("<br />") . "<strong>" . gettext("Force Cron") . "</strong>" .
+ gettext(" will download any Alias/Lists that are within the Frequency Setting (due for Update).") . gettext("<br />") .
+ "<strong>" . gettext("Force Reload") . "</strong>" .
+ gettext(" will reload all Lists using the existing Downloaded files.") .
+ gettext(" This is useful when Lists are out of 'sync' or Reputation changes were made.") ;?><br />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="vncell">
+ <!-- Update Option Buttons -->
+ <input type="submit" class="formbtns" name="pfbupdate" id="pfbupdate" value="Force Update"
+ title="<?=gettext("Run Force Update");?>" />
+ <input type="submit" class="formbtns" name="pfbcron" id="pfbcron" value="Force Cron"
+ title="<?=gettext("Run Force Cron Update");?>" />
+ <input type="submit" class="formbtns" name="pfbreload" id="pfbreload" value="Force Reload"
+ title="<?=gettext("Run Force Reload");?>" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="vncell"><?php echo gettext("<br />"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listtopic"><?php echo gettext("Live Log Viewer only"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="listr"><?php echo gettext("Selecting 'Live Log Viewer' will allow viewing a running Cron Update"); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2" class="vncell">
+ <!-- Log Viewer Buttons -->
+ <input type="submit" class="formbtns" name="pfbview" id="pfbview" value="VIEW"
+ title="<?=gettext("VIEW pfBlockerNG LOG");?>"/>
+ <input type="submit" class="formbtns" name="pfbviewcancel" id="pfbviewcancel" value="End View"
+ title="<?=gettext("END VIEW of pfBlockerNG LOG");?>"/>
+ <?php echo "&nbsp;&nbsp;" . gettext(" Select 'view' to open ") . "<strong>" . gettext(' pfBlockerNG ') . "</strong>" .
+ gettext(" Log. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Select 'End View' to terminate the viewer.)"); ?><br /><br />
+ </td>
+ </tr>
+ <tr>
+ <td class="tabcont" align="left">
+ <!-- status box -->
+ <textarea cols="90" rows="1" name="pfb_status" id="pfb_status"
+ wrap="hard"><?=gettext("Log Viewer Standby");?></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <!-- command output box -->
+ <textarea cols="90" rows="35" name="pfb_output" id="pfb_output" wrap="hard"></textarea>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+<?php
+include("fend.inc");
+
+// Execute the Viewer output Window
+if (isset($_POST['pfbview'])) {
+
+ if (!file_exists("{$pfb['log']}"))
+ touch("{$pfb['log']}");
+
+ // Reference: http://stackoverflow.com/questions/3218895/php-how-to-read-a-file-live-that-is-constantly-being-written-to
+ pfbupdate_status(gettext("Log Viewing in progress. ** Press 'END VIEW' to Exit ** "));
+ $lastpos_old = "";
+ $len = filesize("{$pfb['log']}");
+
+ // Start at EOF ( - 15000)
+ if ($len > 15000) {
+ $lastpos = ($len - 15000);
+ } else {
+ $lastpos = 0;
+ }
+
+ while (true) {
+ usleep(300000); //0.3s
+ clearstatcache(false,$pfb['log']);
+ $len = filesize("{$pfb['log']}");
+ if ($len < $lastpos) {
+ //file deleted or reset
+ $lastpos = $len;
+ } else {
+ $f = fopen($pfb['log'], "rb");
+ if ($f === false)
+ die();
+ fseek($f, $lastpos);
+
+ while (!feof($f)) {
+
+ $pfb_buffer = fread($f, 4096);
+ $pfb_output .= str_replace( array ("\r", "\")"), "", $pfb_buffer);
+
+ // Refresh on new lines only. This allows scrolling.
+ if ($lastpos != $lastpos_old) {
+ pfbupdate_output($pfb_output);
+ }
+ $lastpos_old = $lastpos;
+ ob_flush();
+ flush();
+ }
+ $lastpos = ftell($f);
+ fclose($f);
+ }
+ }
+}
+
+// End the Viewer output Window
+if (isset($_POST['pfbviewcancel'])) {
+ clearstatcache(false,$pfb['log']);
+ ob_flush();
+ flush();
+ fclose("{$pfb['log']}");
+}
+
+// Execute a Force Update
+if (isset($_POST['pfbupdate']) && $pfb['enable'] == "on") {
+ pfb_cron_update(update);
+}
+
+// Execute a CRON Command to update any Lists within the Frequency Settings
+if (isset($_POST['pfbcron']) && $pfb['enable'] == "on") {
+ pfb_cron_update(cron);
+}
+
+// Execute a Reload of all Aliases and Lists
+if (isset($_POST['pfbreload']) && $pfb['enable'] == "on") {
+ $config['installedpackages']['pfblockerng']['config'][0]['pfb_reuse'] = "on";
+ write_config();
+ pfb_cron_update(reload);
+}
+
+?>
+</form>
+</body>
+</html> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_v4lists.xml b/config/pfblockerng/pfblockerng_v4lists.xml
new file mode 100644
index 00000000..6df839ed
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_v4lists.xml
@@ -0,0 +1,426 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* ========================================================================== */
+/*
+ pfBlockerNG_v4lists.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2010 Scott Ullrich <sullrich@gmail.com>
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockernglistsv4</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: IPv4 Alias/List Configuration</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <tooltiptext></tooltiptext>
+ <section>Firewall</section>
+ <configfile>pfblockerng_v4lists.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ <tooltiptext></tooltiptext>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Alias Name</fielddescr>
+ <fieldname>aliasname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Alias Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Action</fielddescr>
+ <fieldname>action</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Frequency</fielddescr>
+ <fieldname>cron</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <name><![CDATA[IPv4 Network ranges / CIDR lists &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ (When Removing or Re-configuring Lists a 'Reload' is recommended.)]]></name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr>Alias Name</fielddescr>
+ <fieldname>aliasname</fieldname>
+ <description><![CDATA[Enter lists Alias Names.<br />
+ Example: Badguys<br />
+ Do not include <strong>'pfBlocker' or 'pfB_'</strong> in the Alias Name, it's done by package.<br />
+ <strong>International, special or space characters will be ignored in firewall alias names.
+ </strong><br />]]>
+ </description>
+ <type>input</type>
+ <size>20</size>
+ </field>
+ <field>
+ <fielddescr>List Description</fielddescr>
+ <fieldname>description</fieldname>
+ <type>input</type>
+ <size>90</size>
+ </field>
+ <field>
+ <fieldname>InfoLists</fieldname>
+ <type>info</type>
+ <description><![CDATA[<strong><u>'Format'</u></strong> : Select the Format Type<br /><br />
+ <strong><u>'URL'</u></strong> : Add direct link to list:
+ Example: <a target=_new href='http://list.iblocklist.com/?list=bt_ads&fileformat=p2p&archiveformat=gz'>Ads</a>,
+ <a target=_new href='http://list.iblocklist.com/?list=bt_spyware&fileformat=p2p&archiveformat=gz'>Spyware</a>,
+ <a target=_new href='http://list.iblocklist.com/?list=bt_proxy&fileformat=p2p&archiveformat=gz'>Proxies</a> )<br /><br />
+ <strong><u>'pfSense Local File'</u></strong> Format :<br /><br />
+ &nbsp;&nbsp;http(s)://127.0.0.1/NAME_OF_FILE &nbsp;&nbsp;<strong>or</strong>&nbsp;&nbsp;
+ /usr/local/www/NAME_OF_FILE &nbsp;&nbsp; (Files can also be placed in the /var/db/pfblockerng folders)<br /><br />
+
+ <strong><u>'Header'</u></strong> : The <u>'Header' Field</u> must be <u>Unique</u>, it will
+ name the List File and it will be referenced in the pfBlockerNG Widget.
+ Use a Unique Prefix per 'Alias Category' followed by a unique descriptor for each List.<br /><br />]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>IPv4</strong> Lists]]></fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<br /><strong>'Format'</strong> - Select the file format that URL will retrieve.<br />
+
+ <ul><li><strong>'txt'</strong> Plain txt Lists</li><br />
+ <li><strong>'gz'</strong> - IBlock GZ Lists in Range Format only.</li><br />
+ <li><strong>'gz_2'</strong> - Other GZ Lists in IP or CIDR only.</li><br />
+ <li><strong>'gz_lg'</strong> - Large IBlock GZ Lists in Range Format only.</li><br />
+ <li><strong>'zip'</strong> - ZIP'd Lists</li><br />
+ <li><strong>'block'</strong>- IP x.x.x.0 Block type</li><br />
+ <li><strong>'html'</strong> - Web Links</li><br />
+ <li><strong>'xlsx'</strong> - Excel Lists</li><br />
+ <li><strong>'rsync'</strong> - RSync Lists</li><br />
+ <li><strong>'ET' IQRisk</strong> - Only</li></ul>
+ <strong>'State'</strong> - Select the Run State for each list.<br />
+ <ul><li><strong>'ON/OFF'</strong> - Enabled / Disabled</li><br />
+ <li><strong>'HOLD'</strong> - Once a List has been Downloaded, list will remain Static.</li></ul>
+ <strong>'Note' -</strong> Downloaded or pfsense local file must have only one network per line and follows the syntax below:
+ <ul>Network ranges: <strong>172.16.1.0-172.16.1.255</strong><br />
+ IP Address: <strong>172.16.1.10</strong><br />
+ CIDR: <strong>172.16.1.0/24</strong></ul>]]>
+ </description>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Format</fielddescr>
+ <fieldname>format</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>txt</name><value>txt</value></option>
+ <option><name>gz</name><value>gz</value></option>
+ <option><name>gz_2</name><value>gz_2</value></option>
+ <option><name>gz_lg</name><value>gz_lg</value></option>
+ <option><name>zip</name><value>zip</value></option>
+ <option><name>block</name><value>block</value></option>
+ <option><name>html</name><value>html</value></option>
+ <option><name>xlsx</name><value>xlsx</value></option>
+ <option><name>RSync</name><value>rsync</value></option>
+ <option><name>ET</name><value>et</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>State</fielddescr>
+ <fieldname>state</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>ON</name><value>Enabled</value></option>
+ <option><name>OFF</name><value>Disabled</value></option>
+ <option><name>HOLD</name><value>Hold</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>URL or pfSense local file</fielddescr>
+ <fieldname>url</fieldname>
+ <type>input</type>
+ <size>50</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Header</fielddescr>
+ <fieldname>header</fieldname>
+ <type>input</type>
+ <size>15</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <fielddescr>List Action</fielddescr>
+ <description><![CDATA[<br />Default : <strong>Disabled</strong><br /><br />
+ Select the <strong>Action</strong> for Firewall Rules on lists you have selected.<br /><br />
+ <strong><u>'Disabled' Rules:</u></strong> Disables selection and does nothing to selected Alias.<br /><br />
+
+ <strong><u>'Deny' Rules:</u></strong><br />
+ 'Deny' rules create high priority 'block' or 'reject' rules on the stated interfaces. They don't change the 'pass' rules on other
+ interfaces. Typical uses of 'Deny' rules are:<br />
+ <ul><li><strong>Deny Both</strong> - blocks all traffic in both directions, if the source or destination IP is in the block list</li>
+ <li><strong>Deny Inbound/Deny Outbound</strong> - blocks all traffic in one direction <u>unless</u> it is part of a session started by
+ traffic sent in the other direction. Does not affect traffic in the other direction.</li>
+ <li>One way 'Deny' rules can be used to selectively block <u>unsolicited</u> incoming (new session) packets in one direction, while
+ still allowing <u>deliberate</u> outgoing sessions to be created in the other direction.</li></ul>
+ <strong><u>'Permit' Rules:</u></strong><br />
+ 'Permit' rules create high priority 'pass' rules on the stated interfaces. They are the opposite of Deny rules, and don't create
+ any 'blocking' effect anywhere. They have priority over all Deny rules. Typical uses of 'Permit' rules are:<br />
+ <ul><li><strong>To ensure</strong> that traffic to/from the listed IPs will <u>always</u> be allowed in the stated directions. They
+ override <u>almost all other</u> Firewall rules on the stated interfaces.</li>
+ <li><strong>To act as a whitelist</strong> for Deny rule exceptions, for example if a large IP range or pre-created blocklist blocks a
+ few IPs that should be accessible.</li></ul>
+ <strong><u>'Match' Rules:</u></strong><br />
+ 'Match' or 'Log' only the traffic on the stated interfaces. This does not Block or Reject. It just Logs the traffic.
+ <ul><li><strong>Match Both</strong> - Matches all traffic in both directions, if the source or destination IP is in the list.</li>
+ <li><strong>Match Inbound/Match Outbound</strong> - Matches all traffic in one direction only.</li></ul>
+ <strong><u>'Alias' Rules:</u></strong><br />
+ <strong>'Alias'</strong> rules create an <a href="/firewall_aliases.php">alias</a> for the list (and do nothing else).
+ This enables a pfBlockerNG list to be used by name, in any firewall rule or pfSense function, as desired.
+ <ul><li><strong>Options &nbsp;&nbsp; - Alias Deny,&nbsp; Alias Permit,&nbsp; Alias Match,&nbsp; Alias Native</strong></li><br />
+ <li>'Alias Deny' can use De-Duplication and Reputation Processes if configured.</li><br />
+ <li>'Alias Permit' and 'Alias Match' will be saved in the Same folder as the other Permit/Match Auto-Rules</li><br />
+ <li>'Alias Native' lists are kept in their Native format without any modifications.</li></ul>
+ <strong>When using 'Alias' rules, change (pfB_) to ( pfb_ ) in the beginning of rule description and Use the 'Exact' spelling of
+ the Alias (no trailing Whitespace)&nbsp;</strong> Custom 'Alias' rules with 'pfB_ xxx' description will be removed by package if
+ using Auto Rule Creation.<br /><br /><strong>Tip</strong>: You can create the Auto Rules and remove "<u>auto rule</u>" from the Rule
+ Descriptions, then disable Auto Rules. This method will 'KEEP' these rules from being 'Deleted' which will allow editing for a Custom
+ Alias Configuration<br />]]>
+ </description>
+ <fieldname>action</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Disabled</name><value>Disabled</value></option>
+ <option><name>Deny Inbound</name><value>Deny_Inbound</value></option>
+ <option><name>Deny Outbound</name><value>Deny_Outbound</value></option>
+ <option><name>Deny Both</name><value>Deny_Both</value></option>
+ <option><name>Permit Inbound</name><value>Permit_Inbound</value></option>
+ <option><name>Permit Outbound</name><value>Permit_Outbound</value></option>
+ <option><name>Permit Both</name><value>Permit_Both</value></option>
+ <option><name>Match Inbound</name><value>Match_Inbound</value></option>
+ <option><name>Match Outbound</name><value>Match_Outbound</value></option>
+ <option><name>Match Both</name><value>Match_Both</value></option>
+ <option><name>Alias Deny</name><value>Alias_Deny</value></option>
+ <option><name>Alias Permit</name><value>Alias_Permit</value></option>
+ <option><name>Alias Match</name><value>Alias_Match</value></option>
+ <option><name>Alias Native</name><value>Alias_Native</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Update Frequency</fielddescr>
+ <fieldname>cron</fieldname>
+ <description><![CDATA[Default:<strong>Never</strong><br />
+ Select how often List files will be downloaded]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Never</name><value>Never</value></option>
+ <option><name>Every Hour</name><value>01hour</value></option>
+ <option><name>Every 2 Hours</name><value>02hours</value></option>
+ <option><name>Every 3 Hours</name><value>03hours</value></option>
+ <option><name>Every 4 Hours</name><value>04hours</value></option>
+ <option><name>Every 6 Hours</name><value>06hours</value></option>
+ <option><name>Every 8 Hours</name><value>08hours</value></option>
+ <option><name>Every 12 Hours</name><value>12hours</value></option>
+ <option><name>Once a day</name><value>EveryDay</value></option>
+ <option><name>Weekly</name><value>Weekly</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Weekly (Day of Week)</fielddescr>
+ <fieldname>dow</fieldname>
+ <description><![CDATA[Default:<strong>1</strong><br />
+ Select the 'Weekly' ( Day of the Week ) to Update <br />
+ This is only required for the 'Weekly' Frequency Selection. The 24 Hour Download 'Time' will be used.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Monday</name><value>1</value></option>
+ <option><name>Tuesday</name><value>2</value></option>
+ <option><name>Wednesday</name><value>3</value></option>
+ <option><name>Thursday</name><value>4</value></option>
+ <option><name>Friday</name><value>5</value></option>
+ <option><name>Saturday</name><value>6</value></option>
+ <option><name>Sunday</name><value>7</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ <description><![CDATA[Default:<strong>Enable</strong><br />
+ Select - Logging to Status: System Logs: FIREWALL ( Log )<br />
+ This can be overriden by the 'Global Logging' Option in the General Tab.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Enable</name><value>enabled</value></option>
+ <option><name>Disable</name><value>disabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name>IPv4 Custom list</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>IPv4 Custom Address(es)</fielddescr>
+ <fieldname>custom</fieldname>
+ <description><![CDATA[Please limit the size of the Custom List as this is stored as 'Base64' format in the config.xml file.<br />
+ Follow the syntax below:<br /><br />
+ Network ranges: <strong>172.16.1.0-172.16.1.255</strong><br />
+ IP Address: <strong>172.16.1.10</strong><br />
+ CIDR: <strong>172.16.1.0/24</strong><br /><br />
+ You may use "<strong>#</strong>" after any IP/CIDR/Range to add comments. ie: x.x.x.x # Safe IP Address]]>
+ </description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>10</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Update Custom List</fielddescr>
+ <fieldname>custom_update</fieldname>
+ <description><![CDATA[Default:<strong>Disable</strong><br />
+ select - Enable Update if changes are made to this List. Cron will also resync this list at the next Scheduled Update.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Disable</name><value>disabled</value></option>
+ <option><name>Enable</name><value>enabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]></name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input($_POST, $input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global $pfb;
+ $pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfblockerng/pfblockerng_v6lists.xml b/config/pfblockerng/pfblockerng_v6lists.xml
new file mode 100644
index 00000000..15d788cf
--- /dev/null
+++ b/config/pfblockerng/pfblockerng_v6lists.xml
@@ -0,0 +1,421 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd">
+<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?>
+<packagegui>
+ <copyright>
+ <![CDATA[
+/* ========================================================================== */
+/*
+ pfBlockerNG_v6lists.xml
+
+ pfBlockerNG
+ Copyright (C) 2014 BBcan177@gmail.com
+ All rights reserved.
+
+ Based upon pfblocker for pfSense
+ Copyright (C) 2011 Marcello Coutinho
+
+ part of pfSense (http://www.pfSense.com)
+ Copyright (C) 2010 Scott Ullrich <sullrich@gmail.com>
+ All rights reserved.
+*/
+/* ========================================================================== */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+*/
+/* ========================================================================== */
+ ]]>
+ </copyright>
+ <description>Describe your package here</description>
+ <requirements>Describe your package requirements here</requirements>
+ <faq>Currently there are no FAQ items provided.</faq>
+ <name>pfblockernglistsv6</name>
+ <version>1.0</version>
+ <title>pfBlockerNG: IPv6 Alias/List Configuration</title>
+ <include_file>/usr/local/pkg/pfblockerng/pfblockerng.inc</include_file>
+ <menu>
+ <name>pfBlockerNG</name>
+ <tooltiptext></tooltiptext>
+ <section>Firewall</section>
+ <configfile>pfblockerng_v6lists.xml</configfile>
+ </menu>
+ <tabs>
+ <tab>
+ <text>General</text>
+ <url>/pkg_edit.php?xml=pfblockerng.xml&amp;id=0</url>
+ <tooltiptext></tooltiptext>
+ </tab>
+ <tab>
+ <text>Update</text>
+ <url>/pfblockerng/pfblockerng_update.php</url>
+ </tab>
+ <tab>
+ <text>Alerts</text>
+ <url>/pfblockerng/pfblockerng_alerts.php</url>
+ </tab>
+ <tab>
+ <text>Reputation</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_reputation.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv4</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v4lists.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>IPv6</text>
+ <url>/pkg.php?xml=/pfblockerng/pfblockerng_v6lists.xml&amp;id=0</url>
+ <active/>
+ </tab>
+ <tab>
+ <text>Top 20</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_top20.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Africa</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Africa.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Asia</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Asia.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Europe</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Europe.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>N.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_NorthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Oceania</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_Oceania.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>S.A.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_SouthAmerica.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>P.S.</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_ProxyandSatellite.xml&amp;id=0</url>
+ </tab>
+ <tab>
+ <text>Logs</text>
+ <url>/pfblockerng/pfblockerng_log.php</url>
+ </tab>
+ <tab>
+ <text>Sync</text>
+ <url>/pkg_edit.php?xml=/pfblockerng/pfblockerng_sync.xml&amp;id=0</url>
+ </tab>
+ </tabs>
+ <adddeleteeditpagefields>
+ <columnitem>
+ <fielddescr>Alias Name</fielddescr>
+ <fieldname>aliasname</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Alias Description</fielddescr>
+ <fieldname>description</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Action</fielddescr>
+ <fieldname>action</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Frequency</fielddescr>
+ <fieldname>cron</fieldname>
+ </columnitem>
+ <columnitem>
+ <fielddescr>Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ </columnitem>
+ </adddeleteeditpagefields>
+ <fields>
+ <field>
+ <name>IPv6 Network ranges / CIDR lists</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>LINKS</fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<a href="/firewall_aliases.php">Firewall Alias</a> &nbsp;&nbsp;&nbsp; <a href="/firewall_rules.php">Firewall Rules</a> &nbsp;&nbsp;&nbsp; <a href="diag_logs_filter.php">Firewall Logs</a>]]>
+ </description>
+ <type>info</type>
+ </field>
+ <field>
+ <fielddescr>Alias Name</fielddescr>
+ <fieldname>aliasname</fieldname>
+ <description><![CDATA[Enter lists Alias Names.<br />
+ Example: Badguys<br />
+ Do not include <strong>'pfBlocker' or 'pfB_'</strong> in the Alias Name, it's done by package.<br />
+ <strong>International, special or space characters will be ignored in firewall alias names.
+ </strong><br />]]>
+ </description>
+ <type>input</type>
+ <size>20</size>
+ </field>
+ <field>
+ <fielddescr>List Description</fielddescr>
+ <fieldname>description</fieldname>
+ <type>input</type>
+ <size>90</size>
+ </field>
+ <field>
+ <fieldname>InfoLists</fieldname>
+ <type>info</type>
+ <description><![CDATA[<strong><u>'Format'</u></strong> : Select the Format Type<br /><br />
+ <strong><u>'URL'</u></strong> : Add direct link to list:
+ Example: <a target=_new href='http://list.iblocklist.com/?list=bt_ads&fileformat=p2p&archiveformat=gz'>Ads</a>,
+ <a target=_new href='http://list.iblocklist.com/?list=bt_spyware&fileformat=p2p&archiveformat=gz'>Spyware</a>,
+ <a target=_new href='http://list.iblocklist.com/?list=bt_proxy&fileformat=p2p&archiveformat=gz'>Proxies</a><br /><br />
+ <strong><u>'pfSense Local File'</u></strong> Format :<br /><br />
+ &nbsp;&nbsp;http(s)://127.0.0.1/NAME_OF_FILE &nbsp;&nbsp;<strong>or</strong>&nbsp;&nbsp;
+ /usr/local/www/NAME_OF_FILE &nbsp;&nbsp; (Files can also be placed in the /var/db/pfblockerng folders)<br /><br />
+
+ <strong><u>'Header'</u></strong> : The <u>'Header' Field</u> must be <u>Unique</u>, it will
+ name the List File and it will be referenced in the pfBlockerNG Widget.
+ Use a Unique Prefix per 'Alias Category' followed by a unique descriptor for each List.<br /><br />]]>
+ </description>
+ </field>
+ <field>
+ <fielddescr><![CDATA[<strong>IPv6</strong> Lists]]></fielddescr>
+ <fieldname>none</fieldname>
+ <description><![CDATA[<br /><strong>'Format'</strong> - Choose the file format that URL will retrieve.<br />
+
+ <ul><li><strong>'txt'</strong> Plain txt Lists</li><br />
+ <li><strong>'gz'</strong> - IBlock GZ Lists in Range Format only.</li><br />
+ <li><strong>'gz_2'</strong> - Other GZ Lists in IP or CIDR only.</li><br />
+ <li><strong>'zip'</strong> - ZIP'd Lists</li><br />
+ <li><strong>'block'</strong>- IP x.x.x.0 Block type</li><br />
+ <li><strong>'html'</strong> - Web Links</li><br />
+ <li><strong>'xlsx'</strong> - Excel Lists</li><br />
+ <li><strong>'rsync'</strong> - RSync Lists</li><br />
+ <strong>'State'</strong> - Select the Run State for each list.<br />
+ <ul><li><strong>'ON/OFF'</strong> - Enabled / Disabled</li><br />
+ <li><strong>'HOLD'</strong> - Once a List has been Downloaded, list will remain Static.</li></ul>
+ <strong>'Note' -</strong> Downloaded or pfsense local file must have only one network per line and follows the syntax below:
+ <ul>Network ranges: <strong> TBC </strong><br />
+ IP Address: <strong> TBC </strong><br />
+ CIDR: <strong> TBC </strong></ul>]]>
+ </description>
+ <type>rowhelper</type>
+ <rowhelper>
+ <rowhelperfield>
+ <fielddescr>Format</fielddescr>
+ <fieldname>format</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>txt</name><value>txt</value></option>
+ <option><name>gz</name><value>gz</value></option>
+ <option><name>gz_2</name><value>gz_2</value></option>
+ <option><name>zip</name><value>zip</value></option>
+ <option><name>block</name><value>block</value></option>
+ <option><name>html</name><value>html</value></option>
+ <option><name>xlsx</name><value>xlsx</value></option>
+ <option><name>RSync</name><value>rsync</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>State</fielddescr>
+ <fieldname>state</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>ON</name><value>Enabled</value></option>
+ <option><name>OFF</name><value>Disabled</value></option>
+ <option><name>HOLD</name><value>Hold</value></option>
+ </options>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>URL or pfSense local file</fielddescr>
+ <fieldname>url</fieldname>
+ <type>input</type>
+ <size>50</size>
+ </rowhelperfield>
+ <rowhelperfield>
+ <fielddescr>Header</fielddescr>
+ <fieldname>header</fieldname>
+ <type>input</type>
+ <size>15</size>
+ </rowhelperfield>
+ </rowhelper>
+ </field>
+ <field>
+ <fielddescr>List Action</fielddescr>
+ <description><![CDATA[<br />Default : <strong>Disabled</strong><br /><br />
+ Select the <strong>Action</strong> for Firewall Rules on lists you have selected.<br /><br />
+ <strong><u>'Disabled' Rules:</u></strong> Disables selection and does nothing to selected Alias.<br /><br />
+
+ <strong><u>'Deny' Rules:</u></strong><br />
+ 'Deny' rules create high priority 'block' or 'reject' rules on the stated interfaces. They don't change the 'pass' rules on other
+ interfaces. Typical uses of 'Deny' rules are:<br />
+ <ul><li><strong>Deny Both</strong> - blocks all traffic in both directions, if the source or destination IP is in the block list</li>
+ <li><strong>Deny Inbound/Deny Outbound</strong> - blocks all traffic in one direction <u>unless</u> it is part of a session started by
+ traffic sent in the other direction. Does not affect traffic in the other direction.</li>
+ <li>One way 'Deny' rules can be used to selectively block <u>unsolicited</u> incoming (new session) packets in one direction, while
+ still allowing <u>deliberate</u> outgoing sessions to be created in the other direction.</li></ul>
+ <strong><u>'Permit' Rules:</u></strong><br />
+ 'Permit' rules create high priority 'pass' rules on the stated interfaces. They are the opposite of Deny rules, and don't create
+ any 'blocking' effect anywhere. They have priority over all Deny rules. Typical uses of 'Permit' rules are:<br />
+ <ul><li><strong>To ensure</strong> that traffic to/from the listed IPs will <u>always</u> be allowed in the stated directions. They
+ override <u>almost all other</u> Firewall rules on the stated interfaces.</li>
+ <li><strong>To act as a whitelist</strong> for Deny rule exceptions, for example if a large IP range or pre-created blocklist blocks a
+ few IPs that should be accessible.</li></ul>
+ <strong><u>'Match' Rules:</u></strong><br />
+ 'Match' or 'Log' only the traffic on the stated interfaces. This does not Block or Reject. It just Logs the traffic.
+ <ul><li><strong>Match Both</strong> - Matches all traffic in both directions, if the source or destination IP is in the list.</li>
+ <li><strong>Match Inbound/Match Outbound</strong> - Matches all traffic in one direction only.</li></ul>
+ <strong><u>'Alias' Rules:</u></strong><br />
+ <strong>'Alias'</strong> rules create an <a href="/firewall_aliases.php">alias</a> for the list (and do nothing else).
+ This enables a pfBlockerNG list to be used by name, in any firewall rule or pfSense function, as desired.
+ <ul><li><strong>Options &nbsp;&nbsp; - Alias Deny,&nbsp; Alias Permit,&nbsp; Alias Match,&nbsp; Alias Native</strong></li><br />
+ <li>'Alias Deny' can use De-Duplication and Reputation Processes if configured.</li><br />
+ <li>'Alias Permit' and 'Alias Match' will be saved in the Same folder as the other Permit/Match Auto-Rules</li><br />
+ <li>'Alias Native' lists are kept in their Native format without any modifications.</li></ul>
+ <strong>When using 'Alias' rules, change (pfB_) to ( pfb_ ) in the beginning of rule description and Use the 'Exact' spelling of
+ the Alias (no trailing Whitespace)&nbsp;</strong> Custom 'Alias' rules with 'pfB_ xxx' description will be removed by package if
+ using Auto Rule Creation.<br /><br /><strong>Tip</strong>: You can create the Auto Rules and remove "<u>auto rule</u>" from the Rule
+ Descriptions, then disable Auto Rules. This method will 'KEEP' these rules from being 'Deleted' which will allow editing for a Custom
+ Alias Configuration<br />]]>
+ </description>
+ <fieldname>action</fieldname>
+ <type>select</type>
+ <options>
+ <option><name>Disabled</name><value>Disabled</value></option>
+ <option><name>Deny Inbound</name><value>Deny_Inbound</value></option>
+ <option><name>Deny Outbound</name><value>Deny_Outbound</value></option>
+ <option><name>Deny Both</name><value>Deny_Both</value></option>
+ <option><name>Permit Inbound</name><value>Permit_Inbound</value></option>
+ <option><name>Permit Outbound</name><value>Permit_Outbound</value></option>
+ <option><name>Permit Both</name><value>Permit_Both</value></option>
+ <option><name>Match Inbound</name><value>Match_Inbound</value></option>
+ <option><name>Match Outbound</name><value>Match_Outbound</value></option>
+ <option><name>Match Both</name><value>Match_Both</value></option>
+ <option><name>Alias Deny</name><value>Alias_Deny</value></option>
+ <option><name>Alias Permit</name><value>Alias_Permit</value></option>
+ <option><name>Alias Match</name><value>Alias_Match</value></option>
+ <option><name>Alias Native</name><value>Alias_Native</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Update Frequency</fielddescr>
+ <fieldname>cron</fieldname>
+ <description><![CDATA[Default:<strong>Never</strong><br />
+ Select how often List files will be downloaded]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Never</name><value>Never</value></option>
+ <option><name>Every Hour</name><value>01hour</value></option>
+ <option><name>Every 2 Hours</name><value>02hours</value></option>
+ <option><name>Every 3 Hours</name><value>03hours</value></option>
+ <option><name>Every 4 Hours</name><value>04hours</value></option>
+ <option><name>Every 6 Hours</name><value>06hours</value></option>
+ <option><name>Every 8 Hours</name><value>08hours</value></option>
+ <option><name>Every 12 Hours</name><value>12hours</value></option>
+ <option><name>Once a day</name><value>EveryDay</value></option>
+ <option><name>Weekly</name><value>Weekly</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Weekly (Day of Week)</fielddescr>
+ <fieldname>dow</fieldname>
+ <description><![CDATA[Default:<strong>1</strong><br />
+ Select the 'Weekly' ( Day of the Week ) to Update <br />
+ This is only required for the 'Weekly' Frequency Selection. The 24 Hour Download 'Time' will be used.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Monday</name><value>1</value></option>
+ <option><name>Tuesday</name><value>2</value></option>
+ <option><name>Wednesday</name><value>3</value></option>
+ <option><name>Thursday</name><value>4</value></option>
+ <option><name>Friday</name><value>5</value></option>
+ <option><name>Saturday</name><value>6</value></option>
+ <option><name>Sunday</name><value>7</value></option>
+ </options>
+ </field>
+ <field>
+ <fielddescr>Enable Logging</fielddescr>
+ <fieldname>aliaslog</fieldname>
+ <description><![CDATA[Default:<strong>Enable</strong><br />
+ Select - Logging to Status: System Logs: FIREWALL ( Log )<br />
+ This can be overriden by the 'Global Logging' Option in the General Tab.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Enable</name><value>enabled</value></option>
+ <option><name>Disable</name><value>disabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name>IPv6 Custom list</name>
+ <type>listtopic</type>
+ </field>
+ <field>
+ <fielddescr>IPv6 Custom Address(es)</fielddescr>
+ <fieldname>custom</fieldname>
+ <description><![CDATA[Please limit the size of the Custom List as this is stored as 'Base64' format in the config.xml file.<br />
+ Follow the syntax below:<br /><br />
+ Network ranges: <strong> TBC </strong><br />
+ IP Address: <strong> TBC </strong><br />
+ CIDR: <strong> TBC </strong><br /><br />
+ You may use "<strong>#</strong>" after any IP/CIDR/Range to add comments. # Safe IP Address]]>
+ </description>
+ <type>textarea</type>
+ <cols>50</cols>
+ <rows>10</rows>
+ <encoding>base64</encoding>
+ </field>
+ <field>
+ <fielddescr>Update Custom List</fielddescr>
+ <fieldname>custom_update</fieldname>
+ <description><![CDATA[Default:<strong>Disable</strong><br />
+ Select - Enable Update if changes are made to this List. Cron will also resync this list at the next Scheduled Update.]]>
+ </description>
+ <type>select</type>
+ <options>
+ <option><name>Disable</name><value>disabled</value></option>
+ <option><name>Enable</name><value>enabled</value></option>
+ </options>
+ </field>
+ <field>
+ <name><![CDATA[<ul>Click to SAVE Settings and/or Rule Edits. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Changes are Applied via CRON or
+ 'Force Update'</ul>]]></name>
+ <type>listtopic</type>
+ </field>
+ </fields>
+ <custom_php_install_command>
+ pfblockerng_php_install_command();
+ </custom_php_install_command>
+ <custom_php_deinstall_command>
+ pfblockerng_php_deinstall_command();
+ </custom_php_deinstall_command>
+ <custom_php_validation_command>
+ pfblockerng_validate_input($_POST, $input_errors);
+ </custom_php_validation_command>
+ <custom_php_resync_config_command>
+ global $pfb;
+ $pfb['save'] = TRUE;
+ sync_package_pfblockerng();
+ </custom_php_resync_config_command>
+</packagegui> \ No newline at end of file
diff --git a/config/pfblockerng/widget-pfblockerng.inc b/config/pfblockerng/widget-pfblockerng.inc
new file mode 100644
index 00000000..1b3c7c2b
--- /dev/null
+++ b/config/pfblockerng/widget-pfblockerng.inc
@@ -0,0 +1,7 @@
+<?php
+
+//set variables for custom title and link
+$pfblockerng_title = "pfBlockerNG";
+$pfblockerng_title_link = "pfblockerng/pfblockerng_alerts.php";
+
+?> \ No newline at end of file