From b3ce3bde07750e25fabca14faf18c0e5f0eb74dc Mon Sep 17 00:00:00 2001 From: BBcan177 Date: Sun, 30 Nov 2014 18:49:04 -0500 Subject: pfBlockerNG Beta v0.99 pkg_config.10.xml edits and associated files for Package pfBlockerNG --- config/pfblockerng/pfblockerng.php | 1546 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1546 insertions(+) create mode 100644 config/pfblockerng/pfblockerng.php (limited to 'config/pfblockerng/pfblockerng.php') diff --git a/config/pfblockerng/pfblockerng.php b/config/pfblockerng/pfblockerng.php new file mode 100644 index 00000000..2c4af706 --- /dev/null +++ b/config/pfblockerng/pfblockerng.php @@ -0,0 +1,1546 @@ + 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 to 256M. This is required to process the MaxMind IP Database +ini_set('memory_limit', '256M'); + +function pfb_update_check($header_url, $list_url, $url_format) { + global $pfb; + + if ($url_format == "rsync" || $url_format == "html") { + print "[ {$header_url} ]\n"; + print " Skipping timestamp query\n"; + return 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; + } + + print "[ {$header_url} ]\n"; + $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}") { + return TRUE; + } else { + print " Remote file unchanged. Download Terminated\n"; + return FALSE; + } + } else { + return TRUE; + } +} + + +if ($argv[1] == 'update') { + sync_package_pfblockerng("cron"); +} + +if ($argv[1] == 'uc') { + pfblockerng_uc_countries(); + pfblockerng_get_countries(); +} + +if ($argv[1] == 'gc') { + pfblockerng_get_countries(); +} + +if ($argv[1] == 'cron') { + $hour = date('H'); + $dow = date('N'); + + # 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" && $list['action'] != "") { + foreach ($list['row'] as $row) { + if ($row['url'] != "" && $row['format'] != "hold" && $row['format'] != "skip") { + + 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']; + + # Check if List file exists, if not found run Update + if (!file_exists($pfbfolder . '/' . $header_url . '.txt')) { + print " Updates Found\n"; + $updates++; + continue; + } + + switch ($list_cron) { + case "01hour": + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + break; + case "02hours": + if (in_array($hour, $e_sch2)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "03hours": + if (in_array($hour, $e_sch3)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "04hours": + if (in_array($hour, $e_sch4)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "06hours": + if (in_array($hour, $e_sch6)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "08hours": + if (in_array($hour, $e_sch8)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "12hours": + if (in_array($hour, $e_sch12)) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "EveryDay": + if ($hour == $pfb['dailystart']) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + case "Weekly": + if ($hour == $pfb['dailystart'] && $dow == $header_dow) { + if (pfb_update_check($header_url, $list_url, $url_format)) { + print " Updates Found\n"; + unlink_if_exists($pfbfolder . '/' . $header_url . '.txt'); + $updates++; + } + } + break; + default: { + } + break; + } + } + } + } + } + } + } + + if ($updates > 0) { + 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 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)); + $csv = array_map('str_getcsv', @file($maxmind_cont)); + if (isset($csv)) { + foreach ($csv as $cc) { + $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($csv); + + // Collect Country ISO Data IPv4 and Sort to Continent Array + $log = "Processing ISO IPv4 Continent/Country Data \n"; + print $log; + pfb_logger("{$log}","3"); + + $csv2 = array_map('str_getcsv', @file($maxmind_cc4)); + if (isset($csv2)) { + foreach ($csv2 as $cc) { + $ip1_key = $cc[0]; + $ip2_key = $cc[1]; + $var1_key = $cc[2]; + $var2_key = $cc[3]; + $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]['ip4'] .= $a_cidr . ","; + $cont_array[$counter][$cc_key]['country'] = $country_key; + continue; + } + $counter++; + } + } + } + unset($csv2); + + // Build Continent IPv4 CIDR 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 IPv4: " . $cont_array[$counter]['continent'] . "\n"; + $pfb_file = $cont_array[$counter]['file4']; + $iso_key = array_keys($iso); + foreach ($iso_key as $key) { + if (preg_match("/[A-Z]{2}/", $key)) { + $header .= "# Country: " . $iso[$key]['country'] . "\n"; + $header .= "# ISO Code: " . $key . "\n"; + $header .= "# Total Networks: " . substr_count($iso[$key]['ip4'], ",") . "\n"; + $header .= str_replace(",", "\n", $iso[$key]['ip4']); + $iso[$key]['ip4'] = ""; + } + } + $counter++; + @file_put_contents($pfb_file, $header, LOCK_EX); + } + + + // Collect Country ISO Data IPv6 and Sort to Continent Array + $log = "Processing ISO IPv6 Continent/Country Data \n"; + print $log; + pfb_logger("{$log}","3"); + + $csv3 = array_map('str_getcsv', @file($maxmind_cc6)); + if (isset($csv3)) { + foreach ($csv3 as $cc) { + $ip1_key = $cc[0]; + $ip2_key = $cc[1]; + $var1_key = $cc[2]; + $var2_key = $cc[3]; + $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]['ip6'] .= $a_cidr . ","; + continue; + } + $counter++; + } + } + } + unset ($csv3); + + // Build Continent IPv6 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 IPv6: " . $cont_array[$counter]['continent'] . "\n"; + $pfb_file = $cont_array[$counter]['file6']; + $iso_key = array_keys($iso); + foreach ($iso_key as $key) { + if (preg_match("/[A-Z]{2}/", $key)) { + $header .= "# Country: " . $iso[$key]['country'] . "\n"; + $header .= "# ISO Code: " . $key . "\n"; + $header .= "# Total Networks: " . substr_count($iso[$key]['ip6'], ",") . "\n"; + $header .= str_replace(",", "\n", $iso[$key]['ip6']); + $iso[$key]['ip6'] = ""; + } + } + $counter++; + @file_put_contents($pfb_file, $header, LOCK_EX); + } + unset($cont_array); +} + + +function pfblockerng_get_countries() { + + global $g,$pfb; + pfb_global(); + + # These arrays are used to collect the '; + $roptions4[] = $Country . '-' . $ISOCode . ' ('. $total4 .') ' . ' ' . $ISOCode . ''; + + // Save ISO IPv4 Data + @file_put_contents($pfb['ccdir'] . '/' . $ISOCode . '_v4.txt',$pfb_v4,LOCK_EX); + + // Clear Variables and Restart Continent Collection process + $total4 = 0; + $pfb_v4 = ""; + $pfb['complete'] = FALSE; + } + 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)) { + $total4++; + if (!empty($line)) + $pfb_v4 .= $line . "\n"; + $pfb['complete'] = TRUE; + } + } + unset ($ips, $convert); + + // Sort IPv4 Countries Alphabetically and Build XML