From 3085e4d18f1e8a644b511adf340948b14bb50c47 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Fri, 28 Oct 2016 20:14:29 +0200 Subject: [PATCH] (plugins / firewall) first steps in moving static firewall rules to plugin registrations. Te idea is simple, start parsing rules in a uniform way, so we're eventually able to display and alter all auto generated rules. Because of the large set of legacy code rules, we're going to migrate step by step, leaving the current setup intact. --- src/etc/inc/filter.inc | 18 ++--- src/etc/inc/plugins.inc.d/core_fw.inc | 18 +++++ .../library/OPNsense/Firewall/FilterRule.php | 66 ++++++++++++++++--- .../app/library/OPNsense/Firewall/Plugin.php | 5 +- 4 files changed, 84 insertions(+), 23 deletions(-) create mode 100644 src/etc/inc/plugins.inc.d/core_fw.inc diff --git a/src/etc/inc/filter.inc b/src/etc/inc/filter.inc index 133d06c0d..f791dd647 100644 --- a/src/etc/inc/filter.inc +++ b/src/etc/inc/filter.inc @@ -374,6 +374,7 @@ function filter_configure_sync() // initialize fw plugin object $fw = new \OPNsense\Firewall\Plugin(); + $fw->setInterfaceMapping($FilterIflist); if (function_exists('plugins_firewall')) { plugins_firewall($fw); @@ -478,6 +479,7 @@ function filter_configure_sync() $rules .= $fw->anchorToText('nat,binat,rdr', 'tail'); $rules .= $fw->anchorToText('fw', 'head'); $rules .= "anchor \"relayd/*\"\n"; // relayd + $rules .= $fw->outputFilterRules(); $rules .= "{$pfrules}\n"; $rules .= $fw->anchorToText('fw', 'tail'); @@ -2494,19 +2496,9 @@ function filter_rules_generate(&$FilterIflist) # BEGIN OF firewall rules /* default block logging? */ - $log = array("block"=>null,"pass"=>null); - if (!isset($config['syslog']['nologdefaultblock'])) { - $log['block'] = "log"; - } - if (!isset($config['syslog']['nologdefaultpass'])) { - $log['pass'] = "log"; - } - - if (!isset($config['system']['ipv6allow'])) { - $ipfrules .= "\n# Block all IPv6 except loopback traffic\n"; - $ipfrules .= "pass {$log['pass']} quick on \$loopback inet6\n"; - $ipfrules .= "block {$log['block']} quick inet6 all label \"Block all IPv6\"\n"; - } + $log = array(); + $log['block'] = !isset($config['syslog']['nologdefaultblock']) ? "log" : ""; + $log['pass'] = !isset($config['syslog']['nologdefaultpass']) ? "log" : ""; $ipfrules .= <<registerFilterRule(0, + array('type'=>'pass','log'=>$log_pass, 'interface' => 'loopback', 'ipprotocol'=>'inet6') + ); + $fw->registerFilterRule(0, + array('type'=>'block','log'=>$log_block, 'ipprotocol'=>'inet6', 'label' => 'Block all IPv6') + ); + } +} diff --git a/src/opnsense/mvc/app/library/OPNsense/Firewall/FilterRule.php b/src/opnsense/mvc/app/library/OPNsense/Firewall/FilterRule.php index c841a9414..0ad78a9b1 100644 --- a/src/opnsense/mvc/app/library/OPNsense/Firewall/FilterRule.php +++ b/src/opnsense/mvc/app/library/OPNsense/Firewall/FilterRule.php @@ -41,8 +41,12 @@ class FilterRule private $procorder = array( 'disabled' => 'parseIsComment', 'type' => 'parseType', + 'log' => 'parseBool,log', + 'quick' => 'parseBool,quick', + 'interface' => 'parseInterface', 'ipprotocol' => 'parsePlain', - 'interface' => 'parseInterface' + 'protocol' => 'parseReplaceSimple,tcp/udp:{tcp udp}', + 'label' => 'parsePlain,label ","' ); /** @@ -60,9 +64,26 @@ class FilterRule * @param string $value field value * @return string */ - private function parsePlain($value) + private function parsePlain($value, $prefix="", $suffix="") { - return empty($value) ? "" : $value . " "; + return empty($value) ? "" : $prefix . $value . $suffix . " "; + } + + /** + * parse data, use replace map + * @param string $value field value + * @param string $map + * @return string + */ + private function parseReplaceSimple($value, $map) + { + foreach (explode('|', $map) as $item) { + $tmp = explode(':', $item); + if ($tmp[0] == $value) { + return $tmp[1] . " "; + } + } + return $value . " "; } /** @@ -89,10 +110,26 @@ class FilterRule */ private function parseInterface($value) { - if (empty($this->interfaceMapping[$value]['if'])) { - return "##{$value}##"; + if (empty($value)) { + return ""; + } elseif (empty($this->interfaceMapping[$value]['if'])) { + return "on ##{$value}## "; } else { - return $this->interfaceMapping[$value]['if']." "; + return "on ". $this->interfaceMapping[$value]['if']." "; + } + } + + /** + * parse boolean, return text from $valueTrue / $valueFalse + * @param string $value field value + * @return string + */ + private function parseBool($value, $valueTrue, $valueFalse="") + { + if (!empty($value)) { + return !empty($valueTrue) ? $valueTrue . " " : ""; + } else { + return !empty($valueFalse) ? $valueFalse . " " : ""; } } @@ -117,10 +154,14 @@ class FilterRule $tmp = $this->rule; $tmp['interface'] = $interface; $tmp['ipprotocol'] = $ipproto; - if (empty($this->interfaceMapping[$interface]['if'])) { - // disable rule when interface not found + // disable rule when interface not found + if (!empty($interface) && empty($this->interfaceMapping[$interface]['if'])) { $tmp['disabled'] = true; } + if (!isset($tmp['quick'])) { + // all rules are quick by default except floating + $tmp['quick'] = !isset($rule['floating']) ? true : false ; + } $result[] = $tmp; } } @@ -147,7 +188,14 @@ class FilterRule $ruleTxt = ''; foreach ($this->fetchActualRules() as $rule) { foreach ($this->procorder as $tag => $handle) { - $ruleTxt .= $this->$handle(isset($rule[$tag]) ? $rule[$tag] : null); + $tmp = explode(',', $handle); + $method = $tmp[0]; + $args = array(isset($rule[$tag]) ? $rule[$tag] : null); + if (count($tmp) > 1) { + array_shift($tmp); + $args = array_merge($args, $tmp); + } + $ruleTxt .= call_user_func_array(array($this,$method), $args); } $ruleTxt .= "\n"; } diff --git a/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php b/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php index c130eb0c4..bb775a878 100644 --- a/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php +++ b/src/opnsense/mvc/app/library/OPNsense/Firewall/Plugin.php @@ -38,13 +38,16 @@ class Plugin private $anchors = array(); private $filterRules = array(); private $interfaceMapping ; + private $interfaceStaticMapping; /** * init firewall plugin component */ public function __construct() { + // set static mappings $this->interfaceMapping = array(); + $this->interfaceMapping['loopback'] = array('if' => 'lo0'); } /** @@ -53,7 +56,7 @@ class Plugin */ public function setInterfaceMapping(&$mapping) { - $this->interfaceMapping = $mapping; + $this->interfaceMapping = array_merge($this->interfaceMapping, $mapping); } /**