From edc40978997efd49422da71169fc177e7b40d8f2 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Fri, 30 Sep 2016 18:14:02 +0200 Subject: [PATCH] work on https://github.com/opnsense/core/issues/993 simple start, wrap anchor registration into plugin system, use miniupnpd as an example. use registerAnchor() to register new anchors for pf into the main firewall script, we've hooked head/tail options and the different anchor types. anchorToText() will extract the registered anchors back for the specified types and place in the script (head/tail) in text format for pf. our new codebase was already hooked using legacy_bindings.inc, no additional includes needed to construct \OPNsense\Firewall\Plugin(). --- src/etc/inc/filter.inc | 18 +++-- src/etc/inc/plugins.inc | 13 +++ src/etc/inc/plugins.inc.d/miniupnpd.inc | 35 ++++++++ .../app/library/OPNsense/Firewall/Plugin.php | 80 +++++++++++++++++++ 4 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/etc/inc/plugins.inc.d/miniupnpd.inc create mode 100644 src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php diff --git a/src/etc/inc/filter.inc b/src/etc/inc/filter.inc index a9159638d..7eae1afde 100644 --- a/src/etc/inc/filter.inc +++ b/src/etc/inc/filter.inc @@ -372,6 +372,13 @@ function filter_configure_sync() $FilterIflist = filter_generate_optcfg_array(); + // initialize fw plugin object + $fw = new \OPNsense\Firewall\Plugin(); + + if (function_exists('plugins_firewall')) { + plugins_firewall($fw); + } + /* Use filter lock to not allow concurrent filter reloads during this run. */ $filterlck = lock('filter', LOCK_EX); @@ -467,8 +474,12 @@ function filter_configure_sync() update_filter_reload_status(gettext("Setting up SCRUB information")); $rules .= filter_generate_scrubing($FilterIflist); $rules .= "\n"; + $rules .= $fw->anchorToText('nat,binat,rdr', 'head'); $rules .= "{$natrules}\n"; + $rules .= $fw->anchorToText('nat,binat,rdr', 'tail'); + $rules .= $fw->anchorToText('fw', 'head'); $rules .= "{$pfrules}\n"; + $rules .= $fw->anchorToText('fw', 'tail'); unset($aliases, $gateways, $natrules, $pfrules); @@ -1888,9 +1899,6 @@ function filter_nat_rules_generate(&$FilterIflist) } } - $natrules .= "\n# UPnP\n"; - $natrules .= "rdr-anchor \"miniupnpd\"\n"; - if (!empty($reflection_txt)) { $natrules .= "\n# Reflection redirects and NAT for 1:1 mappings\n" . $reflection_txt; } @@ -2991,10 +2999,6 @@ EOD; update_filter_reload_status("Creating uPNP rules..."); if (isset($config['installedpackages']['miniupnpd']['config'][0])) { - if (isset($config['installedpackages']['miniupnpd']['config'][0]['enable'])) { - $ipfrules .= "anchor \"miniupnpd\"\n"; - } - if (isset($config['installedpackages']['miniupnpd'][0]['config']) && is_array($config['installedpackages']['miniupnpd'][0]['config'])) { $upnp_interfaces = explode(",", $config['installedpackages']['miniupnpd'][0]['config']['iface_array']); foreach($upnp_interfaces as $upnp_if) { diff --git a/src/etc/inc/plugins.inc b/src/etc/inc/plugins.inc index ba1ddf36c..0121df872 100644 --- a/src/etc/inc/plugins.inc +++ b/src/etc/inc/plugins.inc @@ -149,6 +149,19 @@ function plugins_interfaces() } } +function plugins_firewall($fw) +{ + foreach (plugins_scan() as $name => $path) { + require_once $path; + $func = sprintf('%s_firewall', $name); + if (function_exists($func)) { + $func($fw); + } + } + + return $fw; +} + function plugins_configure() { foreach (plugins_scan() as $name => $path) { diff --git a/src/etc/inc/plugins.inc.d/miniupnpd.inc b/src/etc/inc/plugins.inc.d/miniupnpd.inc new file mode 100644 index 000000000..c654ee074 --- /dev/null +++ b/src/etc/inc/plugins.inc.d/miniupnpd.inc @@ -0,0 +1,35 @@ +registerAnchor("miniupnpd/*", "rdr"); + $fw->registerAnchor("miniupnpd/*", "fw"); + } +} diff --git a/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php b/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php new file mode 100644 index 000000000..31309b0bc --- /dev/null +++ b/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php @@ -0,0 +1,80 @@ +anchors)); + $this->anchors[$anchorKey] = $name; + ksort($this->anchors); + } + + /** + * fetch anchors as text (pf ruleset part) + * @param $types anchor types (fw for filter, other options are nat,rdr,binat. comma seperated) + * @param $priority sort order from low to high + * @return string + */ + public function anchorToText($types="fw", $placement="tail") + { + $result = ""; + foreach (explode(',', $types) as $type) { + foreach ($this->anchors as $anchorKey => $anchor) { + if (strpos($anchorKey, "{$type}.{$placement}") === 0) { + $result .= $type == "fw" ? "" : "{$type}-"; + $result .= "anchor \"{$anchor}\"\n"; + } + } + } + return $result; + } +}