"pfBlockerAfrica", "Antartica" => "pfBlockerAntartica", "Asia" => "pfBlockerAsia", "Europe" => "pfBlockerEurope", "North America" => "pfBlockerNorthAmerica", "Oceania" => "pfBlockerOceania", "South America" => "pfBlockerSouthAmerica", "Top Spammers" => "pfBlockerTopSpammers"); #create rules vars and arrays $new_aliases=array(); $new_aliases_list=array(); $permit_inbound=array(); $permit_outbound=array(); $deny_inbound=array(); $deny_outbound=array(); $aliases_list=array(); #check if pfblocker is enabled or not. $deny_action_inbound=($pfblocker_config['inbound_deny_action']!= ""?$pfblocker_config['inbound_deny_action']:"block"); $deny_action_outbound=($pfblocker_config['outbound_deny_action']!= ""?$pfblocker_config['outbound_deny_action']:"reject"); $base_rule= array( "id" => "", "tag"=> "", "tagged"=> "", "max"=> "", "max-src-nodes"=>"", "max-src-conn"=> "", "max-src-states"=>"", "statetimeout"=>"", "statetype"=>"keep state", "os"=> ""); ############################################# # Assign Countries # ############################################# foreach ($continents as $continent => $pfb_alias){ ${$continent}=""; if (is_array($config['installedpackages']['pfblocker'.strtolower(preg_replace('/ /','',$continent))]['config'])){ $continent_config=$config['installedpackages']['pfblocker'.strtolower(preg_replace('/ /','',$continent))]['config'][0]; if ($continent_config['action'] != 'Disabled' && $continent_config['action'] != '' && $pfblocker_enable == "on"){ foreach (explode(",", $continent_config['countries']) as $iso){ #var_dump ($iso); if ($iso <> "" && file_exists($pfbdir.'/'.$iso.'.txt')){ ${$continent} .= file_get_contents($pfbdir.'/'.$iso.'.txt'); } } if($continent_config['countries'] != "" && $pfblocker_enable == "on"){ #write alias files file_put_contents($pfb_alias_dir.'/'.$pfb_alias.'.txt',${$continent},LOCK_EX); file_put_contents($pfsense_alias_dir.'/'.$pfb_alias.'.txt',${$continent}, LOCK_EX); #Create alias config $new_aliases_list[]=$pfb_alias; $new_aliases[]=array( "name"=> $pfb_alias, "url"=> $web_local.'?pfb='.$pfb_alias, "updatefreq"=> "32", "address"=>"", "descr"=> "pfBlocker country list", "type"=> "urltable", "detail"=> "DO NOT EDIT THIS ALIAS"); #Create rule if action permits switch($continent_config['action']){ case "Deny_Both": $rule = $base_rule; $rule["type"] = $deny_action_inbound; $rule["descr"]= "$pfb_alias auto rule"; $rule["source"]= array("address"=> $pfb_alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_inbound[]=$rule; case "Deny_Outbound": $rule = $base_rule; $rule["type"] = $deny_action_outbound; $rule["descr"]= "$pfb_alias auto rule"; $rule["source"]=array("any"=>""); $rule["destination"]= array("address"=> $pfb_alias); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_outbound[]=$rule; break; case "Deny_Inbound": $rule = $base_rule; $rule["type"] = $deny_action_inbound; $rule["descr"]= "$pfb_alias auto rule"; $rule["source"]= array("address"=> $pfb_alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_inbound[]=$rule; break; case "Permit_Outbound": $rule = $base_rule; $rule["type"] = "pass"; $rule["descr"]= "$pfb_alias auto rule"; $rule["source"]=array("any"=>""); $rule["destination"]= array("address"=> $pfb_alias); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $permit_outbound[]=$rule; break; case "Permit_Inbound": $rule = $base_rule; $rule["type"] = "pass"; $rule["descr"]= "$pfb_alias auto rule"; $rule["source"]= array("address"=> $pfb_alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $permit_inbound[]=$rule; break; } } } else{ #unlink continent list if any unlink_if_exists($pfb_alias_dir.'/'.$pfb_alias.'.txt'); } } #mark pfctl aliastable for cleanup if (!in_array($pfb_alias, $aliases_list)){ $aliases_list[]=$pfb_alias; } } ############################################# # Assign lists # ############################################# #print "
"; if($config['installedpackages']['pfblockerlists']['config'] != ""){ foreach($config['installedpackages']['pfblockerlists']['config'] as $list){ $alias="pfBlocker".preg_replace("/\W/","",$list['aliasname']); #print $list['aliasname'].$list['action']." ".$alias." ".$row['url']."
"; if ($alias != "pfBlocker" && $list['action'] != "" && $list['action'] != 'Disabled' && $pfblocker_enable == "on"){ #remove empty lists files if any if (is_array($list['row'])){ foreach ($list['row'] as $row){ #print $list['aliasname'].$list['action'].$list['cron']." ".$alias." ".$row['url']."$update_local
"; if ($row['url'] != ""){ $md5_url = md5($row['url']); if (file_exists($pfbdir."/".$md5_url.".txt")){ ${$alias}.= file_get_contents($pfbdir.'/'.$md5_url.'.txt'); } else{ if ($row['format'] == "gz"){ $url_list= gzfile($row['url']); } else{ $url_list= file($row['url']); } #extract range lists $new_file=""; if (is_array($url_list)){ foreach ($url_list as $line){ # CIDR format 192.168.0.0/16 if (preg_match("/(\d+\.\d+\.\d+\.\d+\/\d+)/",$line,$matches)){ ${$alias}.= $matches[1]."\n"; $new_file.= $matches[1]."\n"; } # Single ip addresses if (preg_match("/(\d+\.\d+\.\d+\.\d+)\s+/",$line,$matches)){ ${$alias}.= $matches[1]."/32\n"; $new_file.= $matches[1]."/32\n"; } # Network range 192.168.0.0-192.168.0.254 if (preg_match("/(\d+\.\d+\.\d+\.\d+)-(\d+\.\d+\.\d+\.\d+)/",$line,$matches)){ $cidr= pfblocker_Range2CIDR($matches[1],$matches[2]); if ($cidr != ""){ ${$alias}.= $cidr."\n"; $new_file.= $cidr."\n"; } } } } if ($new_file != ""){ file_put_contents($pfbdir.'/'.$md5_url.'.txt',$new_file, LOCK_EX); } } } } } #check custom network list if (pfb_text_area_decode($list['custom']) != ""){ ${$alias}.=pfb_text_area_decode($list['custom'])."\n"; } #save alias file if not empty if (${$alias} == ""){ unlink_if_exists($pfb_alias_dir.'/'.$alias.'.txt'); } else{ file_put_contents($pfb_alias_dir.'/'.$alias.'.txt',${$alias}, LOCK_EX); file_put_contents($pfsense_alias_dir.'/'.$alias.'.txt',${$alias}, LOCK_EX); #create alias $new_aliases_list[]=$alias; $new_aliases[]=array( "name"=> $alias, "url"=> $web_local.'?pfb='.$alias, "updatefreq"=> "32", "address"=>"", "descr"=> "pfBlocker user list", "type"=> "urltable", "detail"=> "DO NOT EDIT THIS ALIAS"); #Create rule if action permits switch($list['action']){ case "Deny_Both": $rule = $base_rule; $rule["type"] = $deny_action_inbound; $rule["descr"]= "$alias auto rule"; $rule["source"]= array("address"=> $alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_inbound[]=$rule; case "Deny_Outbound": $rule = $base_rule; $rule["type"] = $deny_action_outbound; $rule["descr"]= "$alias auto rule"; $rule["source"]=array("any"=>""); $rule["destination"]= array("address"=> $alias); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_outbound[]=$rule; break; case "Deny_Inbound": $rule = $base_rule; $rule["type"] = $deny_action_inbound; $rule["descr"]= "$alias auto rule"; $rule["source"]= array("address"=> $alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $deny_inbound[]=$rule; break; case "Permit_Outbound": $rule = $base_rule; $rule["type"] = "pass"; $rule["descr"]= "$alias auto rule"; $rule["source"]=array("any"=>""); $rule["destination"]= array("address"=> $alias); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $permit_outbound[]=$rule; break; case "Permit_Inbound": $rule = $base_rule; $rule["type"] = "pass"; $rule["descr"]= "$alias auto rule"; $rule["source"]= array("address"=> $alias); $rule["destination"]=array("any"=>""); if ($pfblocker_config['enable_log']){ $rule["log"]=""; } $permit_inbound[]=$rule; break; } } #mark pfctl aliastable for cleanup if (!in_array($alias, $aliases_list)){ $aliases_list[]=$alias; } } else{ #unlink previous pfblocker alias list if any unlink_if_exists($pfb_alias_dir.'/'.$alias.'.txt'); } } } #update pfsense alias table if (is_array($config['aliases']['alias'])){ $aliases=$config['aliases']['alias']; foreach($aliases as $cbalias){ if (preg_match("/pfBlocker/",$cbalias['name'])){ #mark pfctl aliastable for cleaning if (!in_array($cbalias['name'], $aliases_list)){ $aliases_list[]=$cbalias['name']; #mark aliastable for cleaning } #remove previous aliastable file if alias is not defined any more if (!in_array($cbalias['name'], $new_aliases_list)){ unlink_if_exists("/var/db/aliastables/".$cbalias['name'].".txt"); } } else{ $new_aliases[]= $cbalias; if (file_exists($pfb_alias_dir.'/'.$alias.'.txt') && $message ==""){ preg_match("/(\d+)/",exec("/usr/bin/wc -l ".$pfb_alias_dir.'/'.$alias.'.txt'),$matches); } if (($matches[1] * 2.1)>= $table_limit ){ #alias table too large $message= $alias .' alias table is too large. Reduce networks in list or increase "Firewall Maximum Table Entries" value to at least '. (int)($matches[1] * 2.1) .' in "system - advanced - Firewall/NAT".'; } } } } #apply new alias table to xml if ($message == ""){ $config['aliases']['alias']=$new_aliases; } #exit; ############################################# # Assign rules # ############################################# #print ""; #var_dump($permit_inbound); #var_dump($permit_outbound); #var_dump($deny_inbound); #var_dump($deny_outbound); #var_dump($pfblocker_config['inbound_interface']); #print count($deny_inbound) .count($deny_inbound); # Inbound filter options $inbound_interfaces = explode(",",$pfblocker_config['inbound_interface']); if (count($deny_inbound) > 0 || count($permit_inbound) > 0){ if($pfblocker_config['inbound_interface'] == ""){ $message="Unable to apply rules.Inbound Interface option not configured."; } if (in_array("lo0",$inbound_interfaces)){ $message="Floating rules are not implemented in pfBlocker yet, choose Inbound Interface other than loopback or change action to Alias only."; } } # Outbound filter options $outbound_interfaces = explode(",",$pfblocker_config['outbound_interface']); if (count($deny_outbound) > 0 || count($permit_outbound) > 0){ if($pfblocker_config['outbound_interface'] == ""){ $message="Unable to apply rules.Outbound Interface option not configured."; } if (in_array("lo0",$outbound_interfaces)){ $message="Floating rules are not implemented in pfBlocker yet, choose Outbound Interface other than loopback or change action to Alias only."; } } if ($message == ""){ $last_iface=""; $rules=$config['filter']['rule']; $new_rules=array(); # The assumption is that the rules in the config come in groups by interface then priority. # e.g. all rules for WAN (highest priority first), then for LAN then for OPT1 etc. # Note that floating rules (interface is "") can appear mixed in the list. foreach ($rules as $rule){ # If this next rule is for a non-blank interface, different to the previous interface, # then add any needed pfblocker rules to the interface. This puts pfblocker rules at the # top of the list for each interface, after any built-in rules (e.g. anti-lockout) if (($rule['interface'] != "") && ($rule['interface'] <> $last_iface)){ $last_iface = $rule['interface']; #apply pfblocker rules if enabled #Inbound foreach ($inbound_interfaces as $inbound_interface){ if ($inbound_interface==$last_iface){ #permit rules if (is_array($permit_inbound)){ foreach ($permit_inbound as $cb_rules){ $cb_rules['interface']=$rule['interface']; $new_rules[]=$cb_rules; } } #deny rules if (is_array($deny_inbound)){ foreach ($deny_inbound as $cb_rules){ $cb_rules['interface']=$rule['interface']; $new_rules[]=$cb_rules; } } } } #Outbound foreach ($outbound_interfaces as $outbound_interface){ if ($outbound_interface==$last_iface){ #permit rules if (is_array($permit_outbound)){ foreach ($permit_outbound as $cb_rules){ $cb_rules['interface']=$rule['interface']; $new_rules[]=$cb_rules; } } #deny rules if (is_array($deny_outbound)){ foreach ($deny_outbound as $cb_rules){ $cb_rules['interface']=$rule['interface']; $new_rules[]=$cb_rules; } } } } } #include all rules that are not from pfBlocker if (!preg_match("/pfBlocker.*rule/",$rule['descr']) && ($rule['interface'] != "" || $rule['floating']=="yes")){ $new_rules[]=$rule; } } $config['filter']['rule']=$new_rules; } if ($message == ""){ #check cron $cron_found=0; $cron_cmd="/usr/local/bin/php -q /usr/local/www/pfblocker.php cron"; if (is_array($config['cron']['item'])){ $new_cron=array(); foreach($config['cron']['item'] as $cron){ if (preg_match("/usr.local.www.pfblocker.php cron/",$cron["command"])){ #fix 0.1.4.6 missing php path if($cron["command"]==$cron_cmd && $pfblocker_enable == "on"){ $new_cron['item'][]=$cron; $cron_found=1; } } else{ $new_cron['item'][]=$cron; } } if ($cron_found == 0){ if($pfblocker_enable == "on"){ $new_cron['item'][]=array( "minute" => "0", "hour" => "*", "mday" => "*", "month" => "*", "wday" => "*", "who" => "root", "command"=> $cron_cmd); } $config['cron']=$new_cron; } } # to be removed in final version $aliases_list[]="pfBlockerInbound"; #remove previous version lists $aliases_list[]="pfBlockerOutbound"; #remove previous version lists $aliases_list[]="pfBlockerWL"; #remove previous version lists #exit; #update pfctrl tables foreach ($aliases_list as $table){ exec("/sbin/pfctl -t " . escapeshellarg($table) . " -T kill 2>&1", $result_pfb); } #uncheck donation and credits check box $config['installedpackages']['pfblocker']['config'][0]['donation']=""; $config['installedpackages']['pfblocker']['config'][0]['credits']=""; #write config write_config(); #update cron if ($cron_found == 0){ configure_cron(); } #load filter file after editing filter_configure(); #sync config pfblocker_sync_on_changes(); } else{ log_error("[pfBlocker] ".$message); file_notice("pfBlocker", $message, "pfblocker rule apply", ""); } conf_mount_ro(); } function pfblocker_validate_input($post, &$input_errors) { global $config; foreach ($post as $key => $value) { if (empty($value)) continue; if($key == "message_size_limit" && !is_numeric($value)) $input_errors[] = "Message size limit must be numeric."; if($key == "process_limit" && !is_numeric($value)) $input_errors[] = "Process limit must be numeric."; if($key == "freq" && (!preg_match("/^\d+(h|m|d)$/",$value) || $value == 0)) $input_errors[] = "A valid number with a time reference is required for the field 'Frequency'"; if (substr($key, 0, 2) == "dc" && !is_hostname($value)) $input_errors[] = "{$value} is not a valid host name."; if (substr($key, 0, 6) == "domain" && is_numeric(substr($key, 6))) { if (!is_domain($value)) $input_errors[] = "{$value} is not a valid domain name."; } else if (substr($key, 0, 12) == "mailserverip" && is_numeric(substr($key, 12))) { if (empty($post['domain' . substr($key, 12)])) $input_errors[] = "Domain for {$value} cannot be blank."; if (!is_ipaddr($value) && !is_hostname($value)) $input_errors[] = "{$value} is not a valid IP address or host name."; } } } function pfblocker_php_install_command() { include_once '/usr/local/www/pfblocker.php'; pfblocker_get_countries(); sync_package_pfblocker(); } function pfblocker_php_deinstall_command() { global $config; $config['installedpackages']['pfblocker']['config'][0]['enable_cb']=""; write_config(); sync_package_pfblocker(); } /* Uses XMLRPC to synchronize the changes to a remote node */ function pfblocker_sync_on_changes() { global $config, $g; log_error("[pfblocker] pfblocker_xmlrpc_sync.php is starting."); $synconchanges = $config['installedpackages']['pfblockersync']['config'][0]['synconchanges']; if(!$synconchanges) return; foreach ($config['installedpackages']['pfblockersync']['config'] as $rs ){ foreach($rs['row'] as $sh){ $sync_to_ip = $sh['ipaddress']; $password = $sh['password']; if($password && $sync_to_ip){ pfblocker_do_xmlrpc_sync($sync_to_ip, $password); } } } log_error("[pfblocker] pfblocker_xmlrpc_sync.php is ending."); } /* Do the actual XMLRPC sync */ function pfblocker_do_xmlrpc_sync($sync_to_ip, $password) { global $config, $g; if(!$password) return; if(!$sync_to_ip) return; $xmlrpc_sync_neighbor = $sync_to_ip; if($config['system']['webgui']['protocol'] != "") { $synchronizetoip = $config['system']['webgui']['protocol']; $synchronizetoip .= "://"; } $port = $config['system']['webgui']['port']; /* if port is empty lets rely on the protocol selection */ if($port == "") { if($config['system']['webgui']['protocol'] == "http"){ $port = "80"; } else{ $port = "443"; } } $synchronizetoip .= $sync_to_ip; /* xml will hold the sections to sync */ $xml = array(); $xml['pfblocker'] = $config['installedpackages']['pfblocker']; $xml['pfblockerlists'] = $config['installedpackages']['pfblockerlists']; $xml['pfblockertopspammers'] = $config['installedpackages']['pfblockertopspammers']; $xml['pfblockerafrica'] = $config['installedpackages']['pfblockerafrica']; $xml['pfblockerantartica'] = $config['installedpackages']['pfblockerantartica']; $xml['pfblockerasia'] = $config['installedpackages']['pfblockerasia']; $xml['pfblockereurope'] = $config['installedpackages']['pfblockereurope']; $xml['pfblockernorthamerica'] = $config['installedpackages']['pfblockernorthamerica']; $xml['pfblockeroceania'] = $config['installedpackages']['pfblockeroceania']; $xml['pfblockersouthamerica'] = $config['installedpackages']['pfblockersouthamerica']; /* assemble xmlrpc payload */ $params = array( XML_RPC_encode($password), XML_RPC_encode($xml) ); /* set a few variables needed for sync code borrowed from filter.inc */ $url = $synchronizetoip; log_error("Beginning pfblocker XMLRPC sync to {$url}:{$port}."); $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials('admin', $password); if($g['debug']){ $cli->setDebug(1); } /* send our XMLRPC message and timeout after 250 seconds */ $resp = $cli->send($msg, "250"); if(!$resp) { $error = "A communications error occurred while attempting pfblocker XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "pfblocker Settings Sync", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, "250"); $error = "An error code was received while attempting pfblocker XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "pfblocker Settings Sync", ""); } else { log_error("pfblocker XMLRPC sync successfully completed with {$url}:{$port}."); } /* tell pfblocker to reload our settings on the destionation sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/pkg/pfblocker.inc');\n"; $execcmd .= "sync_package_pfblocker();"; /* assemble xmlrpc payload */ $params = array( XML_RPC_encode($password), XML_RPC_encode($execcmd) ); log_error("pfblocker XMLRPC reload data {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials('admin', $password); $resp = $cli->send($msg, "250"); if(!$resp) { $error = "A communications error occurred while attempting pfblocker XMLRPC sync with {$url}:{$port} (exec_php)."; log_error($error); file_notice("sync_settings", $error, "pfblocker Settings Sync", ""); } elseif($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, "250"); $error = "An error code was received while attempting pfblocker XMLRPC exec with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "pfblocker Settings Sync", ""); } else { log_error("pfblocker XMLRPC reload data success with {$url}:{$port} (exec_php)."); } } ?>