From 64668771d5f14fc4b68fff382d166238c164bdde Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Sat, 15 Jan 2022 12:48:48 +0100 Subject: firewall: policy: T4178: Migrate and refactor tcp flags * Add support for ECN and CWR flags --- smoketest/scripts/cli/test_firewall.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'smoketest/scripts/cli/test_firewall.py') diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 2b3b354ba..c70743a9f 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -53,7 +53,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) @@ -61,7 +61,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ ['iifname "eth0"', 'jump smoketest'], - ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'tcp dport { 53, 123 }', 'return'], + ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'th dport { 53, 123 }', 'return'], ] nftables_output = cmd('sudo nft list table ip filter') @@ -72,7 +72,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): if all(item in line for item in search): matched = True break - self.assertTrue(matched) + self.assertTrue(matched, msg=search) def test_basic_rules(self): self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop']) @@ -80,8 +80,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'address', '172.16.20.10']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'reject']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'protocol', 'tcp']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'destination', 'port', '8888']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) @@ -90,7 +92,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ ['iifname "eth0"', 'jump smoketest'], ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'], - ['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'reject'], + ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'], ['smoketest default-action', 'drop'] ] @@ -102,7 +104,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): if all(item in line for item in search): matched = True break - self.assertTrue(matched) + self.assertTrue(matched, msg=search) def test_basic_rules_ipv6(self): self.cli_set(['firewall', 'ipv6-name', 'v6-smoketest', 'default-action', 'drop']) @@ -132,7 +134,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): if all(item in line for item in search): matched = True break - self.assertTrue(matched) + self.assertTrue(matched, msg=search) def test_state_policy(self): self.cli_set(['firewall', 'state-policy', 'established', 'action', 'accept']) -- cgit v1.2.3 From 0a5a78621b2b28f06af1f40c10ee8bb880f860a0 Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Tue, 18 Jan 2022 15:29:03 +0100 Subject: firewall: T3560: Add support for MAC address groups --- data/templates/firewall/nftables-defines.tmpl | 5 ++++ interface-definitions/firewall.xml.in | 21 +++++++++++++++++ .../include/firewall/common-rule.xml.i | 3 +++ .../include/firewall/mac-group.xml.i | 10 ++++++++ .../firewall/source-destination-group-ipv6.xml.i | 1 + .../firewall/source-destination-group.xml.i | 1 + .../include/policy/route-common-rule-ipv6.xml.i | 3 +++ .../include/policy/route-common-rule.xml.i | 3 +++ python/vyos/firewall.py | 3 +++ smoketest/scripts/cli/test_firewall.py | 4 ++++ src/op_mode/firewall.py | 2 ++ src/validators/mac-address-firewall | 27 ++++++++++++++++++++++ 12 files changed, 83 insertions(+) create mode 100644 interface-definitions/include/firewall/mac-group.xml.i create mode 100755 src/validators/mac-address-firewall (limited to 'smoketest/scripts/cli/test_firewall.py') diff --git a/data/templates/firewall/nftables-defines.tmpl b/data/templates/firewall/nftables-defines.tmpl index 3578a9dc5..d9eb7c199 100644 --- a/data/templates/firewall/nftables-defines.tmpl +++ b/data/templates/firewall/nftables-defines.tmpl @@ -9,6 +9,11 @@ define A_{{ group_name }} = { {{ group_conf.address | join(",") }} } define A6_{{ group_name }} = { {{ group_conf.address | join(",") }} } {% endfor %} {% endif %} +{% if group.mac_group is defined %} +{% for group_name, group_conf in group.mac_group.items() %} +define M_{{ group_name }} = { {{ group_conf.mac_address | join(",") }} } +{% endfor %} +{% endif %} {% if group.network_group is defined %} {% for group_name, group_conf in group.network_group.items() %} define N_{{ group_name }} = { {{ group_conf.network | join(",") }} } diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index fd98ae138..987ccaca6 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -144,6 +144,27 @@ + + + Firewall mac-group + + + #include + + + Mac-group member + + <MAC address> + MAC address to match + + + + + + + + + Firewall network-group diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index 5ffbd639c..521fe54f2 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -176,6 +176,9 @@ !<MAC address> Match everything except the specified MAC address + + + #include diff --git a/interface-definitions/include/firewall/mac-group.xml.i b/interface-definitions/include/firewall/mac-group.xml.i new file mode 100644 index 000000000..dbce3fc88 --- /dev/null +++ b/interface-definitions/include/firewall/mac-group.xml.i @@ -0,0 +1,10 @@ + + + + Group of MAC addresses + + firewall group mac-group + + + + \ No newline at end of file diff --git a/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i b/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i index 7815b78d4..c2cc7edb3 100644 --- a/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i +++ b/interface-definitions/include/firewall/source-destination-group-ipv6.xml.i @@ -12,6 +12,7 @@ + #include Group of networks diff --git a/interface-definitions/include/firewall/source-destination-group.xml.i b/interface-definitions/include/firewall/source-destination-group.xml.i index 9a9bed0fe..ab11e89e9 100644 --- a/interface-definitions/include/firewall/source-destination-group.xml.i +++ b/interface-definitions/include/firewall/source-destination-group.xml.i @@ -12,6 +12,7 @@ + #include Group of networks diff --git a/interface-definitions/include/policy/route-common-rule-ipv6.xml.i b/interface-definitions/include/policy/route-common-rule-ipv6.xml.i index 735edbd48..406125e55 100644 --- a/interface-definitions/include/policy/route-common-rule-ipv6.xml.i +++ b/interface-definitions/include/policy/route-common-rule-ipv6.xml.i @@ -232,6 +232,9 @@ !<MAC address> Match everything except the specified MAC address + + + #include diff --git a/interface-definitions/include/policy/route-common-rule.xml.i b/interface-definitions/include/policy/route-common-rule.xml.i index 4452f78fc..33c4ba77c 100644 --- a/interface-definitions/include/policy/route-common-rule.xml.i +++ b/interface-definitions/include/policy/route-common-rule.xml.i @@ -232,6 +232,9 @@ !<MAC address> Match everything except the specified MAC address + + + #include diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index ad84393df..2ab78ff18 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -108,6 +108,9 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): elif 'network_group' in group: group_name = group['network_group'] output.append(f'{ip_name} {prefix}addr $N{def_suffix}_{group_name}') + if 'mac_group' in group: + group_name = group['mac_group'] + output.append(f'ether {prefix}addr $M_{group_name}') if 'port_group' in group: proto = rule_conf['protocol'] group_name = group['port_group'] diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index c70743a9f..6b74e6c92 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -46,6 +46,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_groups(self): + self.cli_set(['firewall', 'group', 'mac-group', 'smoketest_mac', 'mac-address', '00:01:02:03:04:05']) self.cli_set(['firewall', 'group', 'network-group', 'smoketest_network', 'network', '172.16.99.0/24']) self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '53']) self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '123']) @@ -54,6 +55,8 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'address', '172.16.10.10']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'group', 'mac-group', 'smoketest_mac']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) @@ -62,6 +65,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): nftables_search = [ ['iifname "eth0"', 'jump smoketest'], ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'th dport { 53, 123 }', 'return'], + ['ether saddr { 00:01:02:03:04:05 }', 'return'] ] nftables_output = cmd('sudo nft list table ip filter') diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index 030a9b19a..b6bb5b802 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -272,6 +272,8 @@ def show_firewall_group(name=None): row.append("\n".join(sorted(group_conf['address'], key=ipaddress.ip_address))) elif 'network' in group_conf: row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network))) + elif 'mac_address' in group_conf: + row.append("\n".join(sorted(group_conf['mac_address']))) elif 'port' in group_conf: row.append("\n".join(sorted(group_conf['port']))) else: diff --git a/src/validators/mac-address-firewall b/src/validators/mac-address-firewall new file mode 100755 index 000000000..70551f86d --- /dev/null +++ b/src/validators/mac-address-firewall @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018-2022 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import re +import sys + +pattern = "^!?([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" + +if __name__ == '__main__': + if len(sys.argv) != 2: + sys.exit(1) + if not re.match(pattern, sys.argv[1]): + sys.exit(1) + sys.exit(0) -- cgit v1.2.3 From ed67750b94e8bc779ec0e2cf6d568a3f7292de13 Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Sat, 29 Jan 2022 13:18:28 +0100 Subject: firewall: T4218: Adds a prefix to all user defined chains --- data/templates/firewall/nftables.tmpl | 4 ++-- data/templates/zone_policy/nftables.tmpl | 12 ++++++------ python/vyos/template.py | 3 ++- smoketest/scripts/cli/test_firewall.py | 6 +++--- smoketest/scripts/cli/test_zone_policy.py | 4 ++-- src/conf_mode/firewall-interface.py | 11 +++++++---- src/conf_mode/firewall.py | 7 +++++-- src/op_mode/firewall.py | 3 ++- 8 files changed, 29 insertions(+), 21 deletions(-) (limited to 'smoketest/scripts/cli/test_firewall.py') diff --git a/data/templates/firewall/nftables.tmpl b/data/templates/firewall/nftables.tmpl index 33c821e84..468a5a32f 100644 --- a/data/templates/firewall/nftables.tmpl +++ b/data/templates/firewall/nftables.tmpl @@ -32,7 +32,7 @@ table ip filter { {% endif %} {% if name is defined %} {% for name_text, conf in name.items() %} - chain {{ name_text }} { + chain NAME_{{ name_text }} { {% if conf.rule is defined %} {% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not defined %} {{ rule_conf | nft_rule(name_text, rule_id) }} @@ -82,7 +82,7 @@ table ip6 filter { {% endif %} {% if ipv6_name is defined %} {% for name_text, conf in ipv6_name.items() %} - chain {{ name_text }} { + chain NAME6_{{ name_text }} { {% if conf.rule is defined %} {% for rule_id, rule_conf in conf.rule.items() if rule_conf.disable is not defined %} {{ rule_conf | nft_rule(name_text, rule_id, 'ip6') }} diff --git a/data/templates/zone_policy/nftables.tmpl b/data/templates/zone_policy/nftables.tmpl index e59208a0d..093da6bd8 100644 --- a/data/templates/zone_policy/nftables.tmpl +++ b/data/templates/zone_policy/nftables.tmpl @@ -13,7 +13,7 @@ table ip filter { chain VZONE_{{ zone_name }}_IN { iifname lo counter return {% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.name is defined %} - iifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} iifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endfor %} counter {{ zone_conf.default_action if zone_conf.default_action is defined else 'drop' }} @@ -21,7 +21,7 @@ table ip filter { chain VZONE_{{ zone_name }}_OUT { oifname lo counter return {% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall.name is defined %} - oifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.name }} + oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} oifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endfor %} counter {{ zone_conf.default_action if zone_conf.default_action is defined else 'drop' }} @@ -34,7 +34,7 @@ table ip filter { {% endif %} {% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.name is defined %} {% if zone[from_zone].local_zone is not defined %} - iifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME_{{ from_conf.firewall.name }} iifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endif %} {% endfor %} @@ -50,7 +50,7 @@ table ip6 filter { chain VZONE6_{{ zone_name }}_IN { iifname lo counter return {% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.ipv6_name is defined %} - iifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.ipv6_name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} iifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endfor %} counter {{ zone_conf.default_action if zone_conf.default_action is defined else 'drop' }} @@ -58,7 +58,7 @@ table ip6 filter { chain VZONE6_{{ zone_name }}_OUT { oifname lo counter return {% for from_zone, from_conf in zone_conf.from_local.items() if from_conf.firewall.ipv6_name is defined %} - oifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.ipv6_name }} + oifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} oifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endfor %} counter {{ zone_conf.default_action if zone_conf.default_action is defined else 'drop' }} @@ -71,7 +71,7 @@ table ip6 filter { {% endif %} {% for from_zone, from_conf in zone_conf.from.items() if from_conf.firewall.ipv6_name is defined %} {% if zone[from_zone].local_zone is not defined %} - iifname { {{ zone[from_zone].interface | join(",") }} } counter jump {{ from_conf.firewall.ipv6_name }} + iifname { {{ zone[from_zone].interface | join(",") }} } counter jump NAME6_{{ from_conf.firewall.ipv6_name }} iifname { {{ zone[from_zone].interface | join(",") }} } counter return {% endif %} {% endfor %} diff --git a/python/vyos/template.py b/python/vyos/template.py index 633b28ade..3675aef5d 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -548,6 +548,7 @@ def nft_intra_zone_action(zone_conf, ipv6=False): if 'intra_zone_filtering' in zone_conf: intra_zone = zone_conf['intra_zone_filtering'] fw_name = 'ipv6_name' if ipv6 else 'name' + name_prefix = 'NAME6_' if ipv6 else 'NAME_' if 'action' in intra_zone: if intra_zone['action'] == 'accept': @@ -555,5 +556,5 @@ def nft_intra_zone_action(zone_conf, ipv6=False): return intra_zone['action'] elif dict_search_args(intra_zone, 'firewall', fw_name): name = dict_search_args(intra_zone, 'firewall', fw_name) - return f'jump {name}' + return f'jump {name_prefix}{name}' return 'return' diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 6b74e6c92..ecc0c29a0 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -63,7 +63,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_commit() nftables_search = [ - ['iifname "eth0"', 'jump smoketest'], + ['iifname "eth0"', 'jump NAME_smoketest'], ['ip saddr { 172.16.99.0/24 }', 'ip daddr 172.16.10.10', 'th dport { 53, 123 }', 'return'], ['ether saddr { 00:01:02:03:04:05 }', 'return'] ] @@ -94,7 +94,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_commit() nftables_search = [ - ['iifname "eth0"', 'jump smoketest'], + ['iifname "eth0"', 'jump NAME_smoketest'], ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'], ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'], ['smoketest default-action', 'drop'] @@ -124,7 +124,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_commit() nftables_search = [ - ['iifname "eth0"', 'jump v6-smoketest'], + ['iifname "eth0"', 'jump NAME6_v6-smoketest'], ['saddr 2002::1', 'daddr 2002::1:1', 'return'], ['meta l4proto { tcp, udp }', 'th dport { 8888 }', 'reject'], ['smoketest default-action', 'drop'] diff --git a/smoketest/scripts/cli/test_zone_policy.py b/smoketest/scripts/cli/test_zone_policy.py index c0af6164b..00dfe0182 100755 --- a/smoketest/scripts/cli/test_zone_policy.py +++ b/smoketest/scripts/cli/test_zone_policy.py @@ -44,8 +44,8 @@ class TestZonePolicy(VyOSUnitTestSHIM.TestCase): ['oifname { "eth0" }', 'jump VZONE_smoketest-eth0'], ['jump VZONE_smoketest-local_IN'], ['jump VZONE_smoketest-local_OUT'], - ['iifname { "eth0" }', 'jump smoketest'], - ['oifname { "eth0" }', 'jump smoketest'] + ['iifname { "eth0" }', 'jump NAME_smoketest'], + ['oifname { "eth0" }', 'jump NAME_smoketest'] ] nftables_output = cmd('sudo nft list table ip filter') diff --git a/src/conf_mode/firewall-interface.py b/src/conf_mode/firewall-interface.py index a7442ecbd..9a5d278e9 100755 --- a/src/conf_mode/firewall-interface.py +++ b/src/conf_mode/firewall-interface.py @@ -31,6 +31,9 @@ from vyos import ConfigError from vyos import airbag airbag.enable() +NAME_PREFIX = 'NAME_' +NAME6_PREFIX = 'NAME6_' + NFT_CHAINS = { 'in': 'VYOS_FW_FORWARD', 'out': 'VYOS_FW_FORWARD', @@ -127,7 +130,7 @@ def apply(if_firewall): name = dict_search_args(if_firewall, direction, 'name') if name: - rule_exists = cleanup_rule('ip filter', chain, if_prefix, ifname, name) + rule_exists = cleanup_rule('ip filter', chain, if_prefix, ifname, f'{NAME_PREFIX}{name}') if not rule_exists: rule_action = 'insert' @@ -138,13 +141,13 @@ def apply(if_firewall): rule_action = 'add' rule_prefix = f'position {handle}' - run(f'nft {rule_action} rule ip filter {chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {name}') + run(f'nft {rule_action} rule ip filter {chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {NAME_PREFIX}{name}') else: cleanup_rule('ip filter', chain, if_prefix, ifname) ipv6_name = dict_search_args(if_firewall, direction, 'ipv6_name') if ipv6_name: - rule_exists = cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname, ipv6_name) + rule_exists = cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname, f'{NAME6_PREFIX}{ipv6_name}') if not rule_exists: rule_action = 'insert' @@ -155,7 +158,7 @@ def apply(if_firewall): rule_action = 'add' rule_prefix = f'position {handle}' - run(f'nft {rule_action} rule ip6 filter {ipv6_chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {ipv6_name}') + run(f'nft {rule_action} rule ip6 filter {ipv6_chain} {rule_prefix} {if_prefix}ifname {ifname} counter jump {NAME6_PREFIX}{ipv6_name}') else: cleanup_rule('ip6 filter', ipv6_chain, if_prefix, ifname) diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 358b938e3..5b6c57d04 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -54,6 +54,9 @@ sysfs_config = { 'twa_hazards_protection': {'sysfs': '/proc/sys/net/ipv4/tcp_rfc1337'} } +NAME_PREFIX = 'NAME_' +NAME6_PREFIX = 'NAME6_' + preserve_chains = [ 'INPUT', 'FORWARD', @@ -281,9 +284,9 @@ def cleanup_commands(firewall): else: commands.append(f'flush chain {table} {chain}') elif chain not in preserve_chains and not chain.startswith("VZONE"): - if table == 'ip filter' and dict_search_args(firewall, 'name', chain): + if table == 'ip filter' and dict_search_args(firewall, 'name', chain.replace(NAME_PREFIX, "", 1)): commands.append(f'flush chain {table} {chain}') - elif table == 'ip6 filter' and dict_search_args(firewall, 'ipv6_name', chain): + elif table == 'ip6 filter' and dict_search_args(firewall, 'ipv6_name', chain.replace(NAME6_PREFIX, "", 1)): commands.append(f'flush chain {table} {chain}') else: commands += cleanup_rule(table, chain) diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index b6bb5b802..3146fc357 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -88,7 +88,8 @@ def get_config_firewall(conf, name=None, ipv6=False, interfaces=True): def get_nftables_details(name, ipv6=False): suffix = '6' if ipv6 else '' - command = f'sudo nft list chain ip{suffix} filter {name}' + name_prefix = 'NAME6_' if ipv6 else 'NAME_' + command = f'sudo nft list chain ip{suffix} filter {name_prefix}{name}' try: results = cmd(command) except: -- cgit v1.2.3 From c514cea0ad94a00838530cd07f87723be372ea8f Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Tue, 5 Apr 2022 20:40:45 +0200 Subject: firewall: T4345: Fix incorrect rule limit rate syntax --- interface-definitions/include/firewall/common-rule.xml.i | 6 +++--- python/vyos/firewall.py | 2 +- smoketest/configs/dialup-router-complex | 3 +++ smoketest/scripts/cli/test_firewall.py | 5 +++++ src/conf_mode/firewall.py | 6 ++++++ 5 files changed, 18 insertions(+), 4 deletions(-) (limited to 'smoketest/scripts/cli/test_firewall.py') diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index 353804990..cd80b7e28 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -66,11 +66,11 @@ Maximum average matching rate - u32:0-4294967295 - Maximum average matching rate + txt + integer/unit (Example: 5/minute) - + ^\d+/(second|minute|hour|day)$ diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py index 55ce318e7..ff8623592 100644 --- a/python/vyos/firewall.py +++ b/python/vyos/firewall.py @@ -174,7 +174,7 @@ def parse_rule(rule_conf, fw_name, rule_id, ip_name): if 'limit' in rule_conf: if 'rate' in rule_conf['limit']: - output.append(f'limit rate {rule_conf["limit"]["rate"]}/second') + output.append(f'limit rate {rule_conf["limit"]["rate"]}') if 'burst' in rule_conf['limit']: output.append(f'burst {rule_conf["limit"]["burst"]} packets') diff --git a/smoketest/configs/dialup-router-complex b/smoketest/configs/dialup-router-complex index 1b62deb5c..ac5ff5e99 100644 --- a/smoketest/configs/dialup-router-complex +++ b/smoketest/configs/dialup-router-complex @@ -498,6 +498,9 @@ firewall { destination { port 110,995 } + limit { + rate "10/minute" + } protocol tcp } rule 123 { diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index ecc0c29a0..16b020e07 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -88,6 +88,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'destination', 'port', '8888']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'syn']) self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'protocol', 'tcp']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'destination', 'port', '22']) + self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'limit', 'rate', '5/minute']) self.cli_set(['interfaces', 'ethernet', 'eth0', 'firewall', 'in', 'name', 'smoketest']) @@ -97,6 +101,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): ['iifname "eth0"', 'jump NAME_smoketest'], ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'return'], ['tcp flags & (syn | ack) == syn', 'tcp dport { 8888 }', 'reject'], + ['tcp dport { 22 }', 'limit rate 5/minute', 'return'], ['smoketest default-action', 'drop'] ] diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 41df1b84a..f33198a49 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -171,6 +171,12 @@ def verify_rule(firewall, rule_conf, ipv6): if {'match_frag', 'match_non_frag'} <= set(rule_conf['fragment']): raise ConfigError('Cannot specify both "match-frag" and "match-non-frag"') + if 'limit' in rule_conf: + if 'rate' in rule_conf['limit']: + rate_int = re.sub(r'\D', '', rule_conf['limit']['rate']) + if int(rate_int) < 1: + raise ConfigError('Limit rate integer cannot be less than 1') + if 'ipsec' in rule_conf: if {'match_ipsec', 'match_non_ipsec'} <= set(rule_conf['ipsec']): raise ConfigError('Cannot specify both "match-ipsec" and "match-non-ipsec"') -- cgit v1.2.3