0) { $return = @file_get_contents($file); print $return; } break; } } } return; } 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'); require_once('/usr/local/pkg/pfblockerng/pfblockerng_extra.inc'); // 'include functions' not yet merged into pfSense global $g, $pfb; // Clear IP/DNSBL counters via CRON if (isset($argv[1])) { if ($argv[1] == 'clearip') { pfBlockerNG_clearip(); pfBlockerNG_clearsqlite('clearip'); exit; } elseif ($argv[1] == 'cleardnsbl') { pfBlockerNG_clearsqlite('cleardnsbl'); exit; } } // Extras - MaxMind/TOP1M Download URLs/filenames/settings $pfb['extras'] = array(); // MaxMind GeoIP Databases $pfb['extras'][0] = array(); $pfb['extras'][0]['url'] = 'https://download.maxmind.com/geoip/databases/GeoLite2-Country/download?suffix=tar.gz'; $pfb['extras'][0]['file_dwn'] = 'GeoLite2-Country.tar.gz'; $pfb['extras'][0]['file'] = 'GeoLite2-Country.mmdb'; $pfb['extras'][0]['folder'] = "{$pfb['geoipshare']}"; $pfb['extras'][0]['type'] = 'geoip'; $pfb['extras'][1] = array(); $pfb['extras'][1]['url'] = 'https://download.maxmind.com/geoip/databases/GeoLite2-Country-CSV/download?suffix=zip'; $pfb['extras'][1]['file_dwn'] = 'GeoLite2-Country-CSV.zip'; $pfb['extras'][1]['file'] = ''; $pfb['extras'][1]['folder'] = "{$pfb['geoipshare']}"; $pfb['extras'][1]['type'] = 'geoip'; // TOP1M database $pfb['extras'][2] = array(); if ($pfb['dnsbl_alexatype'] == 'alexa') { $pfb['extras'][2]['url'] = 'https://s3.amazonaws.com/alexa-static/top-1m.csv.zip'; } elseif ($pfb['dnsbl_alexatype'] == 'tranco') { $pfb['extras'][2]['url'] = 'https://tranco-list.eu/top-1m.csv.zip'; } else { $pfb['extras'][2]['url'] = 'https://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip'; // Cisco } $pfb['extras'][2]['file_dwn'] = 'top-1m.csv.zip'; $pfb['extras'][2]['file'] = 'top-1m.csv'; $pfb['extras'][2]['folder'] = "{$pfb['dbdir']}"; $pfb['extras'][2]['type'] = 'top1m'; // IPinfo ASN databases $pfb['extras'][3] = array(); $pfb['extras'][3]['url'] = 'https://ipinfo.io/data/free/asn.mmdb?token='; $pfb['extras'][3]['file_dwn'] = 'asn.mmdb'; $pfb['extras'][3]['file'] = 'asn.mmdb'; $pfb['extras'][3]['folder'] = "{$pfb['geoipshare']}"; $pfb['extras'][3]['type'] = 'asn'; $pfb['extras'][4] = array(); $pfb['extras'][4]['url'] = 'https://ipinfo.io/data/free/asn.csv.gz?token='; $pfb['extras'][4]['file_dwn'] = 'asn.csv.gz'; $pfb['extras'][4]['file'] = 'asn.csv'; $pfb['extras'][4]['folder'] = "{$pfb['geoipshare']}"; $pfb['extras'][4]['type'] = 'asn'; // Next Available Extras Key value for Blacklist Category Downloads $next_key = $next_key_start = 5; if ($argv[1] == 'bl' || $argv[1] == 'bls') { if (empty(pfb_filter($argv[2], PFB_FILTER_CSV, 'php'))) { $argv[2] = ''; } if (!empty($argv[2]) && $pfb['blconfig'] && !empty($pfb['blconfig']['blacklist_selected']) && isset($pfb['blconfig']['item'])) { $selected = array_flip(explode(',', $argv[2])) ?: array(); foreach ($pfb['blconfig']['item'] as $item) { // Temporarily Discontinue Shallalist if ($item['title'] == 'Shallalist') { pfb_logger("\nTerminating Shallalist as its now discontinued!\n", 2); continue; } if (isset($selected[$item['xml']])) { $pfb['extras'][$next_key] = array(); $pfb['extras'][$next_key]['url'] = $item['feed']; $pfb['extras'][$next_key]['name'] = $item['title']; $pfb['extras'][$next_key]['file_dwn'] = pathinfo($item['feed'], PATHINFO_BASENAME); $pfb['extras'][$next_key]['file'] = pathinfo($item['feed'], PATHINFO_BASENAME); $pfb['extras'][$next_key]['folder'] = "{$pfb['dbdir']}"; $pfb['extras'][$next_key]['type'] = 'blacklist'; if (isset($item['username']) && isset($item['password'])) { $pfb['extras'][$next_key]['username'] = $item['username']; $pfb['extras'][$next_key]['password'] = $item['password']; } // Patch UT1 filename if ($item['feed'] == 'ftp://ftp.ut-capitole.fr/pub/reseau/cache/squidguard_contrib/blacklists.tar.gz') { $pfb['extras'][$next_key]['file_dwn'] = $pfb['extras'][$next_key]['file'] = 'ut1.tar.gz'; } $next_key++; } } } } // Call include file and collect updated Global settings if (in_array($argv[1], array('update', 'updateip', 'updatednsbl', 'dc', 'dcc', 'bu', 'uc', 'gc', 'al', 'asn', 'asn_shell', 'bl', 'bls', 'cron', 'ugc'))) { pfb_global(); $pfb['extras_update'] = FALSE; // Flag when Extras (MaxMind/TOP1M) are updateded via cron job // Script Arguments switch($argv[1]) { case 'cron': // Sync 'cron' logger(LOG_NOTICE, localize_text('Starting cron process.'), LOG_PREFIX_PKG_PFBLOCKERNG); pfblockerng_sync_cron(); break; case 'updateip': // Sync 'Force Reload IP only' case 'updatednsbl': // Sync 'Force Reload DNSBL only' sync_package_pfblockerng($argv[1]); break; case 'update': // Sync 'Force update' sync_package_pfblockerng('cron'); break; case 'dc': // Update Extras - MaxMind/TOP1M/ASN database files case 'dcc': // 'dcc' called via Cron job if ($argv[1] == 'dcc') { $logtype = 3; $pfb['extras_update'] = TRUE; // Remove MaxMind updates if Key or Account not defined if (empty($pfb['maxmind_key']) || empty($pfb['maxmind_account'])) { unset($pfb['extras'][0], $pfb['extras'][1]); } // Skip TOP1M update, if disabled if ($pfb['dnsbl_alexa'] != 'on') { unset($pfb['extras'][2]); // Remove TOP1M } // Skip ASN update, if disabled or Token not defined if (empty($pfb['asn_token'])) { unset($pfb['extras'][3], $pfb['extras'][4]); } } else { $logtype = 4; unset($pfb['extras'][2], $pfb['extras'][3], $pfb['extras'][4]); // Remove TOP1M and ASN } // If 'IP Tab' skip MaxMind download setting if checked, only download binary updates for Reputation/Alerts page. if (!empty($pfb['cc']) && isset($pfb['extras'][1])) { unset($pfb['extras'][1]); // Remove MaxMind GeoIP CSV } // Download Database updates if (pfblockerng_download_extras(600, $logtype)) { // Proceed with conversion of MaxMind files on download success if (empty($pfb['cc']) || !empty($pfb['maxmind_key']) || !empty($pfb['maxmind_account'])) { pfblockerng_uc_countries(); pfblockerng_get_countries(); } } break; case 'bu': // Update MaxMind binary database files only. // Remove MaxMind updates if Key or Account not defined if (empty($pfb['maxmind_key']) || empty($pfb['maxmind_account'])) { pfb_logger("\nTerminating MaxMind download due to invalid Account or Key", 2); return; } unset($pfb['extras'][1], $pfb['extras'][2], $pfb['extras'][3], $pfb['extras'][4]); // Remove MaxMind GeoIP CSV, TOP1M and ASN pfblockerng_download_extras(600, 3); break; case 'al': // Update TOP1M database only. unset($pfb['extras'][0], $pfb['extras'][1], $pfb['extras'][3], $pfb['extras'][4]); // Remove MaxMind GeoIP mmdb, CSV and ASN pfblockerng_download_extras(600, 3); break; case 'asn': // Update ASN database only case 'asn_shell': // Skip ASN update, if disabled or Token not defined if (empty($pfb['asn_token'])) { $asn_log = "\n ASN Token not defined. Terminating Download. "; if ($argv[1] == 'asn') { pfb_logger($asn_log, 2); } else { pfb_logger($asn_log, 1); } return; } unset($pfb['extras'][0], $pfb['extras'][1], $pfb['extras'][2]); pfblockerng_download_extras(600, 3); break; case 'bl': // Update DNSBL Category database(s) only. case 'bls': // Exit if no Blacklist Extra found if (empty($pfb['extras'][$next_key_start])) { break; } unset($pfb['extras'][0], $pfb['extras'][1], $pfb['extras'][2], $pfb['extras'][3], $pfb['extras'][4]); // Remove MaxMind GeoIP mmdb, CSV, TOP1M and ASN // 'bls' called via 'Force Update|Reload' if ($argv[1] == 'bls') { $pfb_return = pfblockerng_download_extras(600, 'blacklist'); return $pfb_return; } else { pfblockerng_download_extras(600, 3); } break; case 'uc': // Update MaxMind ISO files from local database files. pfblockerng_uc_countries(); break; case 'gc': // Update Continent XML files. pfblockerng_get_countries(); break; case 'ugc': pfblockerng_uc_countries(); pfblockerng_get_countries(); if (!empty($argv[2]) && !empty($argv[3])) { $argv2 = htmlspecialchars($argv[2]); $argv3 = htmlspecialchars($argv[3]); if (in_array($argv2, array('en', 'fr', 'de', 'pt-BR', 'ja', 'zh-CN', 'es')) && in_array($argv3, array('en', 'fr', 'de', 'pt-BR', 'ja', 'zh-CN', 'es'))) { file_notice('pfBlockerNG', "The MaxMind GeoIP Locale has been changed from [ {$argv2} ]" . " to [ {$argv3} ]", gettext('MaxMind Locale Changed'), '', 0); } } break; default: return; } } // Determine if source list file has an updated timestamp function pfb_update_check($header, $list_url, $pfbfolder, $pfborig, $pflex, $format, $vtype, $srcint=FALSE) { global $pfb; $log = "[ {$header} ] [ NOW ]\n"; pfb_logger("{$log}", 1); $pfb['cron_update'] = FALSE; if (empty(pfb_filter($header, PFB_FILTER_WORD, 'php'))) { pfb_logger("\n Failed to update due to Invalid header name!", 2); return; } // Re-evaluate URL if ($format == 'whois' || $format == 'asn') { if (strpos($list_url, ' ') !== FALSE) { $list_url = strstr($list_url, ' ', TRUE); } $pfb_filter_type = PFB_FILTER_ALNUM; $pfb_filter_text = 'ASN'; if ($format == 'whois') { $pfb_filter_type = PFB_FILTER_DOMAIN; $pfb_filter_text = 'WHOIS'; } if (empty(pfb_filter($list_url, $pfb_filter_type, 'php'))) { pfb_logger("\n Invalid {$pfb_filter_text}. Terminating Download! [ {$list_url} ]\n", 1); return; } $log = "\t\t\t\t\t\t\tUpdate found\n"; pfb_logger("{$log}", 1); $pfb['update_cron'] = TRUE; touch("{$pfbfolder}/{$header}.update"); return; } elseif ($format == 'geoip') { if (strpos($list_url, ' ') !== FALSE) { $list_url = strstr($list_url, ' ', TRUE); } if (!empty(pfb_filter($list_url, PFB_FILTER_WORD, 'php'))) { $list_url = "/usr/local/share/GeoIP/cc/{$list_url}{$vtype}.txt"; } else { pfb_logger("\n Invalid GEOIP. Terminating Download! [ {$list_url} ]\n", 1); return; } } elseif (!pfb_filter($list_url, PFB_FILTER_URL, 'php')) { pfb_logger("\n Invalid URL. Terminating Download! [ {$list_url} ]\n", 1); return; } $list_url_esc = escapeshellarg("{$list_url}"); $list_download = trim("{$list_url_esc}", "'"); // Call function to get all previous download fails pfb_failures(); if ($pfb['skipfeed'] != 0) { // Determine if previous download fails have exceeded threshold. if ($pfb['failed'][$header] >= $pfb['skipfeed']) { $log = " Max daily download failure attempts exceeded. Clear widget 'failed downloads' to reset.\n\n"; pfb_logger("{$log}", 1); unlink_if_exists("{$pfbfolder}/{$header}.fail"); return; } } // Attempt download, when a previous 'fail' file marker is found. if (file_exists("{$pfbfolder}/{$header}.fail")) { $log = "\t\t\tPrevious download failed.\tRe-attempt download\n"; pfb_logger("{$log}", 1); $pfb['update_cron'] = TRUE; touch("{$pfbfolder}/{$header}.update"); return; } // Check if List file doesn't exist or Format is 'whois'. if (!file_exists("{$pfbfolder}/{$header}.txt") || $format == 'whois') { $log = "\t\t\t\t\t\t\tUpdate found\n"; pfb_logger("{$log}", 1); $pfb['update_cron'] = TRUE; return; } $local_file = "{$pfborig}/{$header}.orig"; // Compare previously downloaded file timestamp with remote timestamp if (file_exists($local_file)) { if ($format == 'rsync') { $log = "\t\t\t\t( rsync )\t\tUpdate found\n"; pfb_logger("{$log}", 1); $pfb['update_cron'] = TRUE; touch("{$pfbfolder}/{$header}.update"); return; } // Determine if URL is a pfSense localfile $localfile = FALSE; if (pfb_filter($list_download, PFB_FILTER_URL, 'php', '', TRUE)) { $localfile = TRUE; } if ($localfile) { clearstatcache(); $remote_tds = gmdate('D, j M Y H:i:s T', @filemtime("{$list_download}")); } else { // Download URL headers and compare previously downloaded file with remote timestamp if (($ch = curl_init("{$list_download}"))) { curl_setopt_array($ch, $pfb['curl_defaults']); // Load curl default settings curl_setopt($ch, CURLOPT_NOBODY, true); // Exclude the body from the output curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); // Allow downgrade of cURL settings if user configured if ($pflex == 'Flex') { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1.2, TLSv1, SSLv3'); } // If source interface is specified (not 'default') set CURLOPT_INTERFACE if ($srcint) { curl_setopt($ch, CURLOPT_INTERFACE, $srcint); pfb_logger("\nList: {$header} will be downloaded via interface: {$srcint}\n", 1); } // Try up to 3 times to download the file before giving up for ($retries = 1; $retries <= 3; $retries++) { $remote_stamp_raw = -1; if (curl_exec($ch)) { $raw_filetime = curl_getinfo($ch, CURLINFO_FILETIME); if ($raw_filetime == -1) { $remote_stamp_raw = -1; } elseif(!empty(pfb_filter($raw_filetime, PFB_FILTER_NUM, 'php'))) { $remote_stamp_raw = $raw_filetime; } break; // Break on success } sleep(3); } if ($remote_stamp_raw != -1) { $remote_tds = gmdate('D, j M Y H:i:s T', $remote_stamp_raw); } } if ($ch) { curl_close($ch); } } // If remote timestamp not found, Attempt md5 comparison if ($remote_stamp_raw == -1) { // Download Feed to compare md5's. If update required, downloaded md5 file will be used instead of downloading twice if (pfb_download("{$list_download}", "{$pfborig}/{$header}.md5", $pflex, $header, '', 1, '', 300, 'md5', '', '', $srcint)) { // Collect md5 checksums $remote_md5 = @md5_file("{$pfborig}/{$header}.md5.raw"); $local_md5 = @md5_file($local_file); if ($remote_md5 != $local_md5) { $log = "\n\t\t\t\t( md5 changed )\t\tUpdate found\n"; pfb_logger("{$log}", 1); $pfb['update_cron'] = TRUE; touch("{$pfbfolder}/{$header}.update"); return; } else { $log = "\n\t\t\t\t( md5 unchanged )\tUpdate not required\n"; pfb_logger("{$log}", 1); unlink_if_exists("{$pfborig}/{$header}.md5.raw"); return; } } else { $log = "\n\tFailed to download Feed for md5 comparison!\tUpdate skipped\n"; unlink_if_exists("{$pfborig}/{$header}.md5.raw"); touch("{$pfbfolder}/{$header}.fail"); pfb_logger("{$log}", 1); return; } } else { $log = " Remote timestamp: {$remote_tds}\n"; pfb_logger("{$log}", 1); clearstatcache(); $local_tds = gmdate('D, j M Y H:i:s T', @filemtime($local_file)); $log = " Local timestamp: {$local_tds}\t"; pfb_logger("{$log}", 1); if ("{$remote_tds}" != "{$local_tds}") { $pfb['cron_update'] = TRUE; } else { $log = "Update not required\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 = "Update found\n"; pfb_logger("{$log}", 1); touch("{$pfbfolder}/{$header}.update"); } return; } // Download Extras - MaxMind/TOP1M/Category feeds via cURL function pfblockerng_download_extras($timeout=600, $type='') { global $pfb; pfb_global(); $pfb_return = ''; $pfb_error = FALSE; $logtype = 3; if ($type == 4) { $logtype = 4; } pfb_logger("\nDownload Process Starting [ NOW ]\n", $logtype); foreach ($pfb['extras'] as $feed) { if (empty($feed)) { continue; } // Add Token/Credentials if ($feed['type'] == 'geoip') { $feed['username'] = $pfb['maxmind_account']; $feed['password'] = $pfb['maxmind_key']; } elseif ($feed['type'] == 'asn') { $feed['url'] = "{$feed['url']}{$pfb['asn_token']}"; } else { $feed['username'] = $feed['username'] ?: ''; $feed['password'] = $feed['password'] ?: ''; } $file_dwn = "{$feed['folder']}/{$feed['file_dwn']}"; if (!pfb_download($feed['url'], $file_dwn, FALSE, "{$feed['folder']}/{$feed['file']}", '', $logtype, '', $timeout, $feed['type'], $feed['username'], $feed['password'])) { $log = "\nFailed to Download {$feed['file']}\n"; pfb_logger("{$log}", $logtype); // On Extras update (MaxMind and TOP1M), if error found when downloading MaxMind Country database // return error to update process if ($feed['file_dwn'] == 'GeoLite2-Country-CSV.zip') { $pfb_error = TRUE; } if ($type == 'blacklist') { $pfb_return .= "\t{$feed['name']} ... Failed\n"; } } else { if ($type == 'blacklist') { $pfb_return .= "\t{$feed['name']} ... Completed\n"; } } } pfb_logger("Download Process Ended [ NOW ]\n\n", $logtype); if ($type == 'blacklist') { print "{$pfb_return}"; } else { if ($pfb_error) { return FALSE; } else { return TRUE; } } } // Function to update Lists/Feeds as per Cron function pfblockerng_sync_cron() { global $pfb, $pfbarr; $hour = date('G'); $dow = date('N'); $pfb['update_cron'] = FALSE; $log = " CRON PROCESS START [ " . pfb_pkg_ver() . " ] [ NOW ]\n"; pfb_logger("{$log}", 1); $list_type = array('pfblockernglistsv4' => '_v4', 'pfblockernglistsv6' => '_v6', 'pfblockerngdnsbl' => '_v4'); foreach ($list_type as $ltype => $vtype) { foreach (config_get_path("installedpackages/{$ltype}/config", []) as $list) { if (isset($list['row']) && $list['action'] != 'Disabled' && $list['cron'] != 'Never') { foreach ($list['row'] as $row) { if (!empty($row['url']) && $row['state'] != 'Disabled') { if ($ltype == 'pfblockerngdnsbl') { $header = "{$row['header']}"; } else { $header = "{$row['header']}{$vtype}"; } if (empty(pfb_filter($header, PFB_FILTER_WORD, 'php'))) { pfb_logger("\n Invalid Header:{$row['header']} *skipping*", 1); continue; } // Determine cURL source interface (sets CURLOPT_INTERFACE; applies to entire alias) $srcint = $list['srcint'] ?: FALSE; // Determine folder location for alias (return array $pfbarr) pfb_determine_list_detail($list['action'], '', '', ''); $pfbfolder = $pfbarr['folder']; $pfborig = $pfbarr['orig']; // Bypass update if state is defined as 'Hold' and list file exists if ($row['state'] == 'Hold' && file_exists("{$pfbfolder}/{$header}.txt")) { continue; } // Attempt download, when a previous 'fail' file marker is found. if (file_exists("{$pfbfolder}/{$header}.fail")) { pfb_update_check($header, $row['url'], $pfbfolder, $pfborig, $pflex, $row['format'], $vtype, $srcint); continue; } // Allow cURL SSL downgrade if user configured. $pflex = FALSE; if ($row['state'] == 'Flex') { $pflex = TRUE; } switch ($list['cron']) { case 'EveryDay': if ($hour == $pfb['24hour']) { pfb_update_check($header, $row['url'], $pfbfolder, $pfborig, $pflex, $row['format'], $vtype, $srcint); } break; case 'Weekly': if ($hour == $pfb['24hour'] && $dow == $list['dow']) { pfb_update_check($header, $row['url'], $pfbfolder, $pfborig, $pflex, $row['format'], $vtype, $srcint); } break; default: $pfb_sch = pfb_cron_base_hour($list['cron']); if (in_array($hour, $pfb_sch)) { pfb_update_check($header, $row['url'], $pfbfolder, $pfborig, $pflex, $row['format'], $vtype, $srcint); } break; } } } } } } // If no lists require updates, check if Continents are configured and update accordingly. if (!$pfb['update_cron']) { foreach ($pfb['continents'] as $continent => $pfb_alias) { $continent_config = config_get_path('installedpackages/pfblockerng' . strtolower(str_replace(' ', '', $continent)) . '/config/0'); if ($continent_config !== null) { if ($continent_config['action'] != 'Disabled') { $pfb['update_cron'] = TRUE; break; } } } } if ($pfb['update_cron']) { sync_package_pfblockerng('cron'); $pfb['update_cron'] = FALSE; } else { sync_package_pfblockerng('noupdates'); $log = "\n No Updates required.\n CRON PROCESS ENDED\n UPDATE PROCESS ENDED\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; // Create folders if not exist $folder_array = array ("{$pfb['dbdir']}", "{$pfb['logdir']}", "{$pfb['ccdir']}"); foreach ($folder_array as $folder) { safe_mkdir ("{$folder}", 0755); } $log = "Country code update Start [ NOW ]\n"; pfb_logger("{$log}", 4); $maxmind_cont = "{$pfb['geoipshare']}/GeoLite2-Country-Locations-{$pfb['maxmind_locale']}.csv"; if (!file_exists($maxmind_cont)) { $log = " [ MAXMIND UPDATE FAIL, Language File Missing, using previous Country code database ] [ NOW ]\n"; pfb_logger("{$log}", 4); return; } // Save Date/Time stamp to MaxMind version file $local_tds = @gmdate('D, j M Y H:i:s T', @filemtime($maxmind_cont)); $maxmind_ver = "MaxMind GeoLite2 Date/Time Stamp\n"; $maxmind_ver .= "Last-Modified: {$local_tds}\n"; @file_put_contents("{$pfb['logdir']}/maxmind_ver", $maxmind_ver, LOCK_EX); // Remove any previous tmp working files rmdir_recursive("{$pfb['ccdir_tmp']}"); safe_mkdir("{$pfb['ccdir_tmp']}"); $pfb_geoip = array(); $pfb_geoip['country'] = array(); $top_20 = array_flip( array('CN', 'RU', 'JP', 'UA', 'GB', 'DE', 'BR', 'FR', 'IN', 'TR', 'IT', 'KR', 'PL', 'ES', 'VN', 'AR', 'CO', 'TW', 'MX', 'CL') ); // Read GeoLite2 database and create array by geoname_ids if (($handle = @fopen("{$maxmind_cont}", 'r')) !== FALSE) { while (($cc = @fgetcsv($handle)) !== FALSE) { if ($cc[0] == 'geoname_id') { continue; } /* Sample MaxMind lines: geoname_id,locale_code,continent_code,continent_name,country_iso_code,country_name 49518,en,AF,Africa,RW,Rwanda */ if (!empty($cc[0]) && !empty($cc[1]) && !empty($cc[2]) && !empty($cc[3]) && !empty($cc[4]) && !empty($cc[5])) { $pfb_geoip['country'][$cc[0]] = array('id' => $cc[0], 'continent' => $cc[3], 'name' => $cc[5], 'iso' => array("{$cc[4]}")); // Collect English Continent name for filenames only if ($cc[1] != 'en') { $geoip_en = escapeshellarg(str_replace("Locations-{$pfb['maxmind_locale']}", 'Locations-en', $maxmind_cont)); $cc_2 = escapeshellarg(",en,{$cc[2]}"); $continent_en = exec("{$pfb['grep']} -m1 {$cc_2} {$geoip_en} | {$pfb['cut']} -d',' -f4"); } else { $continent_en = "{$cc[3]}"; } $continent_en = str_replace(array(' ', '"'), array('_', ''), $continent_en); $pfb_geoip['country'][$cc[0]]['continent_en'] = "{$continent_en}"; // Collect data for TOP 20 tab if (isset($top_20[$cc[4]])) { $top20 = 'A' . str_pad($top_20[$cc[4]], 5, '0', STR_PAD_LEFT); $pfb_geoip['country'][$top20] = array('name' => $cc[5], 'iso' => $cc[4], 'id' => $cc[0]); } } } if ($cc) { unset($cc); } if ($handle) { @fclose($handle); } } // Add 'Proxy and Satellite' geoname_ids $pfb_geoip['country']['proxy'] = array('continent' => 'Proxy and Satellite', 'name' => 'Proxy', 'iso' => array('A1'), 'continent_en' => 'Proxy_and_Satellite'); $pfb_geoip['country']['satellite'] = array('continent' => 'Proxy and Satellite', 'name' => 'Satellite', 'iso' => array('A2'), 'continent_en' => 'Proxy_and_Satellite'); // Add 'Asia/Europe' undefined geoname_ids $pfb_geoip['country']['6255147'] = array('continent' => 'Asia', 'name' => 'AA ASIA UNDEFINED', 'iso' => array('6255147'), 'continent_en' => 'Asia'); $pfb_geoip['country']['6255148'] = array('continent' => 'Europe', 'name' => 'AA EUROPE UNDEFINED', 'iso' => array('6255148'), 'continent_en' => 'Europe'); // List of all known Countries via Geonames.org (Used to validate MaxMind Country listings) $pfb_geoip_all = array( '3041565' => array ( 'iso' => 'AD', 'name' => 'Andorra', 'continent' => 'Europe' ), '290557' => array ( 'iso' => 'AE', 'name' => 'United Arab Emirates', 'continent' => 'Asia' ), '1149361' => array ( 'iso' => 'AF', 'name' => 'Afghanistan', 'continent' => 'Asia' ), '3576396' => array ( 'iso' => 'AG', 'name' => 'Antigua and Barbuda', 'continent' => 'North America' ), '3573511' => array ( 'iso' => 'AI', 'name' => 'Anguilla', 'continent' => 'North America' ), '783754' => array ( 'iso' => 'AL', 'name' => 'Albania', 'continent' => 'Europe' ), '174982' => array ( 'iso' => 'AM', 'name' => 'Armenia', 'continent' => 'Asia' ), '3351879' => array ( 'iso' => 'AO', 'name' => 'Angola', 'continent' => 'Africa' ), '6697173' => array ( 'iso' => 'AQ', 'name' => 'Antarctica', 'continent' => 'Antarctica' ), '3865483' => array ( 'iso' => 'AR', 'name' => 'Argentina', 'continent' => 'South America' ), '5880801' => array ( 'iso' => 'AS', 'name' => 'American Samoa', 'continent' => 'Oceania' ), '2782113' => array ( 'iso' => 'AT', 'name' => 'Austria', 'continent' => 'Europe' ), '2077456' => array ( 'iso' => 'AU', 'name' => 'Australia', 'continent' => 'Oceania' ), '3577279' => array ( 'iso' => 'AW', 'name' => 'Aruba', 'continent' => 'North America' ), '661882' => array ( 'iso' => 'AX', 'name' => 'Aland Islands', 'continent' => 'Europe' ), '587116' => array ( 'iso' => 'AZ', 'name' => 'Azerbaijan', 'continent' => 'Asia' ), '3277605' => array ( 'iso' => 'BA', 'name' => 'Bosnia and Herzegovina', 'continent' => 'Europe' ), '3374084' => array ( 'iso' => 'BB', 'name' => 'Barbados', 'continent' => 'North America' ), '1210997' => array ( 'iso' => 'BD', 'name' => 'Bangladesh', 'continent' => 'Asia' ), '2802361' => array ( 'iso' => 'BE', 'name' => 'Belgium', 'continent' => 'Europe' ), '2361809' => array ( 'iso' => 'BF', 'name' => 'Burkina Faso', 'continent' => 'Africa' ), '732800' => array ( 'iso' => 'BG', 'name' => 'Bulgaria', 'continent' => 'Europe' ), '290291' => array ( 'iso' => 'BH', 'name' => 'Bahrain', 'continent' => 'Asia' ), '433561' => array ( 'iso' => 'BI', 'name' => 'Burundi', 'continent' => 'Africa' ), '2395170' => array ( 'iso' => 'BJ', 'name' => 'Benin', 'continent' => 'Africa' ), '3578476' => array ( 'iso' => 'BL', 'name' => 'Saint Barthelemy', 'continent' => 'North America' ), '3573345' => array ( 'iso' => 'BM', 'name' => 'Bermuda', 'continent' => 'North America' ), '1820814' => array ( 'iso' => 'BN', 'name' => 'Brunei', 'continent' => 'Asia' ), '3923057' => array ( 'iso' => 'BO', 'name' => 'Bolivia', 'continent' => 'South America' ), '7626844' => array ( 'iso' => 'BQ', 'name' => 'Bonaire, Saint Eustatius and Saba ', 'continent' => 'North America' ), '3469034' => array ( 'iso' => 'BR', 'name' => 'Brazil', 'continent' => 'South America' ), '3572887' => array ( 'iso' => 'BS', 'name' => 'Bahamas', 'continent' => 'North America' ), '1252634' => array ( 'iso' => 'BT', 'name' => 'Bhutan', 'continent' => 'Asia' ), '3371123' => array ( 'iso' => 'BV', 'name' => 'Bouvet Island', 'continent' => 'Antarctica' ), '933860' => array ( 'iso' => 'BW', 'name' => 'Botswana', 'continent' => 'Africa' ), '630336' => array ( 'iso' => 'BY', 'name' => 'Belarus', 'continent' => 'Europe' ), '3582678' => array ( 'iso' => 'BZ', 'name' => 'Belize', 'continent' => 'North America' ), '6251999' => array ( 'iso' => 'CA', 'name' => 'Canada', 'continent' => 'North America' ), '1547376' => array ( 'iso' => 'CC', 'name' => 'Cocos Islands', 'continent' => 'Asia' ), '203312' => array ( 'iso' => 'CD', 'name' => 'Democratic Republic of the Congo', 'continent' => 'Africa' ), '239880' => array ( 'iso' => 'CF', 'name' => 'Central African Republic', 'continent' => 'Africa' ), '2260494' => array ( 'iso' => 'CG', 'name' => 'Republic of the Congo', 'continent' => 'Africa' ), '2658434' => array ( 'iso' => 'CH', 'name' => 'Switzerland', 'continent' => 'Europe' ), '2287781' => array ( 'iso' => 'CI', 'name' => 'Ivory Coast', 'continent' => 'Africa' ), '1899402' => array ( 'iso' => 'CK', 'name' => 'Cook Islands', 'continent' => 'Oceania' ), '3895114' => array ( 'iso' => 'CL', 'name' => 'Chile', 'continent' => 'South America' ), '2233387' => array ( 'iso' => 'CM', 'name' => 'Cameroon', 'continent' => 'Africa' ), '1814991' => array ( 'iso' => 'CN', 'name' => 'China', 'continent' => 'Asia' ), '3686110' => array ( 'iso' => 'CO', 'name' => 'Colombia', 'continent' => 'South America' ), '3624060' => array ( 'iso' => 'CR', 'name' => 'Costa Rica', 'continent' => 'North America' ), '3562981' => array ( 'iso' => 'CU', 'name' => 'Cuba', 'continent' => 'North America' ), '3374766' => array ( 'iso' => 'CV', 'name' => 'Cape Verde', 'continent' => 'Africa' ), '7626836' => array ( 'iso' => 'CW', 'name' => 'Curacao', 'continent' => 'North America' ), '2078138' => array ( 'iso' => 'CX', 'name' => 'Christmas Island', 'continent' => 'Asia' ), '146669' => array ( 'iso' => 'CY', 'name' => 'Cyprus', 'continent' => 'Europe' ), '3077311' => array ( 'iso' => 'CZ', 'name' => 'Czechia', 'continent' => 'Europe' ), '2921044' => array ( 'iso' => 'DE', 'name' => 'Germany', 'continent' => 'Europe' ), '223816' => array ( 'iso' => 'DJ', 'name' => 'Djibouti', 'continent' => 'Africa' ), '2623032' => array ( 'iso' => 'DK', 'name' => 'Denmark', 'continent' => 'Europe' ), '3575830' => array ( 'iso' => 'DM', 'name' => 'Dominica', 'continent' => 'North America' ), '3508796' => array ( 'iso' => 'DO', 'name' => 'Dominican Republic', 'continent' => 'North America' ), '2589581' => array ( 'iso' => 'DZ', 'name' => 'Algeria', 'continent' => 'Africa' ), '3658394' => array ( 'iso' => 'EC', 'name' => 'Ecuador', 'continent' => 'South America' ), '453733' => array ( 'iso' => 'EE', 'name' => 'Estonia', 'continent' => 'Europe' ), '357994' => array ( 'iso' => 'EG', 'name' => 'Egypt', 'continent' => 'Africa' ), '2461445' => array ( 'iso' => 'EH', 'name' => 'Western Sahara', 'continent' => 'Africa' ), '338010' => array ( 'iso' => 'ER', 'name' => 'Eritrea', 'continent' => 'Africa' ), '2510769' => array ( 'iso' => 'ES', 'name' => 'Spain', 'continent' => 'Europe' ), '337996' => array ( 'iso' => 'ET', 'name' => 'Ethiopia', 'continent' => 'Africa' ), '660013' => array ( 'iso' => 'FI', 'name' => 'Finland', 'continent' => 'Europe' ), '2205218' => array ( 'iso' => 'FJ', 'name' => 'Fiji', 'continent' => 'Oceania' ), '3474414' => array ( 'iso' => 'FK', 'name' => 'Falkland Islands', 'continent' => 'South America' ), '2081918' => array ( 'iso' => 'FM', 'name' => 'Micronesia', 'continent' => 'Oceania' ), '2622320' => array ( 'iso' => 'FO', 'name' => 'Faroe Islands', 'continent' => 'Europe' ), '3017382' => array ( 'iso' => 'FR', 'name' => 'France', 'continent' => 'Europe' ), '2400553' => array ( 'iso' => 'GA', 'name' => 'Gabon', 'continent' => 'Africa' ), '2635167' => array ( 'iso' => 'GB', 'name' => 'United Kingdom', 'continent' => 'Europe' ), '3580239' => array ( 'iso' => 'GD', 'name' => 'Grenada', 'continent' => 'North America' ), '614540' => array ( 'iso' => 'GE', 'name' => 'Georgia', 'continent' => 'Asia' ), '3381670' => array ( 'iso' => 'GF', 'name' => 'French Guiana', 'continent' => 'South America' ), '3042362' => array ( 'iso' => 'GG', 'name' => 'Guernsey', 'continent' => 'Europe' ), '2300660' => array ( 'iso' => 'GH', 'name' => 'Ghana', 'continent' => 'Africa' ), '2411586' => array ( 'iso' => 'GI', 'name' => 'Gibraltar', 'continent' => 'Europe' ), '3425505' => array ( 'iso' => 'GL', 'name' => 'Greenland', 'continent' => 'North America' ), '2413451' => array ( 'iso' => 'GM', 'name' => 'Gambia', 'continent' => 'Africa' ), '2420477' => array ( 'iso' => 'GN', 'name' => 'Guinea', 'continent' => 'Africa' ), '3579143' => array ( 'iso' => 'GP', 'name' => 'Guadeloupe', 'continent' => 'North America' ), '2309096' => array ( 'iso' => 'GQ', 'name' => 'Equatorial Guinea', 'continent' => 'Africa' ), '390903' => array ( 'iso' => 'GR', 'name' => 'Greece', 'continent' => 'Europe' ), '3474415' => array ( 'iso' => 'GS', 'name' => 'South Georgia and the South Sandwich Islands', 'continent' => 'Antarctica' ), '3595528' => array ( 'iso' => 'GT', 'name' => 'Guatemala', 'continent' => 'North America' ), '4043988' => array ( 'iso' => 'GU', 'name' => 'Guam', 'continent' => 'Oceania' ), '2372248' => array ( 'iso' => 'GW', 'name' => 'Guinea-Bissau', 'continent' => 'Africa' ), '3378535' => array ( 'iso' => 'GY', 'name' => 'Guyana', 'continent' => 'South America' ), '1819730' => array ( 'iso' => 'HK', 'name' => 'Hong Kong', 'continent' => 'Asia' ), '1547314' => array ( 'iso' => 'HM', 'name' => 'Heard Island and McDonald Islands', 'continent' => 'Antarctica' ), '3608932' => array ( 'iso' => 'HN', 'name' => 'Honduras', 'continent' => 'North America' ), '3202326' => array ( 'iso' => 'HR', 'name' => 'Croatia', 'continent' => 'Europe' ), '3723988' => array ( 'iso' => 'HT', 'name' => 'Haiti', 'continent' => 'North America' ), '719819' => array ( 'iso' => 'HU', 'name' => 'Hungary', 'continent' => 'Europe' ), '1643084' => array ( 'iso' => 'ID', 'name' => 'Indonesia', 'continent' => 'Asia' ), '2963597' => array ( 'iso' => 'IE', 'name' => 'Ireland', 'continent' => 'Europe' ), '294640' => array ( 'iso' => 'IL', 'name' => 'Israel', 'continent' => 'Asia' ), '3042225' => array ( 'iso' => 'IM', 'name' => 'Isle of Man', 'continent' => 'Europe' ), '1269750' => array ( 'iso' => 'IN', 'name' => 'India', 'continent' => 'Asia' ), '1282588' => array ( 'iso' => 'IO', 'name' => 'British Indian Ocean Territory', 'continent' => 'Asia' ), '99237' => array ( 'iso' => 'IQ', 'name' => 'Iraq', 'continent' => 'Asia' ), '130758' => array ( 'iso' => 'IR', 'name' => 'Iran', 'continent' => 'Asia' ), '2629691' => array ( 'iso' => 'IS', 'name' => 'Iceland', 'continent' => 'Europe' ), '3175395' => array ( 'iso' => 'IT', 'name' => 'Italy', 'continent' => 'Europe' ), '3042142' => array ( 'iso' => 'JE', 'name' => 'Jersey', 'continent' => 'Europe' ), '3489940' => array ( 'iso' => 'JM', 'name' => 'Jamaica', 'continent' => 'North America' ), '248816' => array ( 'iso' => 'JO', 'name' => 'Jordan', 'continent' => 'Asia' ), '1861060' => array ( 'iso' => 'JP', 'name' => 'Japan', 'continent' => 'Asia' ), '192950' => array ( 'iso' => 'KE', 'name' => 'Kenya', 'continent' => 'Africa' ), '1527747' => array ( 'iso' => 'KG', 'name' => 'Kyrgyzstan', 'continent' => 'Asia' ), '1831722' => array ( 'iso' => 'KH', 'name' => 'Cambodia', 'continent' => 'Asia' ), '4030945' => array ( 'iso' => 'KI', 'name' => 'Kiribati', 'continent' => 'Oceania' ), '921929' => array ( 'iso' => 'KM', 'name' => 'Comoros', 'continent' => 'Africa' ), '3575174' => array ( 'iso' => 'KN', 'name' => 'Saint Kitts and Nevis', 'continent' => 'North America' ), '1873107' => array ( 'iso' => 'KP', 'name' => 'North Korea', 'continent' => 'Asia' ), '1835841' => array ( 'iso' => 'KR', 'name' => 'South Korea', 'continent' => 'Asia' ), '831053' => array ( 'iso' => 'XK', 'name' => 'Kosovo', 'continent' => 'Europe' ), '285570' => array ( 'iso' => 'KW', 'name' => 'Kuwait', 'continent' => 'Asia' ), '3580718' => array ( 'iso' => 'KY', 'name' => 'Cayman Islands', 'continent' => 'North America' ), '1522867' => array ( 'iso' => 'KZ', 'name' => 'Kazakhstan', 'continent' => 'Asia' ), '1655842' => array ( 'iso' => 'LA', 'name' => 'Laos', 'continent' => 'Asia' ), '272103' => array ( 'iso' => 'LB', 'name' => 'Lebanon', 'continent' => 'Asia' ), '3576468' => array ( 'iso' => 'LC', 'name' => 'Saint Lucia', 'continent' => 'North America' ), '3042058' => array ( 'iso' => 'LI', 'name' => 'Liechtenstein', 'continent' => 'Europe' ), '1227603' => array ( 'iso' => 'LK', 'name' => 'Sri Lanka', 'continent' => 'Asia' ), '2275384' => array ( 'iso' => 'LR', 'name' => 'Liberia', 'continent' => 'Africa' ), '932692' => array ( 'iso' => 'LS', 'name' => 'Lesotho', 'continent' => 'Africa' ), '597427' => array ( 'iso' => 'LT', 'name' => 'Lithuania', 'continent' => 'Europe' ), '2960313' => array ( 'iso' => 'LU', 'name' => 'Luxembourg', 'continent' => 'Europe' ), '458258' => array ( 'iso' => 'LV', 'name' => 'Latvia', 'continent' => 'Europe' ), '2215636' => array ( 'iso' => 'LY', 'name' => 'Libya', 'continent' => 'Africa' ), '2542007' => array ( 'iso' => 'MA', 'name' => 'Morocco', 'continent' => 'Africa' ), '2993457' => array ( 'iso' => 'MC', 'name' => 'Monaco', 'continent' => 'Europe' ), '617790' => array ( 'iso' => 'MD', 'name' => 'Moldova', 'continent' => 'Europe' ), '3194884' => array ( 'iso' => 'ME', 'name' => 'Montenegro', 'continent' => 'Europe' ), '3578421' => array ( 'iso' => 'MF', 'name' => 'Saint Martin', 'continent' => 'North America' ), '1062947' => array ( 'iso' => 'MG', 'name' => 'Madagascar', 'continent' => 'Africa' ), '2080185' => array ( 'iso' => 'MH', 'name' => 'Marshall Islands', 'continent' => 'Oceania' ), '718075' => array ( 'iso' => 'MK', 'name' => 'Macedonia', 'continent' => 'Europe' ), '2453866' => array ( 'iso' => 'ML', 'name' => 'Mali', 'continent' => 'Africa' ), '1327865' => array ( 'iso' => 'MM', 'name' => 'Myanmar', 'continent' => 'Asia' ), '2029969' => array ( 'iso' => 'MN', 'name' => 'Mongolia', 'continent' => 'Asia' ), '1821275' => array ( 'iso' => 'MO', 'name' => 'Macao', 'continent' => 'Asia' ), '4041468' => array ( 'iso' => 'MP', 'name' => 'Northern Mariana Islands', 'continent' => 'Oceania' ), '3570311' => array ( 'iso' => 'MQ', 'name' => 'Martinique', 'continent' => 'North America' ), '2378080' => array ( 'iso' => 'MR', 'name' => 'Mauritania', 'continent' => 'Africa' ), '3578097' => array ( 'iso' => 'MS', 'name' => 'Montserrat', 'continent' => 'North America' ), '2562770' => array ( 'iso' => 'MT', 'name' => 'Malta', 'continent' => 'Europe' ), '934292' => array ( 'iso' => 'MU', 'name' => 'Mauritius', 'continent' => 'Africa' ), '1282028' => array ( 'iso' => 'MV', 'name' => 'Maldives', 'continent' => 'Asia' ), '927384' => array ( 'iso' => 'MW', 'name' => 'Malawi', 'continent' => 'Africa' ), '3996063' => array ( 'iso' => 'MX', 'name' => 'Mexico', 'continent' => 'North America' ), '1733045' => array ( 'iso' => 'MY', 'name' => 'Malaysia', 'continent' => 'Asia' ), '1036973' => array ( 'iso' => 'MZ', 'name' => 'Mozambique', 'continent' => 'Africa' ), '3355338' => array ( 'iso' => 'NA', 'name' => 'Namibia', 'continent' => 'Africa' ), '2139685' => array ( 'iso' => 'NC', 'name' => 'New Caledonia', 'continent' => 'Oceania' ), '2440476' => array ( 'iso' => 'NE', 'name' => 'Niger', 'continent' => 'Africa' ), '2155115' => array ( 'iso' => 'NF', 'name' => 'Norfolk Island', 'continent' => 'Oceania' ), '2328926' => array ( 'iso' => 'NG', 'name' => 'Nigeria', 'continent' => 'Africa' ), '3617476' => array ( 'iso' => 'NI', 'name' => 'Nicaragua', 'continent' => 'North America' ), '2750405' => array ( 'iso' => 'NL', 'name' => 'Netherlands', 'continent' => 'Europe' ), '3144096' => array ( 'iso' => 'NO', 'name' => 'Norway', 'continent' => 'Europe' ), '1282988' => array ( 'iso' => 'NP', 'name' => 'Nepal', 'continent' => 'Asia' ), '2110425' => array ( 'iso' => 'NR', 'name' => 'Nauru', 'continent' => 'Oceania' ), '4036232' => array ( 'iso' => 'NU', 'name' => 'Niue', 'continent' => 'Oceania' ), '2186224' => array ( 'iso' => 'NZ', 'name' => 'New Zealand', 'continent' => 'Oceania' ), '286963' => array ( 'iso' => 'OM', 'name' => 'Oman', 'continent' => 'Asia' ), '3703430' => array ( 'iso' => 'PA', 'name' => 'Panama', 'continent' => 'North America' ), '3932488' => array ( 'iso' => 'PE', 'name' => 'Peru', 'continent' => 'South America' ), '4030656' => array ( 'iso' => 'PF', 'name' => 'French Polynesia', 'continent' => 'Oceania' ), '2088628' => array ( 'iso' => 'PG', 'name' => 'Papua New Guinea', 'continent' => 'Oceania' ), '1694008' => array ( 'iso' => 'PH', 'name' => 'Philippines', 'continent' => 'Asia' ), '1168579' => array ( 'iso' => 'PK', 'name' => 'Pakistan', 'continent' => 'Asia' ), '798544' => array ( 'iso' => 'PL', 'name' => 'Poland', 'continent' => 'Europe' ), '3424932' => array ( 'iso' => 'PM', 'name' => 'Saint Pierre and Miquelon','continent' => 'North America' ), '4030699' => array ( 'iso' => 'PN', 'name' => 'Pitcairn', 'continent' => 'Oceania' ), '4566966' => array ( 'iso' => 'PR', 'name' => 'Puerto Rico', 'continent' => 'North America' ), '6254930' => array ( 'iso' => 'PS', 'name' => 'Palestinian Territory', 'continent' => 'Asia' ), '2264397' => array ( 'iso' => 'PT', 'name' => 'Portugal', 'continent' => 'Europe' ), '1559582' => array ( 'iso' => 'PW', 'name' => 'Palau', 'continent' => 'Oceania' ), '3437598' => array ( 'iso' => 'PY', 'name' => 'Paraguay', 'continent' => 'South America' ), '289688' => array ( 'iso' => 'QA', 'name' => 'Qatar', 'continent' => 'Asia' ), '935317' => array ( 'iso' => 'RE', 'name' => 'Reunion', 'continent' => 'Africa' ), '798549' => array ( 'iso' => 'RO', 'name' => 'Romania', 'continent' => 'Europe' ), '6290252' => array ( 'iso' => 'RS', 'name' => 'Serbia', 'continent' => 'Europe' ), '2017370' => array ( 'iso' => 'RU', 'name' => 'Russia', 'continent' => 'Europe' ), '49518' => array ( 'iso' => 'RW', 'name' => 'Rwanda', 'continent' => 'Africa' ), '102358' => array ( 'iso' => 'SA', 'name' => 'Saudi Arabia', 'continent' => 'Asia' ), '2103350' => array ( 'iso' => 'SB', 'name' => 'Solomon Islands', 'continent' => 'Oceania' ), '241170' => array ( 'iso' => 'SC', 'name' => 'Seychelles', 'continent' => 'Africa' ), '366755' => array ( 'iso' => 'SD', 'name' => 'Sudan', 'continent' => 'Africa' ), '7909807' => array ( 'iso' => 'SS', 'name' => 'South Sudan', 'continent' => 'Africa' ), '2661886' => array ( 'iso' => 'SE', 'name' => 'Sweden', 'continent' => 'Europe' ), '1880251' => array ( 'iso' => 'SG', 'name' => 'Singapore', 'continent' => 'Asia' ), '3370751' => array ( 'iso' => 'SH', 'name' => 'Saint Helena', 'continent' => 'Africa' ), '3190538' => array ( 'iso' => 'SI', 'name' => 'Slovenia', 'continent' => 'Europe' ), '607072' => array ( 'iso' => 'SJ', 'name' => 'Svalbard and Jan Mayen', 'continent' => 'Europe' ), '3057568' => array ( 'iso' => 'SK', 'name' => 'Slovakia', 'continent' => 'Europe' ), '2403846' => array ( 'iso' => 'SL', 'name' => 'Sierra Leone', 'continent' => 'Africa' ), '3168068' => array ( 'iso' => 'SM', 'name' => 'San Marino', 'continent' => 'Europe' ), '2245662' => array ( 'iso' => 'SN', 'name' => 'Senegal', 'continent' => 'Africa' ), '51537' => array ( 'iso' => 'SO', 'name' => 'Somalia', 'continent' => 'Africa' ), '3382998' => array ( 'iso' => 'SR', 'name' => 'Suriname', 'continent' => 'South America' ), '2410758' => array ( 'iso' => 'ST', 'name' => 'Sao Tome and Principe', 'continent' => 'Africa' ), '3585968' => array ( 'iso' => 'SV', 'name' => 'El Salvador', 'continent' => 'North America' ), '7609695' => array ( 'iso' => 'SX', 'name' => 'Sint Maarten', 'continent' => 'North America' ), '163843' => array ( 'iso' => 'SY', 'name' => 'Syria', 'continent' => 'Asia' ), '934841' => array ( 'iso' => 'SZ', 'name' => 'Swaziland', 'continent' => 'Africa' ), '3576916' => array ( 'iso' => 'TC', 'name' => 'Turks and Caicos Islands','continent' => 'North America' ), '2434508' => array ( 'iso' => 'TD', 'name' => 'Chad', 'continent' => 'Africa' ), '1546748' => array ( 'iso' => 'TF', 'name' => 'French Southern Territories', 'continent' => 'Antarctica' ), '2363686' => array ( 'iso' => 'TG', 'name' => 'Togo', 'continent' => 'Africa' ), '1605651' => array ( 'iso' => 'TH', 'name' => 'Thailand', 'continent' => 'Asia' ), '1220409' => array ( 'iso' => 'TJ', 'name' => 'Tajikistan', 'continent' => 'Asia' ), '4031074' => array ( 'iso' => 'TK', 'name' => 'Tokelau', 'continent' => 'Oceania' ), '1966436' => array ( 'iso' => 'TL', 'name' => 'East Timor', 'continent' => 'Oceania' ), '1218197' => array ( 'iso' => 'TM', 'name' => 'Turkmenistan', 'continent' => 'Asia' ), '2464461' => array ( 'iso' => 'TN', 'name' => 'Tunisia', 'continent' => 'Africa' ), '4032283' => array ( 'iso' => 'TO', 'name' => 'Tonga', 'continent' => 'Oceania' ), '298795' => array ( 'iso' => 'TR', 'name' => 'Turkey', 'continent' => 'Asia' ), '3573591' => array ( 'iso' => 'TT', 'name' => 'Trinidad and Tobago', 'continent' => 'North America' ), '2110297' => array ( 'iso' => 'TV', 'name' => 'Tuvalu', 'continent' => 'Oceania' ), '1668284' => array ( 'iso' => 'TW', 'name' => 'Taiwan', 'continent' => 'Asia' ), '149590' => array ( 'iso' => 'TZ', 'name' => 'Tanzania', 'continent' => 'Africa' ), '690791' => array ( 'iso' => 'UA', 'name' => 'Ukraine', 'continent' => 'Europe' ), '226074' => array ( 'iso' => 'UG', 'name' => 'Uganda', 'continent' => 'Africa' ), '5854968' => array ( 'iso' => 'UM', 'name' => 'United States Minor Outlying Islands', 'continent' => 'Oceania' ), '6252001' => array ( 'iso' => 'US', 'name' => 'United States', 'continent' => 'North America' ), '3439705' => array ( 'iso' => 'UY', 'name' => 'Uruguay', 'continent' => 'South America' ), '1512440' => array ( 'iso' => 'UZ', 'name' => 'Uzbekistan', 'continent' => 'Asia' ), '3164670' => array ( 'iso' => 'VA', 'name' => 'Vatican', 'continent' => 'Europe' ), '3577815' => array ( 'iso' => 'VC', 'name' => 'Saint Vincent and the Grenadines', 'continent' => 'North America' ), '3625428' => array ( 'iso' => 'VE', 'name' => 'Venezuela', 'continent' => 'South America' ), '3577718' => array ( 'iso' => 'VG', 'name' => 'British Virgin Islands', 'continent' => 'North America' ), '4796775' => array ( 'iso' => 'VI', 'name' => 'U.S. Virgin Islands', 'continent' => 'North America' ), '1562822' => array ( 'iso' => 'VN', 'name' => 'Vietnam', 'continent' => 'Asia' ), '2134431' => array ( 'iso' => 'VU', 'name' => 'Vanuatu', 'continent' => 'Oceania' ), '4034749' => array ( 'iso' => 'WF', 'name' => 'Wallis and Futuna', 'continent' => 'Oceania' ), '4034894' => array ( 'iso' => 'WS', 'name' => 'Samoa', 'continent' => 'Oceania' ), '69543' => array ( 'iso' => 'YE', 'name' => 'Yemen', 'continent' => 'Asia' ), '1024031' => array ( 'iso' => 'YT', 'name' => 'Mayotte', 'continent' => 'Africa' ), '953987' => array ( 'iso' => 'ZA', 'name' => 'South Africa', 'continent' => 'Africa' ), '895949' => array ( 'iso' => 'ZM', 'name' => 'Zambia', 'continent' => 'Africa' ), '878675' => array ( 'iso' => 'ZW', 'name' => 'Zimbabwe', 'continent' => 'Africa' ) ); // Remove previous list of GeoIP ISOs for IPv4/6 Source Field lookup unlink_if_exists("{$pfb['geoip_isos']}"); // Determine if any Countries are missing from the MaxMind Database foreach ($pfb_geoip_all as $iso => $cc) { // Create list of GeoIP ISOs for IPv4/6 Source Field lookup @file_put_contents("{$pfb['geoip_isos']}", "{$cc['iso']} [ {$cc['name']} ],{$cc['iso']}_rep [ {$cc['name']} ],", FILE_APPEND | LOCK_EX); // Add missing Country as a 'placeholder' if (!isset($pfb_geoip['country'][$iso])) { $continent_en = str_replace(array(' ', '"'), array('_', ''), $cc['continent']); $pfb_geoip['country'][$iso] = array ( 'missing_iso' => TRUE, 'id' => $iso, 'name' => $cc['name'], 'iso' => array ( "{$cc['iso']}", "{$cc['iso']}_rep" ), 'continent' => $cc['continent'], 'continent_en' => $continent_en); $pfb_geoip['country']['proxy']['iso'][] = "A1_{$cc['iso']}_rep"; $pfb_geoip['country']['satellite']['iso'][] = "A2_{$cc['iso']}_rep"; } } // Add Continents to GeoIP ISOs for IPv4/6 Source Field lookup $add_continents = 'Africa [Continent],Antarctica [Continent],Asia [Continent],Europe [Continent],North_America [Continent],Oceania [Continent]'; $add_continents .= ',South_America [Continent],Proxy_and_Satellite [GeoIP]'; @file_put_contents("{$pfb['geoip_isos']}", "{$add_continents}", FILE_APPEND | LOCK_EX); ksort($pfb_geoip['country'], SORT_NATURAL); // 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 [ NOW ]\n"; pfb_logger("{$log}", 4); $geoip_dup = 0; // Count of Geoname_ids which have both a different 'Registered and Represented' geoname_id $maxmind_cc = "{$pfb['geoipshare']}/GeoLite2-Country-Blocks-IPv{$type}.csv"; if (($handle = @fopen("{$maxmind_cc}", 'r')) !== FALSE) { while (($cc = @fgetcsv($handle)) !== FALSE) { /* Sample lines: Network,geoname_id,registered_country_geoname_id,represented_country_geoname_id,is_anonymous_proxy,is_satellite_provider 1.0.0.0/24,2077456,2077456,,0,0 */ if ($cc[0] == 'network') { continue; } $iso = $iso_rep = ''; if ($type == 4) { // Remove all Countries listed by MaxMind from list of all known Countries if (isset($pfb_geoip_all[$cc[1]])) { unset($pfb_geoip_all[$cc[1]]); } // Is Anonymous Proxy? if ($cc[4] == 1) { if (!empty($cc[1])) { $iso = "A1_{$pfb_geoip['country']['proxy']['iso'][0]}"; } if (!empty($cc[2]) && $cc[1] != $cc[2]) { $geoip_dup++; $iso_rep = "A1_{$pfb_geoip['country'][$cc[2]]['iso'][0]}_rep"; } if (empty($cc[1]) && empty($cc[2])) { $iso = 'A1'; } $cc[2] = 'proxy'; // Re-define variable } // Is Satellite Provider? elseif ($cc[5] == 1) { if (!empty($cc[1])) { $iso = "A2_{$pfb_geoip['country']['satellite']['iso'][0]}"; } if (!empty($cc[2]) && $cc[1] != $cc[2]) { $geoip_dup++; $iso_rep = "A2_{$pfb_geoip['country'][$cc[2]]['iso'][0]}_rep"; } if (empty($cc[1]) && empty($cc[2])) { $iso = 'A2'; } $cc[2] = 'satellite'; // Re-define variable } else { if (!empty($cc[1])) { $iso = "{$pfb_geoip['country'][$cc[1]]['iso'][0]}"; } if (!empty($cc[2]) && $cc[1] != $cc[2]) { $geoip_dup++; $iso_rep = "{$pfb_geoip['country'][$cc[2]]['iso'][0]}_rep"; } } // Add 'ISO Represented' to Country ISO list if (!empty($iso_rep) && !empty($cc[2])) { // Only add if not existing if (!isset($pfb_geoip['country'][$cc[2]]) || !in_array($iso_rep, $pfb_geoip['country'][$cc[2]]['iso'])) { $pfb_geoip['country'][$cc[2]]['iso'][] = "{$iso_rep}"; } } // Add placeholders for 'undefined ISO Represented' to Country ISO list if (!empty($cc[1])) { foreach (array( '' => $cc[1], 'A1_' => 'proxy', 'A2_' => 'satellite' ) as $reptype => $iso_placeholder) { $iso_rep_placeholder = "{$reptype}{$pfb_geoip['country'][$cc[1]]['iso'][0]}_rep"; // Only add if not existing if (!isset($pfb_geoip['country'][$iso_placeholder]) || !in_array($iso_rep_placeholder, $pfb_geoip['country'][$iso_placeholder]['iso'])) { $pfb_geoip['country'][$iso_placeholder]['iso'][] = "{$iso_rep_placeholder}"; } } } // Save ISO 'Represented Network' to ISO file if (!empty($iso_rep) && !empty($cc[0]) && !empty(pfb_filter($iso_rep, PFB_FILTER_WORD, 'php'))) { @file_put_contents("{$pfb['ccdir_tmp']}/{$iso_rep}_v{$type}.txt", "{$cc[0]}\n", FILE_APPEND | LOCK_EX); } } else { if (!empty($cc[1])) { $iso = "{$pfb_geoip['country'][$cc[1]]['iso'][0]}"; } } // Save 'ISO Registered Network' to ISO file if (!empty($iso) && !empty($cc[0]) && !empty(pfb_filter($iso, PFB_FILTER_WORD, 'php'))) { @file_put_contents("{$pfb['ccdir_tmp']}/{$iso}_v{$type}.txt", "{$cc[0]}\n", FILE_APPEND | LOCK_EX); } } // For IPv4 - Add A1 & A2 placeholders for any Countries that MaxMind has not listed any data if ($type == 4) { if (!empty($pfb_geoip_all)) { foreach ($pfb_geoip_all as $cc) { foreach (array( 'A1_' => 'proxy', 'A2_' => 'satellite' ) as $reptype => $iso_placeholder) { $pfb_geoip['country'][$iso_placeholder]['iso'][] = "{$reptype}{$cc['iso']}_rep"; } } } unset($pfb_geoip_all); } // Report number of Geoname_ids which have both a different 'Registered and Represented' geoname_id if ($geoip_dup != 0) { @file_put_contents("{$pfb['logdir']}/maxmind_ver", "Duplicate Represented IP{$type} Networks: {$geoip_dup}\n", FILE_APPEND | LOCK_EX); } // Delete previous GeoIP Continent files array_map('unlink_if_exists', array( "{$pfb['ccdir']}/Top_Spammers_v{$type}.info", "{$pfb['ccdir']}/Africa_v{$type}.txt", "{$pfb['ccdir']}/Antarctica_v{$type}.txt", "{$pfb['ccdir']}/Asia_v{$type}.txt", "{$pfb['ccdir']}/Europe_v{$type}.txt", "{$pfb['ccdir']}/*_America_v{$type}.txt", "{$pfb['ccdir']}/Oceania_v{$type}.txt", "{$pfb['ccdir']}/Proxy_and_Satellite_v{$type}.txt" )); // Create Continent txt files if (!empty($pfb_geoip['country'])) { foreach ($pfb_geoip['country'] as $key => $geoip) { // Save 'TOP 20' data if (strpos($key, 'A000') !== FALSE) { $pfb_file = "{$pfb['ccdir']}/Top_Spammers_v{$type}.info"; if (!file_exists($pfb_file)) { $header = '# Generated from MaxMind Inc. on: ' . date('m/j/y G:i:s', time()) . "\n"; $header .= "# Continent IPv{$type}: Top_Spammers\n"; $header .= "# Continent en: Top_Spammers\n"; @file_put_contents($pfb_file, $header, LOCK_EX); } $iso_header = "# Country: {$geoip['name']} ({$geoip['id']})\n"; $iso_header .= "# ISO Code: {$geoip['iso']}\n"; $iso_header .= "# Total Networks: Top20\n"; $iso_header .= "Top20\n"; // Add any 'TOP 20' Represented ISOs Networks if (file_exists("{$pfb['ccdir_tmp']}/{$geoip['iso']}_rep_v{$type}.txt")) { $iso_header .= "# Country: {$geoip['name']} ({$geoip['id']})\n"; $iso_header .= "# ISO Code: {$geoip['iso']}_rep\n"; $iso_header .= "# Total Networks: Top20\n"; $iso_header .= "Top20\n"; } @file_put_contents($pfb_file, $iso_header, FILE_APPEND | LOCK_EX); } else { if (!empty($geoip['continent_en']) && !empty(pfb_filter($geoip['continent_en'], PFB_FILTER_WORD, 'php'))) { $pfb_file = "{$pfb['ccdir']}/{$geoip['continent_en']}_v{$type}.txt"; $pfb_file_esc = escapeshellarg($pfb_file); if (!file_exists($pfb_file)) { $header = '# Generated from MaxMind Inc. on: ' . date('m/j/y G:i:s', time()) . "\n"; $header .= "# Continent IPv{$type}: {$geoip['continent']}\n"; $header .= "# Continent en: {$geoip['continent_en']}\n"; @file_put_contents($pfb_file, $header, LOCK_EX); } if (!empty($geoip['iso'])) { foreach ($geoip['iso'] as $iso) { if (!empty(pfb_filter($iso, PFB_FILTER_WORD, 'php'))) { $iso_file = "{$pfb['ccdir_tmp']}/{$iso}_v{$type}.txt"; $iso_file_esc = escapeshellarg($iso_file); $geoip_id = ''; if (!empty($geoip['id'])) { $geoip_id = " [{$geoip['id']}]"; } if (file_exists($iso_file)) { $networks = exec("{$pfb['grep']} -c ^ {$iso_file_esc} 2>&1"); $iso_header = "# Country: {$geoip['name']}{$geoip_id}\n"; $iso_header .= "# ISO Code: {$iso}\n"; $iso_header .= "# Total Networks: {$networks}\n"; @file_put_contents($pfb_file, $iso_header, FILE_APPEND | LOCK_EX); // Concat ISO Networks to Continent file exec("{$pfb['cat']} {$iso_file_esc} >> {$pfb_file_esc} 2>&1"); } else { // Create placeholder file for undefined 'ISO Represented' or undefined Countries $iso_header = "# Country: {$geoip['name']}{$geoip_id}\n"; $iso_header .= "# ISO Code: {$iso}\n"; $iso_header .= "# Total Networks: NA\n"; @file_put_contents($pfb_file, $iso_header, FILE_APPEND | LOCK_EX); } } } // Reset ISOs to original setting (Remove any Represented ISOs) $pfb_geoip['country'][$key]['iso'] = array($pfb_geoip['country'][$key]['iso'][0]); } else { $log = "\n Missing ISO data: {$geoip['continent']}"; pfb_logger("{$log}", 4); } } else { $log = "\n Failed to create Continent file: {$geoip['continent']}"; pfb_logger("{$log}", 4); } } } } if ($cc) { unset($cc); } if ($handle) { @fclose($handle); } } else { $log = "\n Failed to load file: {$maxmind_cc}\n"; pfb_logger("{$log}", 4); } } unset($pfb_geoip); rmdir_recursive("{$pfb['ccdir_tmp']}"); } // Function to process Continent txt files and create Country ISO files and to Generate GUI PHP files. function pfblockerng_get_countries() { global $g, $pfb; $geoip_files = array ( 'Africa' => "{$pfb['ccdir']}/Africa_v4.txt", 'Antarctica' => "{$pfb['ccdir']}/Antarctica_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_and_Satellite_v4.txt", 'Top Spammers' => "{$pfb['ccdir']}/Top_Spammers_v4.info" ); // Collect data to generate new continent PHP files. $log = " Creating pfBlockerNG Continent PHP files\n"; pfb_logger("{$log}", 4); $continent = $continent_en = ''; $roptions4 = array(); foreach ($geoip_files as $cont => $file) { // Process the following for IPv4 and IPv6 foreach (array('4', '6') as $type) { $cont_length = strlen($cont); if ($cont_length < 8) { $tab = "\t\t\t"; } elseif ($cont_length < 19) { $tab = "\t\t"; } else { $tab = "\t"; } $log = " IPv{$type} {$cont}{$tab} [ NOW ]\n"; pfb_logger("{$log}", 4); if ($type == '6') { $file = str_replace('v4', 'v6', $file); } $file_esc = escapeshellarg($file); $lastline = exec("{$pfb['grep']} -c ^ {$file_esc}") ?: 0; $pfb['complete'] = FALSE; $linenum = 1; $total = 0; if (($handle = @fopen("{$file}", 'r')) !== FALSE) { while (($line = @fgets($handle)) !== FALSE) { $line = trim($line); if (substr($line, 0, 1) == '#') { if ($pfb['complete']) { if (file_exists("{$pfb['ccdir']}/{$isocode}_v{$type}.txt")) { ${'coptions' . $type}[] = "{$country}|\"{$isocode}\" => \"{$country} {$isocode} ({$total})\""; // Only collect IPv4 for Reputation Tab if ($type == '4' && strpos($isocode, '_rep') === FALSE) { $roptions4[] = "{$country}|\"{$isocode}\" => \"{$country} {$isocode} ({$total})\""; } } // Clear variables and restart Continent collection process $total = 0; $pfb['complete'] = FALSE; } if (strpos($line, 'Continent IPv') !== FALSE) { $continent = trim(str_replace(':', '', strstr($line, ':', FALSE))); } if (strpos($line, 'Continent en:') !== FALSE) { $continent_en = trim(str_replace(':', '', strstr($line, ':', FALSE))); } if (strpos($line, 'Country: ') !== FALSE) { $country = str_replace('# Country: ', '', $line); } if (strpos($line, 'ISO Code: ') !== FALSE) { $isocode = str_replace('# ISO Code: ', '', $line); // Remove previous ISO file if ($cont != 'Top Spammers') { unlink_if_exists("{$pfb['ccdir']}/{$isocode}_v{$type}.txt"); } } // Create placeholder for null ISO Data or 'undefined ISO Represented' if (strpos($line, 'Total Networks: 0') !== FALSE || strpos($line, 'Total Networks: NA') !== FALSE) { if (!empty(pfb_filter($isocode, PFB_FILTER_WORD, 'php'))) { @file_put_contents("{$pfb['ccdir']}/{$isocode}_v{$type}.txt", '', LOCK_EX); } $pfb['complete'] = TRUE; } } elseif (substr($line, 0, 1) != '#') { if (!empty(pfb_filter($isocode, PFB_FILTER_WORD, 'php'))) { if ($cont == 'Top Spammers') { $isocode_esc = escapeshellarg("{$pfb['ccdir']}/{$isocode}_v{$type}.txt"); $total = exec("{$pfb['grep']} -c ^ {$isocode_esc} 2>&1"); } else { $total++; if (!empty($line)) { @file_put_contents("{$pfb['ccdir']}/{$isocode}_v{$type}.txt", "{$line}\n", FILE_APPEND | LOCK_EX); } } } $pfb['complete'] = TRUE; } // Save last EOF ISO IP data if ($linenum == $lastline) { if (!empty(pfb_filter($isocode, PFB_FILTER_WORD, 'php'))) { // Create placeholder for null ISO Data or 'undefined ISO Represented' if (strpos($line, 'Total Networks: 0') !== FALSE || strpos($line, 'Total Networks: NA') !== FALSE) { @file_put_contents("{$pfb['ccdir']}/{$isocode}_v{$type}.txt", '', LOCK_EX); } if (file_exists("{$pfb['ccdir']}/{$isocode}_v{$type}.txt")) { ${'coptions' . $type}[] = "{$country}|\"{$isocode}\" => \"{$country} {$isocode} ({$total})\""; if ($type == '4' && strpos($isocode, '_rep') === FALSE) { $roptions4[] = "{$country}|\"{$isocode}\" => \"{$country} {$isocode} ({$total})\""; } } } } $linenum++; } } if ($handle) { @fclose($handle); } if (empty($continent)) { pfb_logger("Continent data [ {$cont} ] not found\n", 4); continue; } // Sort IP Countries alphabetically and build PHP drop-down lists for Continent tabs if (!empty(${'coptions' . $type})) { if ($cont != 'Top Spammers') { sort(${'coptions' . $type}, SORT_STRING); } ${'ftotal' . $type} = count(${'coptions' . $type}); $count = 1; ${'options' . $type} = ''; foreach (${'coptions' . $type} as $option) { // Remove prefixed Country string (Used to sort array) $option = ltrim(strstr($option, '|', FALSE), '|'); if ($count == 1) { ${'options' . $type} .= "\t{$option},\n"; $count++; continue; } if (${'ftotal' . $type} == $count) { ${'options' . $type} .= "\t\t{$option}\n\t"; } else { ${'options' . $type} .= "\t\t{$option},\n"; } $count++; } } unset(${'coptions' . $type}); } $php_data = << 'Disabled', 'Deny_Inbound' => 'Deny Inbound', 'Deny_Outbound' => 'Deny Outbound', 'Deny_Both' => 'Deny Both', 'Permit_Inbound' => 'Permit Inbound', 'Permit_Outbound' => 'Permit Outbound', 'Permit_Both' => 'Permit Both', 'Match_Inbound' => 'Match Inbound', 'Match_Outbound' => 'Match Outbound', 'Match_Both' => 'Match Both', 'Alias_Deny' => 'Alias Deny', 'Alias_Permit' => 'Alias Permit', 'Alias_Match' => 'Alias Match', 'Alias_Native' => 'Alias Native' ]; $options_aliaslog = [ 'enabled' => 'Enabled', 'disabled' => 'Disabled' ]; // Collect all pfSense 'Port' Aliases $portslist = $networkslist = ''; $options_aliasports_in = $options_aliasports_out = array(); foreach (config_get_path('aliases/alias', []) as $alias) { if ($alias['type'] == 'port') { $portslist .= "{$alias['name']},"; $options_aliasports_in[$alias['name']] = $alias['name']; $options_aliasports_out[$alias['name']] = $alias['name']; } elseif ($alias['type'] == 'network') { $networkslist .= "{$alias['name']},"; $options_aliasaddr_in[$alias['name']] = $alias['name']; $options_aliasaddr_out[$alias['name']] = $alias['name']; } } $ports_list = trim($portslist, ','); $networks_list = trim($networkslist, ','); $options_autoproto_in = $options_autoproto_out = get_ipprotocols(); $options_agateway_in = $options_agateway_out = pfb_get_gateways(); $continent_display = str_replace('_', ' ', "{$continent}"); // Continent name displayed on page $conf_type = 'pfblockerng' . strtolower(str_replace('_', '', $continent_en)); // XML config location $pfb['geoipconfig'] = config_get_path("installedpackages/{$conf_type}/config/0", []); $active[$continent_display] = TRUE; foreach (array('Top Spammers', 'Africa', 'Antarctica', 'Asia', 'Europe', 'North America', 'Oceania', 'South America', 'Proxy and Satellite') as $tab_active) { if (!isset($active[$tab_active])) { $active[$tab_active] = FALSE; } } $pconfig = array(); $pconfig['countries4'] = explode(',', $pfb['geoipconfig']['countries4']); $pconfig['countries6'] = explode(',', $pfb['geoipconfig']['countries6']); $pconfig['action'] = $pfb['geoipconfig']['action'] ?: 'Disabled'; $pconfig['aliaslog'] = $pfb['geoipconfig']['aliaslog'] ?: 'enabled'; $pconfig['autoaddrnot_in'] = $pfb['geoipconfig']['autoaddrnot_in']; $pconfig['autoports_in'] = $pfb['geoipconfig']['autoports_in']; $pconfig['aliasports_in'] = $pfb['geoipconfig']['aliasports_in']; $pconfig['autoaddr_in'] = $pfb['geoipconfig']['autoaddr_in']; $pconfig['autonot_in'] = $pfb['geoipconfig']['autonot_in']; $pconfig['aliasaddr_in'] = $pfb['geoipconfig']['aliasaddr_in']; $pconfig['autoproto_in'] = $pfb['geoipconfig']['autoproto_in']; $pconfig['agateway_in'] = $pfb['geoipconfig']['agateway_in']; $pconfig['autoaddrnot_out'] = $pfb['geoipconfig']['autoaddrnot_out']; $pconfig['autoports_out'] = $pfb['geoipconfig']['autoports_out']; $pconfig['aliasports_out'] = $pfb['geoipconfig']['aliasports_out']; $pconfig['autoaddr_out'] = $pfb['geoipconfig']['autoaddr_out']; $pconfig['autonot_out'] = $pfb['geoipconfig']['autonot_out']; $pconfig['aliasaddr_out'] = $pfb['geoipconfig']['aliasaddr_out']; $pconfig['autoproto_out'] = $pfb['geoipconfig']['autoproto_out']; $pconfig['agateway_out'] = $pfb['geoipconfig']['agateway_out']; // Validate input fields and save if ($_POST) { if (isset($_POST['save'])) { if (isset($input_errors)) { unset($input_errors); } // Validate Select field options $select_options = array( 'action' => 'Disabled', 'aliaslog' => 'enabled', 'aliasports_in' => '', 'aliasports_out' => '', 'aliasaddr_in' => '', 'aliasaddr_out' => '', 'autoproto_in' => 'any', 'autoproto_out' => 'any', 'agateway_in' => 'default', 'agateway_out' => 'default', ); foreach ($select_options as $s_option => $s_default) { if (!isset($_POST[$s_option])) { // do nothing } elseif (is_array($_POST[$s_option])) { $_POST[$s_option] = $s_default; } elseif (!array_key_exists($_POST[$s_option], ${"options_$s_option"})) { $_POST[$s_option] = $s_default; } } // Validate Select field (array) options $select_options = array( 'countries4' => '', 'countries6' => '' ); foreach ($select_options as $s_option => $s_default) { if (!isset($_POST[$s_option])) { // do nothing } elseif (is_array($_POST[$s_option])) { foreach ($_POST[$s_option] as $post_option) { if (!array_key_exists($post_option, ${"options_$s_option"})) { $_POST[$s_option] = $s_default; break; } } } elseif (!array_key_exists($_POST[$s_option], ${"options_$s_option"})) { $_POST[$s_option] = $s_default; } } // Validate Adv. In/Outbound firewall rules settings foreach (array( 'aliasports_in' => 'Port In', 'aliasaddr_in' => 'Destination In', 'aliasports_out' => 'Port Out', 'aliasaddr_out' => 'Destination Out') as $value => $auto_dir) { if (!empty($_POST[$value]) && !is_alias($_POST[$value])) { $input_errors[] = "Settings: Advanced {$auto_dir}bound Alias error - Must use an existing Alias"; } } // Validate Adv. firewall rule 'Protocol' setting if (!empty($_POST['autoports_in']) || !empty($_POST['autoaddr_in'])) { if (empty($_POST['autoproto_in']) || $_POST['autoproto_in'] == 'any') { $input_errors[] = "Settings: Protocol setting cannot be set to 'Any' with Advanced Inbound firewall rule settings."; } } if (!empty($_POST['autoports_out']) || !empty($_POST['autoaddr_out'])) { if (empty($_POST['autoproto_out']) || $_POST['autoproto_out'] == 'any') { $input_errors[] = "Settings: Protocol setting cannot be set to 'Any' with Advanced Outbound firewall rule settings."; } } // Validate if any Countries (v4/v6) are defined when Action is enabled. if ($_POST['action'] != 'Disabled' && !isset($_POST['countries4']) && !isset($_POST['countries6'])) { $input_errors[] = "No Countries defined!"; } // Avoid creating a permit rule on WAN with 'any' if ($_POST['action'] == 'Permit_Inbound' || $_POST['action'] == 'Permit_Both') { $pfb_warning = FALSE; if ($_POST['autoproto_in'] == '' || $_POST['autoproto_in'] == 'any') { $pfb_warning = TRUE; $input_errors[] = "Warning: When using an Action setting of 'Permit Inbound or Permit Both'," . " you must configure the 'Advanced Inbound Custom Protocol' setting. The current setting of 'Any' is not allowed."; } if ($_POST['aliasports_in'] == '' && $_POST['aliasaddr_in'] == '') { $pfb_warning = TRUE; $input_errors[] = "Warning: When using an Action setting of 'Permit Inbound or Permit Both'," . " you must configure at least one of 'Advanced Inbound Custom Port/Destination' settings."; } if ($pfb_warning) { $input_errors[] = ''; $input_errors[] = '===> WARNING <==='; $input_errors[] = "Improper Permit rules on the WAN can catastrophically impact the security of your network!"; } } if (!$input_errors) { $pfb['geoipconfig']['countries4'] = implode(',', (array)$_POST['countries4']) ?: ''; $pfb['geoipconfig']['countries6'] = implode(',', (array)$_POST['countries6']) ?: ''; $pfb['geoipconfig']['action'] = $_POST['action'] ?: ''; $pfb['geoipconfig']['aliaslog'] = $_POST['aliaslog'] ?: ''; $pfb['geoipconfig']['autoaddrnot_in'] = pfb_filter($_POST['autoaddrnot_in'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['autoports_in'] = pfb_filter($_POST['autoports_in'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['aliasports_in'] = $_POST['aliasports_in'] ?: ''; $pfb['geoipconfig']['autoaddr_in'] = pfb_filter($_POST['autoaddr_in'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['autonot_in'] = pfb_filter($_POST['autonot_in'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['aliasaddr_in'] = $_POST['aliasaddr_in'] ?: ''; $pfb['geoipconfig']['autoproto_in'] = $_POST['autoproto_in'] ?: 'any'; $pfb['geoipconfig']['agateway_in'] = $_POST['agateway_in'] ?: ''; $pfb['geoipconfig']['autoaddrnot_out'] = pfb_filter($_POST['autoaddrnot_out'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['autoports_out'] = pfb_filter($_POST['autoports_out'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['aliasports_out'] = $_POST['aliasports_out'] ?: ''; $pfb['geoipconfig']['autoaddr_out'] = pfb_filter($_POST['autoaddr_out'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['autonot_out'] = pfb_filter($_POST['autonot_out'], PFB_FILTER_ON_OFF, 'Geoip'); $pfb['geoipconfig']['aliasaddr_out'] = $_POST['aliasaddr_out'] ?: ''; $pfb['geoipconfig']['autoproto_out'] = $_POST['autoproto_out'] ?: 'any'; $pfb['geoipconfig']['agateway_out'] = $_POST['agateway_out'] ?: ''; config_set_path("installedpackages/{$conf_type}/config/0", $pfb['geoipconfig']); write_config("[pfBlockerNG] save GeoIP [ {$continent_display} ] settings"); header("Location: /pfblockerng/pfblockerng_{$continent_en}.php"); exit; } else { $pconfig = $_POST; // Restore failed user-entered data } } } $pgtitle = array(gettext('Firewall'), gettext('pfBlockerNG'), gettext('IP'), gettext('GeoIP'), $continent_display); $pglinks = array( '', '/pfblockerng/pfblockerng_general.php', '/pfblockerng/pfblockerng_ip.php', '/pfblockerng/pfblockerng_category.php?type=geoip', '@self'); include_once('head.inc'); if ($input_errors) { print_input_errors($input_errors); } // Define default Alerts Tab href link (Top row) $get_req = pfb_alerts_default_page(); $tab_array = array(); $tab_array[] = array(gettext('General'), false, '/pfblockerng/pfblockerng_general.php'); $tab_array[] = array(gettext('IP'), true, '/pfblockerng/pfblockerng_ip.php'); $tab_array[] = array(gettext('DNSBL'), false, '/pfblockerng/pfblockerng_dnsbl.php'); $tab_array[] = array(gettext('Update'), false, '/pfblockerng/pfblockerng_update.php'); $tab_array[] = array(gettext('Reports'), false, "/pfblockerng/pfblockerng_alerts.php{$get_req}"); $tab_array[] = array(gettext('Feeds'), false, '/pfblockerng/pfblockerng_feeds.php'); $tab_array[] = array(gettext('Logs'), false, '/pfblockerng/pfblockerng_log.php'); $tab_array[] = array(gettext('Sync'), false, '/pfblockerng/pfblockerng_sync.php'); display_top_tabs($tab_array, true); $tab_array = array(); $tab_array[] = array(gettext('GeoIP'), false, '/pfblockerng/pfblockerng_category.php?type=geoip'); $tab_array[] = array(gettext('Top Spammers'), $active['Top Spammers'] ?: false, '/pfblockerng/pfblockerng_Top_Spammers.php'); $tab_array[] = array(gettext('Africa'), $active['Africa'] ?: false, '/pfblockerng/pfblockerng_Africa.php'); $tab_array[] = array(gettext('Antarctica'), $active['Antarctica'] ?: false, '/pfblockerng/pfblockerng_Antarctica.php'); $tab_array[] = array(gettext('Asia'), $active['Asia'] ?: false, '/pfblockerng/pfblockerng_Asia.php'); $tab_array[] = array(gettext('Europe'), $active['Europe'] ?: false, '/pfblockerng/pfblockerng_Europe.php'); $tab_array[] = array(gettext('North America'), $active['North America'] ?: false, '/pfblockerng/pfblockerng_North_America.php'); $tab_array[] = array(gettext('Oceania'), $active['Oceania'] ?: false, '/pfblockerng/pfblockerng_Oceania.php'); $tab_array[] = array(gettext('South America'), $active['South America'] ?: false, '/pfblockerng/pfblockerng_South_America.php'); $tab_array[] = array(gettext('Proxy and Satellite'), $active['Proxy and Satellite'] ?: false, '/pfblockerng/pfblockerng_Proxy_and_Satellite.php'); display_top_tabs($tab_array, true); $form = new Form('Save'); $section = new Form_Section("Continent - {$continent_display}"); $section->addInput(new Form_StaticText( 'Links', '' . 'Firewall Alias ' . 'Firewall Rules ' . 'Firewall Logs' )); $section->addInput(new Form_StaticText( 'NOTES:', 'GeoIP data by MaxMind Inc. - GeoLite2
' . 'Click here for IMPORTANT info --> ' . '' . 'What\'s new in GeoIP2' . '
' . '
' . 'pfSense by default implicitly blocks all unsolicited inbound traffic to the WAN interface.
' . 'Therefore adding GeoIP based firewall rules to the WAN will not provide any benefit, unless there are open WAN ports.

