Package development - firewall rules
-
I'm developing a pfSense package and I would like to generate one or more firewall rules from my package. I used the existing packages as an example and found the XML element '<filter_rules_needed>'. It looks like this is what is need (correct me when I'm wrong!). But this method is never being called (I think) by PFSense.
My package config XML:
<packagegui><description>My package</description> <name>MyPackage</name> <version>0.1</version> <title>My Package</title> <include_file>/usr/local/pkg/mypackage.inc</include_file> ... <filter_rules_needed>mypackage_generate_rules</filter_rules_needed></packagegui>
My package include file:
require_once('util.inc'); require_once('filter.inc'); require_once('interfaces.inc'); require_once('pfsense-utils.inc'); require_once('service-utils.inc'); function mypackage_generate_rules($sType) { global $config; log_error("mypackage_generate_rules: ".$sType); $aInterfaces = explode(',', $config['installedpackages']['mypackage']['config'][0]['serverinterfaces']); $aInterfaces = array_map('convert_friendly_interface_to_real_interface_name', $aInterfaces); log_error("interfaces: ".print_r($aInterfaces, true)); $sRules = ""; switch($sType) { case 'nat': // Nothing here yet. break; case 'filter': case 'rule': foreach ($aInterfaces as $sInterface) { $sRules .= "pass quick on {$sInterface} proto upd to port 1234 flags S/SA keep state label \"MyPackage: Test\"\n"; } break; default: break; } return $sRules; }
PFSense doesn't create the rule as far as I can see. Also nothing in the logs; I would expect something like: 'mypackage_generate_rules' as I call log_error in this method.
Anyone suggestions? Thanks!</filter_rules_needed>
-
I finally figured out what went wrong. There where 2 issues.
-
The XML tag isn't used by PFSense at all, below a copy of the method PFSense uses to generate the rules (https://github.com/bsdperimeter/pfsense/blob/master/etc/inc/filter.inc).
-
You should not use a subdirectory for your package; leave it in '/usr/local/pkg'. Otherwise the system won't find your 'generate_rules' function.
function discover_pkg_rules($ruletype) { global $config, $g, $aliases; /* Bail if there is no pkg directory, or if the package files might be out of sync. */ if(!is_dir("/usr/local/pkg") || file_exists('/conf/needs_package_sync')) return ""; $rules = ""; $files = glob("/usr/local/pkg/*.inc"); foreach($files as $pkg_inc) { update_filter_reload_status(sprintf(gettext('Checking for %1$s PF hooks in package %2$s'), $ruletype, $pkg_inc)); $pkg = basename($pkg_inc, ".inc"); $pkg_generate_rules = "{$pkg}_generate_rules"; if (!function_exists($pkg_generate_rules)) require_once($pkg_inc); if(function_exists($pkg_generate_rules)) { update_filter_reload_status(sprintf(gettext('Processing early %1$s rules for package %2$s'), $ruletype, $pkg_inc)); $tmprules = $pkg_generate_rules("$ruletype"); file_put_contents("{$g['tmp_path']}/rules.test.packages", $aliases . $tmprules); $status = mwexec("/sbin/pfctl -nf {$g['tmp_path']}/rules.test.packages"); if ($status <> 0) { $errorrules = sprintf(gettext("There was an error while parsing the package filter rules for %s."), $pkg_inc) . "\n"; log_error($errorrules); file_put_contents("{$g['tmp_path']}/rules.packages.{$pkg}", "#{$errorrules}\n{$tmprules}\n"); continue; } $rules .= $tmprules; } } return $rules; }
I hope that this info will help someone figuring it out a lot faster than I did ;)
-