' . 'It\'s also not recommended to block the \'world\', instead consider rules to \'Permit\' traffic from selected Countries only.
' . 'Also consider protecting just the specific open WAN ports and it\'s just as important to protect the outbound LAN traffic.

' . 'GeoIP ISOs can also be configured in the pfBlockerNG IPv4/IPv6 Alias(es) Source Definitions (Format: GeoIP)' . '
' . '
' . ' Use  CTRL+CLICK to select/unselect  the IPv4/6 Countries below as required.' )); // Maxmind License Key verification if (empty($pfb['maxmind_key'])) { print_callout('

' . 'MaxMind now requires a License Key! Review the IP tab: MaxMind settings for more information.' . '


', 'danger', ''); } $group = new Form_Group(''); $group->add(new Form_Select( 'countries4', NULL, $pconfig['countries4'], $options_countries4, TRUE ))->setHelp(' IPv4 countries')->setAttribute('size', $options_countries4_cnt) ->setAttribute('style', 'overflow: auto;'); $group->add(new Form_Select( 'countries6', NULL, $pconfig['countries6'], $options_countries6, TRUE ))->setHelp(' IPv6 countries')->setAttribute('size', $options_countries6_cnt) ->setAttribute('style', 'overflow: auto;'); $section->add($group); $form->add($section); $action_txt = "Default: Disabled
For Non-Alias type rules you must define the appropriate Firewall 'Auto' Rule Order option.
Click here for more info\xe2\x80\x83-->
Select the Action for Firewall Rules on lists you have selected.

'Disabled' Rules: Disables selection and does nothing to selected Alias.

'Deny' Rules:
'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:
'Permit' Rules:
'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:
'Match' Rules:
'Match' or 'Log' only the traffic on the stated interfaces. This does not Block or Reject. It just Logs the traffic. 'Alias' Rules:
'Alias' rules create an alias 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. Note:
"; $section->addInput(new Form_Select( 'action', 'List Action', $pconfig['action'], $options_action ))->setHelp($action_txt); $section->addInput(new Form_Select( 'aliaslog', 'Enable Logging', $pconfig['aliaslog'], $options_aliaslog ))->setHelp("Default: Enable
Select - Logging to Status: System Logs: FIREWALL ( Log )
This can be overriden by the 'Global Logging' Option in the General Tab."); // Print Advanced Firewall Rule Settings (Inbound and Outbound) section foreach (array( 'In' => 'Source', 'Out' => 'Destination') as $adv_mode => $adv_type) { $advmode = strtolower($adv_mode); $section = new Form_Section("Advanced {$adv_mode}bound Firewall Rule Settings", "adv{$advmode}boundsettings", COLLAPSIBLE|SEC_CLOSED); $section->addInput(new Form_StaticText( NULL, "Note:  In general, Auto-Rules are created as follows:
{$adv_mode}bound
'any' port, 'any' protocol, 'any' destination and 'any' gateway
Configuring the Adv. {$adv_mode}bound Rule settings, will allow for more customization of the {$adv_mode}bound Auto-Rules.")); $section->addInput(new Form_Checkbox( 'autoaddrnot_' . $advmode, "Invert {$adv_type}", NULL, $pconfig['autoaddrnot_' . $advmode] === 'on' ? true:false, 'on' ))->setHelp("Option to invert the sense of the match. ie - Not (!) {$adv_type} Address(es)"); $group = new Form_Group("Custom DST Port"); $group->add(new Form_Checkbox( 'autoports_' . $advmode, 'Custom DST Port', NULL, $pconfig['autoports_' . $advmode] === 'on' ? true:false, 'on' ))->setHelp('Enable') ->setWidth(2); $group->add(new Form_Input( 'aliasports_' . $advmode, 'Custom Port', 'text', $pconfig["aliasports_{$advmode}"] ))->setHelp("Click Here to add/edit Aliases Do not manually enter port numbers.
Do not use 'pfB_' in the Port Alias name." )->setWidth(8); $section->add($group); if ($adv_type == 'Source') { $custom_location = 'Destination'; } else { $custom_location = 'Source'; } $group = new Form_Group("Custom {$custom_location}"); $group->add(new Form_Checkbox( 'autoaddr_' . $advmode, "Custom {$custom_location}", NULL, $pconfig["autoaddr_{$advmode}"] === 'on' ? true:false, 'on' ))->setHelp('Enable')->setWidth(1); $group->add(new Form_Checkbox( 'autonot_' . $advmode, NULL, NULL, $pconfig["autonot_{$advmode}"] === 'on' ? true:false, 'on' ))->setHelp('Invert')->setWidth(1); $group->add(new Form_Input( 'aliasaddr_' . $advmode, "Custom {$custom_location}", 'text', $pconfig['aliasaddr_' . $advmode] ))->sethelp('Click Here to add/edit Aliases' . 'Do not manually enter Addresses(es).
Do not use \'pfB_\' in the \'IP Network Type\' Alias name.
' . "Select 'invert' to invert the sense of the match. ie - Not (!) {$custom_location} Address(es)" )->setWidth(8); $section->add($group); $group = new Form_Group('Custom Protocol'); $group->add(new Form_Select( 'autoproto_' . $advmode, NULL, $pconfig['autoproto_' . $advmode], $options_autoproto_in ))->setHelp("Default: any
Select the Protocol used for {$adv_mode}bound Firewall Rule(s).
Note: Do not use 'Any' with Adv. {$adv_mode}bound Rules as it will bypass these settings!"); $section->add($group); $group = new Form_Group('Custom Gateway'); $group->add(new Form_Select( 'agateway_' . $advmode, NULL, $pconfig['agateway_' . $advmode], $options_agateway_in ))->setHelp("Select alternate Gateway or keep 'default' setting."); $section->add($group); $form->add($section); } print($form); print_callout('

Setting changes are applied via CRON or \'Force Update|Reload\' only!

'); ?> EOF; // Update each Continent PHP file. if (!empty(pfb_filter($continent_en, PFB_FILTER_WORD, 'php'))) { @file_put_contents("/usr/local/www/pfblockerng/pfblockerng_{$continent_en}.php", $php_data, LOCK_EX); } // Unset Arrays unset(${'options4'}, ${'options6'}, $php_data); } // End foreach 'Six Continents and Proxy/Satellite' update PHP script builder process // Sort Countries IPv4 alphabetically and build XML