diff options
author | Nicolas Fort <nicolasfort1988@gmail.com> | 2023-05-23 14:56:29 -0300 |
---|---|---|
committer | Nicolas Fort <nicolasfort1988@gmail.com> | 2023-08-11 11:40:57 -0300 |
commit | ac5b9a4630f87a34d367deef690e8a54cc1eabec (patch) | |
tree | afd0b96198f635e9dc8fa43b53edad3d8b45f92d | |
parent | a8244928af84e65dcc9833e14e2de3324b484977 (diff) | |
download | vyos-1x-ac5b9a4630f87a34d367deef690e8a54cc1eabec.tar.gz vyos-1x-ac5b9a4630f87a34d367deef690e8a54cc1eabec.zip |
T5160: firewall refactor: new cli structure. Add migration script and update smoketest
-rwxr-xr-x | smoketest/scripts/cli/test_firewall.py | 462 | ||||
-rwxr-xr-x | src/migration-scripts/firewall/10-to-11 | 373 |
2 files changed, 601 insertions, 234 deletions
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 0c56c2c93..153793453 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -90,19 +90,19 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): return False def test_geoip(self): - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'drop']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'se']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'gb']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'action', 'accept']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'de']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'fr']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'inverse-match']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'se']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'gb']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'de']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'fr']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '2', 'source', 'geoip', 'inverse-match']) self.cli_commit() nftables_search = [ - ['ip saddr @GEOIP_CC_smoketest_1', 'drop'], - ['ip saddr != @GEOIP_CC_smoketest_2', 'return'] + ['ip saddr @GEOIP_CC_name_smoketest_1', 'drop'], + ['ip saddr != @GEOIP_CC_name_smoketest_2', 'accept'] ] # -t prevents 1000+ GeoIP elements being returned @@ -127,36 +127,33 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'group', 'interface-group', 'smoketest_interface', 'interface', 'eth0']) self.cli_set(['firewall', 'group', 'interface-group', 'smoketest_interface', 'interface', 'vtun0']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) - 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_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(['firewall', 'name', 'smoketest', 'rule', '3', 'action', 'accept']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '3', 'source', 'group', 'domain-group', 'smoketest_domain']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'action', 'accept']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '4', 'outbound-interface', 'interface-group', 'smoketest_interface']) - - self.cli_set(['firewall', 'interface', 'eth0', 'in', 'name', 'smoketest']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'destination', 'address', '172.16.10.10']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '2', 'source', 'group', 'mac-group', 'smoketest_mac']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'source', 'group', 'domain-group', 'smoketest_domain']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'outbound-interface', 'interface-group', 'smoketest_interface']) self.cli_commit() self.wait_for_domain_resolver('ip vyos_filter', 'D_smoketest_domain', '192.0.2.5') nftables_search = [ - ['iifname "eth0"', 'jump NAME_smoketest'], - ['ip saddr @N_smoketest_network', 'ip daddr 172.16.10.10', 'th dport @P_smoketest_port', 'return'], + ['ip saddr @N_smoketest_network', 'ip daddr 172.16.10.10', 'th dport @P_smoketest_port', 'accept'], ['elements = { 172.16.99.0/24 }'], ['elements = { 53, 123 }'], - ['ether saddr @M_smoketest_mac', 'return'], + ['ether saddr @M_smoketest_mac', 'accept'], ['elements = { 00:01:02:03:04:05 }'], ['set D_smoketest_domain'], ['elements = { 192.0.2.5, 192.0.2.8,'], ['192.0.2.10, 192.0.2.11 }'], - ['ip saddr @D_smoketest_domain', 'return'], - ['oifname @I_smoketest_interface', 'return'] + ['ip saddr @D_smoketest_domain', 'accept'], + ['oifname @I_smoketest_interface', 'accept'] ] self.verify_nftables(nftables_search, 'ip vyos_filter') @@ -170,12 +167,10 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port', 'port', '53']) self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port1', 'port', '123']) self.cli_set(['firewall', 'group', 'port-group', 'smoketest_port1', 'include', 'smoketest_port']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network1']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port1']) - self.cli_set(['firewall', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp']) - - self.cli_set(['firewall', 'interface', 'eth0', 'in', 'name', 'smoketest']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'source', 'group', 'network-group', 'smoketest_network1']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'destination', 'group', 'port-group', 'smoketest_port1']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'rule', '1', 'protocol', 'tcp_udp']) self.cli_commit() @@ -187,8 +182,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_delete(['firewall', 'group', 'network-group', 'smoketest_network', 'include', 'smoketest_network1']) nftables_search = [ - ['iifname "eth0"', 'jump NAME_smoketest'], - ['ip saddr @N_smoketest_network1', 'th dport @P_smoketest_port1', 'return'], + ['ip saddr @N_smoketest_network1', 'th dport @P_smoketest_port1', 'accept'], ['elements = { 172.16.99.0/24, 172.16.101.0/24 }'], ['elements = { 53, 123 }'] ] @@ -202,61 +196,75 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): mss_range = '501-1460' conn_mark = '555' - self.cli_set(['firewall', 'name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'name', name, 'enable-default-log']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'source', 'address', '172.16.20.10']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'destination', 'address', '172.16.10.10']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'log', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'log-options', 'level', 'debug']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'ttl', 'eq', '15']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'action', 'reject']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'protocol', 'tcp']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'destination', 'port', '8888']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'log', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'log-options', 'level', 'err']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'tcp', 'flags', 'syn']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'tcp', 'flags', 'not', 'ack']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'ttl', 'gt', '102']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'protocol', 'tcp']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'destination', 'port', '22']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'limit', 'rate', '5/minute']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'log', 'disable']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'action', 'drop']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'protocol', 'tcp']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'destination', 'port', '22']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'recent', 'count', '10']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'recent', 'time', 'minute']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'packet-type', 'host']) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'protocol', 'tcp']) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'flags', 'syn']) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'tcp', 'mss', mss_range]) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'packet-type', 'broadcast']) - self.cli_set(['firewall', 'name', name, 'rule', '5', 'inbound-interface', 'interface-name', interface]) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'action', 'return']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'protocol', 'gre']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'outbound-interface', 'interface-name', interface]) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'connection-mark', conn_mark]) - - self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) - self.cli_set(['firewall', 'interface', interface_wc, 'in', 'name', name]) + self.cli_set(['firewall', 'ip', 'name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'enable-default-log']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'source', 'address', '172.16.20.10']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'destination', 'address', '172.16.10.10']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'log', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'log-options', 'level', 'debug']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'ttl', 'eq', '15']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'destination', 'port', '8888']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'log', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'log-options', 'level', 'err']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'tcp', 'flags', 'syn']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'tcp', 'flags', 'not', 'ack']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'ttl', 'gt', '102']) + + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'destination', 'port', '22']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'limit', 'rate', '5/minute']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '3', 'log', 'disable']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'action', 'drop']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'destination', 'port', '22']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'recent', 'count', '10']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'recent', 'time', 'minute']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '4', 'packet-type', 'host']) + + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'tcp', 'flags', 'syn']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'tcp', 'mss', mss_range]) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'packet-type', 'broadcast']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '5', 'inbound-interface', 'interface-name', interface]) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '6', 'action', 'return']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '6', 'protocol', 'gre']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '6', 'connection-mark', conn_mark]) + + self.cli_set(['firewall', 'ip', 'output', 'filter', 'default-action', 'accept']) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '5', 'action', 'drop']) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '5', 'protocol', 'gre']) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '5', 'outbound-interface', 'interface-name', interface_wc]) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '6', 'action', 'return']) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '6', 'protocol', 'icmp']) + self.cli_set(['firewall', 'ip', 'output', 'filter', 'rule', '6', 'connection-mark', conn_mark]) self.cli_commit() mark_hex = "{0:#010x}".format(int(conn_mark)) nftables_search = [ - [f'iifname "{interface}"', f'jump NAME_{name}'], - [f'iifname "{interface_wc}"', f'jump NAME_{name}'], - ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[smoketest-1-A]" log level debug', 'ip ttl 15', 'return'], + ['chain VYOS_FORWARD_filter'], + ['type filter hook forward priority filter; policy drop;'], + ['tcp dport 22', 'limit rate 5/minute', 'accept'], + ['tcp dport 22', 'add @RECENT_FWD_filter_4 { ip saddr limit rate over 10/minute burst 10 packets }', 'meta pkttype host', 'drop'], + ['chain VYOS_INPUT_filter'], + ['type filter hook input priority filter; policy drop;'], + ['tcp flags & syn == syn', f'tcp option maxseg size {mss_range}', f'iifname "{interface}"', 'meta pkttype broadcast', 'accept'], + ['meta l4proto gre', f'ct mark {mark_hex}', 'return'], + ['chain VYOS_OUTPUT_filter'], + ['type filter hook output priority filter; policy accept;'], + ['meta l4proto gre', f'oifname "{interface_wc}"', 'drop'], + ['meta l4proto icmp', f'ct mark {mark_hex}', 'return'], + ['chain NAME_smoketest'], + ['saddr 172.16.20.10', 'daddr 172.16.10.10', 'log prefix "[smoketest-1-A]" log level debug', 'ip ttl 15', 'accept'], ['tcp flags syn / syn,ack', 'tcp dport 8888', 'log prefix "[smoketest-2-R]" log level err', 'ip ttl > 102', 'reject'], - ['tcp dport 22', 'limit rate 5/minute', 'return'], - ['log prefix "[smoketest-default-D]"','smoketest default-action', 'drop'], - ['tcp dport 22', 'add @RECENT_smoketest_4 { ip saddr limit rate over 10/minute burst 10 packets }', 'meta pkttype host', 'drop'], - ['tcp flags & syn == syn', f'tcp option maxseg size {mss_range}', f'iifname "{interface}"', 'meta pkttype broadcast'], - ['meta l4proto gre', f'oifname "{interface}"', f'ct mark {mark_hex}', 'return'] + ['log prefix "[smoketest-default-D]"','smoketest default-action', 'drop'] ] self.verify_nftables(nftables_search, 'ip vyos_filter') @@ -266,55 +274,54 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): name2 = 'smoketest-adv2' interface = 'eth0' - self.cli_set(['firewall', 'name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'name', name, 'enable-default-log']) - - self.cli_set(['firewall', 'name', name, 'rule', '6', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'packet-length', '64']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'packet-length', '512']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'packet-length', '1024']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'dscp', '17']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'dscp', '52']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'log', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'log-options', 'group', '66']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'log-options', 'snapshot-length', '6666']) - self.cli_set(['firewall', 'name', name, 'rule', '6', 'log-options', 'queue-threshold','32000']) - - self.cli_set(['firewall', 'name', name, 'rule', '7', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '7', 'packet-length', '1-30000']) - self.cli_set(['firewall', 'name', name, 'rule', '7', 'packet-length-exclude', '60000-65535']) - self.cli_set(['firewall', 'name', name, 'rule', '7', 'dscp', '3-11']) - self.cli_set(['firewall', 'name', name, 'rule', '7', 'dscp-exclude', '21-25']) - - self.cli_set(['firewall', 'name', name2, 'default-action', 'jump']) - self.cli_set(['firewall', 'name', name2, 'default-jump-target', name]) - self.cli_set(['firewall', 'name', name2, 'enable-default-log']) - self.cli_set(['firewall', 'name', name2, 'rule', '1', 'source', 'address', '198.51.100.1']) - self.cli_set(['firewall', 'name', name2, 'rule', '1', 'action', 'jump']) - self.cli_set(['firewall', 'name', name2, 'rule', '1', 'jump-target', name]) - - self.cli_set(['firewall', 'name', name2, 'rule', '2', 'protocol', 'tcp']) - self.cli_set(['firewall', 'name', name2, 'rule', '2', 'action', 'queue']) - self.cli_set(['firewall', 'name', name2, 'rule', '2', 'queue', '3']) - self.cli_set(['firewall', 'name', name2, 'rule', '3', 'protocol', 'udp']) - self.cli_set(['firewall', 'name', name2, 'rule', '3', 'action', 'queue']) - self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue-options', 'fanout']) - self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue-options', 'bypass']) - self.cli_set(['firewall', 'name', name2, 'rule', '3', 'queue', '0-15']) - - self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) + self.cli_set(['firewall', 'ip', 'name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'enable-default-log']) + + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'packet-length', '64']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'packet-length', '512']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'packet-length', '1024']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'dscp', '17']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'dscp', '52']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'log', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'log-options', 'group', '66']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'log-options', 'snapshot-length', '6666']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '6', 'log-options', 'queue-threshold','32000']) + + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '7', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '7', 'packet-length', '1-30000']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '7', 'packet-length-exclude', '60000-65535']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '7', 'dscp', '3-11']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '7', 'dscp-exclude', '21-25']) + + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'default-action', 'accept']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'source', 'address', '198.51.100.1']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'action', 'jump']) + self.cli_set(['firewall', 'ip', 'forward', 'filter', 'rule', '1', 'jump-target', name]) + + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '2', 'protocol', 'tcp']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '2', 'action', 'queue']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '2', 'queue', '3']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '3', 'protocol', 'udp']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '3', 'action', 'queue']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '3', 'queue-options', 'fanout']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '3', 'queue-options', 'bypass']) + self.cli_set(['firewall', 'ip', 'input', 'filter', 'rule', '3', 'queue', '0-15']) self.cli_commit() nftables_search = [ - [f'iifname "{interface}"', f'jump NAME_{name}'], - ['ip length { 64, 512, 1024 }', 'ip dscp { 0x11, 0x34 }', f'log prefix "[{name}-6-A]" log group 66 snaplen 6666 queue-threshold 32000', 'return'], - ['ip length 1-30000', 'ip length != 60000-65535', 'ip dscp 0x03-0x0b', 'ip dscp != 0x15-0x19', 'return'], - [f'log prefix "[{name}-default-D]"', 'drop'], + ['chain VYOS_FORWARD_filter'], + ['type filter hook forward priority filter; policy accept;'], ['ip saddr 198.51.100.1', f'jump NAME_{name}'], - [f'log prefix "[{name2}-default-J]"', f'jump NAME_{name}'], + ['chain VYOS_INPUT_filter'], + ['type filter hook input priority filter; policy drop;'], [f'meta l4proto tcp','queue to 3'], - [f'meta l4proto udp','queue flags bypass,fanout to 0-15'] + [f'meta l4proto udp','queue flags bypass,fanout to 0-15'], + [f'chain NAME_{name}'], + ['ip length { 64, 512, 1024 }', 'ip dscp { 0x11, 0x34 }', f'log prefix "[{name}-6-A]" log group 66 snaplen 6666 queue-threshold 32000', 'accept'], + ['ip length 1-30000', 'ip length != 60000-65535', 'ip dscp 0x03-0x0b', 'ip dscp != 0x15-0x19', 'accept'], + [f'log prefix "[{name}-default-D]"', 'drop'] ] self.verify_nftables(nftables_search, 'ip vyos_filter') @@ -325,22 +332,20 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'group', 'address-group', 'mask_group', 'address', '1.1.1.1']) - self.cli_set(['firewall', 'name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'name', name, 'enable-default-log']) + self.cli_set(['firewall', 'ip', 'name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'enable-default-log']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'action', 'drop']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'destination', 'address', '0.0.1.2']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'destination', 'address-mask', '0.0.255.255']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'destination', 'address', '0.0.1.2']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'destination', 'address-mask', '0.0.255.255']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'source', 'address', '!0.0.3.4']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'source', 'address-mask', '0.0.255.255']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'source', 'address', '!0.0.3.4']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'source', 'address-mask', '0.0.255.255']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'action', 'drop']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'source', 'group', 'address-group', 'mask_group']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'source', 'address-mask', '0.0.255.255']) - - self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'source', 'group', 'address-group', 'mask_group']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'source', 'address-mask', '0.0.255.255']) self.cli_commit() @@ -357,34 +362,46 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): name = 'v6-smoketest' interface = 'eth0' - self.cli_set(['firewall', 'ipv6-name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'ipv6-name', name, 'enable-default-log']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'enable-default-log']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'action', 'accept']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'source', 'address', '2002::1']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'destination', 'address', '2002::1:1']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'log', 'enable']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'log-options', 'level', 'crit']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'source', 'address', '2002::1']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'destination', 'address', '2002::1:1']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'log', 'enable']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'log-options', 'level', 'crit']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'action', 'reject']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'protocol', 'tcp_udp']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'destination', 'port', '8888']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'inbound-interface', 'interface-name', interface]) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'default-action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'protocol', 'tcp_udp']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'destination', 'port', '8888']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '2', 'inbound-interface', 'interface-name', interface]) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'action', 'return']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'protocol', 'gre']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'outbound-interface', 'interface-name', interface]) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'action', 'return']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'protocol', 'gre']) + self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '3', 'outbound-interface', 'interface-name', interface]) - self.cli_set(['firewall', 'interface', interface, 'in', 'ipv6-name', name]) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'protocol', 'udp']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'source', 'address', '2002::1:2']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '3', 'inbound-interface', 'interface-name', interface]) self.cli_commit() nftables_search = [ - [f'iifname "{interface}"', f'jump NAME6_{name}'], - ['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[v6-smoketest-1-A]" log level crit', 'return'], + ['chain VYOS_IPV6_FORWARD_filter'], + ['type filter hook forward priority filter; policy accept;'], ['meta l4proto { tcp, udp }', 'th dport 8888', f'iifname "{interface}"', 'reject'], + ['chain VYOS_IPV6_INPUT_filter'], + ['type filter hook input priority filter; policy drop;'], + ['meta l4proto udp', 'ip6 saddr 2002::1:2', f'iifname "{interface}"', 'accept'], + ['chain VYOS_IPV6_OUTPUT_filter'], + ['type filter hook output priority filter; policy drop;'], ['meta l4proto gre', f'oifname "{interface}"', 'return'], - ['smoketest default-action', f'log prefix "[{name}-default-D]"', 'drop'] + [f'chain NAME6_{name}'], + ['saddr 2002::1', 'daddr 2002::1:1', 'log prefix "[v6-smoketest-1-A]" log level crit', 'accept'], + [f'"{name} default-action drop"', f'log prefix "[{name}-default-D]"', 'drop'] ] self.verify_nftables(nftables_search, 'ip6 vyos_filter') @@ -394,40 +411,39 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): name2 = 'v6-smoketest-adv2' interface = 'eth0' - self.cli_set(['firewall', 'ipv6-name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'ipv6-name', name, 'enable-default-log']) - - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'action', 'accept']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'packet-length', '65']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'packet-length', '513']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'packet-length', '1025']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'dscp', '18']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'dscp', '53']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'enable-default-log']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '4', 'action', 'accept']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '4', 'packet-length', '1-1999']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '4', 'packet-length-exclude', '60000-65535']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '4', 'dscp', '4-14']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '4', 'dscp-exclude', '31-35']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'packet-length', '65']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'packet-length', '513']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'packet-length', '1025']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'dscp', '18']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'dscp', '53']) - self.cli_set(['firewall', 'ipv6-name', name2, 'default-action', 'jump']) - self.cli_set(['firewall', 'ipv6-name', name2, 'default-jump-target', name]) - self.cli_set(['firewall', 'ipv6-name', name2, 'enable-default-log']) - self.cli_set(['firewall', 'ipv6-name', name2, 'rule', '1', 'source', 'address', '2001:db8::/64']) - self.cli_set(['firewall', 'ipv6-name', name2, 'rule', '1', 'action', 'jump']) - self.cli_set(['firewall', 'ipv6-name', name2, 'rule', '1', 'jump-target', name]) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '4', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '4', 'packet-length', '1-1999']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '4', 'packet-length-exclude', '60000-65535']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '4', 'dscp', '4-14']) + self.cli_set(['firewall', 'ipv6', 'forward', 'filter', 'rule', '4', 'dscp-exclude', '31-35']) - self.cli_set(['firewall', 'interface', interface, 'in', 'ipv6-name', name]) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'default-action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'source', 'address', '2001:db8::/64']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'action', 'jump']) + self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '1', 'jump-target', name]) self.cli_commit() nftables_search = [ - [f'iifname "{interface}"', f'jump NAME6_{name}'], - ['ip6 length { 65, 513, 1025 }', 'ip6 dscp { af21, 0x35 }', 'return'], - ['ip6 length 1-1999', 'ip6 length != 60000-65535', 'ip6 dscp 0x04-0x0e', 'ip6 dscp != 0x1f-0x23', 'return'], - [f'log prefix "[{name}-default-D]"', 'drop'], + ['chain VYOS_IPV6_FORWARD_filter'], + ['type filter hook forward priority filter; policy drop;'], + ['ip6 length 1-1999', 'ip6 length != 60000-65535', 'ip6 dscp 0x04-0x0e', 'ip6 dscp != 0x1f-0x23', 'accept'], + ['chain VYOS_IPV6_INPUT_filter'], + ['type filter hook input priority filter; policy accept;'], ['ip6 saddr 2001:db8::/64', f'jump NAME6_{name}'], - [f'log prefix "[{name2}-default-J]"', f'jump NAME6_{name}'] + [f'chain NAME6_{name}'], + ['ip6 length { 65, 513, 1025 }', 'ip6 dscp { af21, 0x35 }', 'accept'], + [f'log prefix "[{name}-default-D]"', 'drop'] ] self.verify_nftables(nftables_search, 'ip6 vyos_filter') @@ -438,22 +454,20 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.cli_set(['firewall', 'group', 'ipv6-address-group', 'mask_group', 'address', '::beef']) - self.cli_set(['firewall', 'ipv6-name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'ipv6-name', name, 'enable-default-log']) - - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'action', 'drop']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'destination', 'address', '::1111:2222:3333:4444']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '1', 'destination', 'address-mask', '::ffff:ffff:ffff:ffff']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'enable-default-log']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'action', 'accept']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'source', 'address', '!::aaaa:bbbb:cccc:dddd']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '2', 'source', 'address-mask', '::ffff:ffff:ffff:ffff']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'destination', 'address', '::1111:2222:3333:4444']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '1', 'destination', 'address-mask', '::ffff:ffff:ffff:ffff']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'action', 'drop']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'source', 'group', 'address-group', 'mask_group']) - self.cli_set(['firewall', 'ipv6-name', name, 'rule', '3', 'source', 'address-mask', '::ffff:ffff:ffff:ffff']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '2', 'action', 'accept']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '2', 'source', 'address', '!::aaaa:bbbb:cccc:dddd']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '2', 'source', 'address-mask', '::ffff:ffff:ffff:ffff']) - self.cli_set(['firewall', 'interface', interface, 'in', 'ipv6-name', name]) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'action', 'drop']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'source', 'group', 'address-group', 'mask_group']) + self.cli_set(['firewall', 'ipv6', 'ipv6-name', name, 'rule', '3', 'source', 'address-mask', '::ffff:ffff:ffff:ffff']) self.cli_commit() @@ -465,52 +479,32 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.verify_nftables(nftables_search, 'ip6 vyos_filter') - def test_state_policy(self): - self.cli_set(['firewall', 'state-policy', 'established', 'action', 'accept']) - self.cli_set(['firewall', 'state-policy', 'related', 'action', 'accept']) - self.cli_set(['firewall', 'state-policy', 'invalid', 'action', 'drop']) - - self.cli_commit() - - chains = { - 'ip vyos_filter': ['VYOS_FW_FORWARD', 'VYOS_FW_OUTPUT', 'VYOS_FW_LOCAL'], - 'ip6 vyos_filter': ['VYOS_FW6_FORWARD', 'VYOS_FW6_OUTPUT', 'VYOS_FW6_LOCAL'] - } - - for table in ['ip vyos_filter', 'ip6 vyos_filter']: - for chain in chains[table]: - nftables_output = cmd(f'sudo nft list chain {table} {chain}') - self.assertTrue('jump VYOS_STATE_POLICY' in nftables_output) - def test_ipv4_state_and_status_rules(self): name = 'smoketest-state' interface = 'eth0' - self.cli_set(['firewall', 'name', name, 'default-action', 'drop']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'state', 'established', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '1', 'state', 'related', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'action', 'reject']) - self.cli_set(['firewall', 'name', name, 'rule', '2', 'state', 'invalid', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '3', 'state', 'new', 'enable']) - - self.cli_set(['firewall', 'name', name, 'rule', '3', 'connection-status', 'nat', 'destination']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'action', 'accept']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'state', 'new', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'state', 'established', 'enable']) - self.cli_set(['firewall', 'name', name, 'rule', '4', 'connection-status', 'nat', 'source']) - - self.cli_set(['firewall', 'interface', interface, 'in', 'name', name]) + self.cli_set(['firewall', 'ip', 'name', name, 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '1', 'state', 'related', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'action', 'reject']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '2', 'state', 'invalid', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'state', 'new', 'enable']) + + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '3', 'connection-status', 'nat', 'destination']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '4', 'action', 'accept']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '4', 'state', 'new', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '4', 'state', 'established', 'enable']) + self.cli_set(['firewall', 'ip', 'name', name, 'rule', '4', 'connection-status', 'nat', 'source']) self.cli_commit() nftables_search = [ - [f'iifname "{interface}"', f'jump NAME_{name}'], - ['ct state { established, related }', 'return'], + ['ct state { established, related }', 'accept'], ['ct state invalid', 'reject'], - ['ct state new', 'ct status dnat', 'return'], - ['ct state { established, new }', 'ct status snat', 'return'], + ['ct state new', 'ct status dnat', 'accept'], + ['ct state { established, new }', 'ct status snat', 'accept'], ['drop', f'comment "{name} default-action drop"'] ] @@ -534,7 +528,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase): self.assertNotEqual(f.read().strip(), conf['default'], msg=path) def test_zone_basic(self): - self.cli_set(['firewall', 'name', 'smoketest', 'default-action', 'drop']) + self.cli_set(['firewall', 'ip', 'name', 'smoketest', 'default-action', 'drop']) self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'interface', 'eth0']) self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'from', 'smoketest-local', 'firewall', 'name', 'smoketest']) self.cli_set(['firewall', 'zone', 'smoketest-local', 'local-zone']) diff --git a/src/migration-scripts/firewall/10-to-11 b/src/migration-scripts/firewall/10-to-11 new file mode 100755 index 000000000..b2880afac --- /dev/null +++ b/src/migration-scripts/firewall/10-to-11 @@ -0,0 +1,373 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 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 <http://www.gnu.org/licenses/>. + +# T5160: Firewall re-writing + +# cli changes from: +# set firewall name <name> ... +# set firewall ipv6-name <name> ... +# To +# set firewall ip name <name> +# set firewall ipv6 ipv6-name <name> + +## Also from 'firewall interface' removed. +## in and out: + # set firewall interface <iface> [in|out] [name | ipv6-name] <name> + # To + # set firewall [ip | ipv6] forward filter rule <5,10,15,...> [inbound-interface | outboubd-interface] interface-name <iface> + # set firewall [ip | ipv6] forward filter rule <5,10,15,...> action jump + # set firewall [ip | ipv6] forward filter rule <5,10,15,...> jump-target <name> +## local: + # set firewall interface <iface> local [name | ipv6-name] <name> + # To + # set firewall [ip | ipv6] input filter rule <5,10,15,...> inbound-interface interface-name <iface> + # set firewall [ip | ipv6] input filter rule <5,10,15,...> action jump + # set firewall [ip | ipv6] input filter rule <5,10,15,...> jump-target <name> + +import re + +from sys import argv +from sys import exit + +from vyos.configtree import ConfigTree +from vyos.ifconfig import Section + +if (len(argv) < 1): + print("Must specify file name!") + exit(1) + +file_name = argv[1] + +with open(file_name, 'r') as f: + config_file = f.read() + +base = ['firewall'] +config = ConfigTree(config_file) + +if not config.exists(base): + # Nothing to do + exit(0) + +### Migration of state policies +if config.exists(base + ['state-policy']): + for family in ['ip', 'ipv6']: + for hook in ['forward', 'input', 'output']: + for priority in ['filter']: + # Add default-action== accept for compatibility reasons: + config.set(base + [family, hook, priority, 'default-action'], value='accept') + position = 1 + for state in config.list_nodes(base + ['state-policy']): + action = config.return_value(base + ['state-policy', state, 'action']) + config.set(base + [family, hook, priority, 'rule']) + config.set_tag(base + [family, hook, priority, 'rule']) + config.set(base + [family, hook, priority, 'rule', position, 'state', state], value='enable') + config.set(base + [family, hook, priority, 'rule', position, 'action'], value=action) + position = position + 1 + config.delete(base + ['state-policy']) +############ + +## migration of global options: +for option in ['all-ping', 'broadcast-ping', 'config-trap', 'ip-src-route', 'ipv6-receive-redirects', 'ipv6-src-route', 'log-martians', + 'receive-redirects', 'resolver-cache', 'resolver-internal', 'send-redirects', 'source-validation', 'syn-cookies', 'twa-hazards-protection']: + if config.exists(base + [option]): + val = config.return_value(base + [option]) + config.set(base + ['global-options', option], value=val) + config.delete(base + [option]) + +### Migration of firewall name and ipv6-name +if config.exists(base + ['name']): + config.set(['firewall', 'ip', 'name']) + config.set_tag(['firewall', 'ip', 'name']) + + for ipv4name in config.list_nodes(base + ['name']): + config.copy(base + ['name', ipv4name], base + ['ip', 'name', ipv4name]) + config.delete(base + ['name']) + +if config.exists(base + ['ipv6-name']): + config.set(['firewall', 'ipv6', 'ipv6-name']) + config.set_tag(['firewall', 'ipv6', 'ipv6-name']) + + for ipv6name in config.list_nodes(base + ['ipv6-name']): + config.copy(base + ['ipv6-name', ipv6name], base + ['ipv6', 'ipv6-name', ipv6name]) + config.delete(base + ['ipv6-name']) + +### Migration of firewall interface +if config.exists(base + ['interface']): + fwd_ipv4_rule = 5 + inp_ipv4_rule = 5 + fwd_ipv6_rule = 5 + inp_ipv6_rule = 5 + for iface in config.list_nodes(base + ['interface']): + for direction in ['in', 'out', 'local']: + if config.exists(base + ['interface', iface, direction]): + if config.exists(base + ['interface', iface, direction, 'name']): + target = config.return_value(base + ['interface', iface, direction, 'name']) + if direction == 'in': + # Add default-action== accept for compatibility reasons: + config.set(base + ['ip', 'forward', 'filter', 'default-action'], value='accept') + new_base = base + ['ip', 'forward', 'filter', 'rule'] + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [fwd_ipv4_rule, 'inbound-interface', 'interface-name'], value=iface) + config.set(new_base + [fwd_ipv4_rule, 'action'], value='jump') + config.set(new_base + [fwd_ipv4_rule, 'jump-target'], value=target) + fwd_ipv4_rule = fwd_ipv4_rule + 5 + elif direction == 'out': + # Add default-action== accept for compatibility reasons: + config.set(base + ['ip', 'forward', 'filter', 'default-action'], value='accept') + new_base = base + ['ip', 'forward', 'filter', 'rule'] + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [fwd_ipv4_rule, 'outbound-interface', 'interface-name'], value=iface) + config.set(new_base + [fwd_ipv4_rule, 'action'], value='jump') + config.set(new_base + [fwd_ipv4_rule, 'jump-target'], value=target) + fwd_ipv4_rule = fwd_ipv4_rule + 5 + else: + # Add default-action== accept for compatibility reasons: + config.set(base + ['ip', 'input', 'filter', 'default-action'], value='accept') + new_base = base + ['ip', 'input', 'filter', 'rule'] + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [inp_ipv4_rule, 'inbound-interface', 'interface-name'], value=iface) + config.set(new_base + [inp_ipv4_rule, 'action'], value='jump') + config.set(new_base + [inp_ipv4_rule, 'jump-target'], value=target) + inp_ipv4_rule = inp_ipv4_rule + 5 + + if config.exists(base + ['interface', iface, direction, 'ipv6-name']): + target = config.return_value(base + ['interface', iface, direction, 'ipv6-name']) + if direction == 'in': + # Add default-action== accept for compatibility reasons: + config.set(base + ['ipv6', 'forward', 'filter', 'default-action'], value='accept') + new_base = base + ['ipv6', 'forward', 'filter', 'rule'] + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [fwd_ipv6_rule, 'inbound-interface', 'interface-name'], value=iface) + config.set(new_base + [fwd_ipv6_rule, 'action'], value='jump') + config.set(new_base + [fwd_ipv6_rule, 'jump-target'], value=target) + fwd_ipv6_rule = fwd_ipv6_rule + 5 + elif direction == 'out': + # Add default-action== accept for compatibility reasons: + config.set(base + ['ipv6', 'forward', 'filter', 'default-action'], value='accept') + new_base = base + ['ipv6', 'forward', 'filter', 'rule'] + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [fwd_ipv6_rule, 'outbound-interface', 'interface-name'], value=iface) + config.set(new_base + [fwd_ipv6_rule, 'action'], value='jump') + config.set(new_base + [fwd_ipv6_rule, 'jump-target'], value=target) + fwd_ipv6_rule = fwd_ipv6_rule + 5 + else: + new_base = base + ['ipv6', 'input', 'filter', 'rule'] + # Add default-action== accept for compatibility reasons: + config.set(base + ['ipv6', 'input', 'filter', 'default-action'], value='accept') + config.set(new_base) + config.set_tag(new_base) + config.set(new_base + [inp_ipv6_rule, 'inbound-interface', 'interface-name'], value=iface) + config.set(new_base + [inp_ipv6_rule, 'action'], value='jump') + config.set(new_base + [inp_ipv6_rule, 'jump-target'], value=target) + inp_ipv6_rule = inp_ipv6_rule + 5 + + config.delete(base + ['interface']) + + +### Migration of zones config v2: +### User interface groups +if config.exists(base + ['zone']): + inp_ipv4_rule = 101 + inp_ipv6_rule = 101 + fwd_ipv4_rule = 101 + fwd_ipv6_rule = 101 + out_ipv4_rule = 101 + out_ipv6_rule = 101 + local_zone = 'False' + + for zone in config.list_nodes(base + ['zone']): + if config.exists(base + ['zone', zone, 'local-zone']): + local_zone = 'True' + # Add default-action== accept for compatibility reasons: + config.set(base + ['ip', 'input', 'filter', 'default-action'], value='accept') + config.set(base + ['ipv6', 'input', 'filter', 'default-action'], value='accept') + config.set(base + ['ip', 'output', 'filter', 'default-action'], value='accept') + config.set(base + ['ipv6', 'output', 'filter', 'default-action'], value='accept') + for from_zone in config.list_nodes(base + ['zone', zone, 'from']): + group_name = 'IG_' + from_zone + if config.exists(base + ['zone', zone, 'from', from_zone, 'firewall', 'name']): + # ipv4 input ruleset + target_ipv4_chain = config.return_value(base + ['zone', zone, 'from', from_zone, 'firewall', 'name']) + config.set(base + ['ip', 'input', 'filter', 'rule']) + config.set_tag(base + ['ip', 'input', 'filter', 'rule']) + config.set(base + ['ip', 'input', 'filter', 'rule', inp_ipv4_rule, 'inbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'input', 'filter', 'rule', inp_ipv4_rule, 'action'], value='jump') + config.set(base + ['ip', 'input', 'filter', 'rule', inp_ipv4_rule, 'jump-target'], value=target_ipv4_chain) + inp_ipv4_rule = inp_ipv4_rule + 5 + if config.exists(base + ['zone', zone, 'from', from_zone, 'firewall', 'ipv6-name']): + # ipv6 input ruleset + target_ipv6_chain = config.return_value(base + ['zone', zone, 'from', from_zone, 'firewall', 'ipv6-name']) + config.set(base + ['ipv6', 'input', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'input', 'filter', 'rule']) + config.set(base + ['ipv6', 'input', 'filter', 'rule', inp_ipv6_rule, 'inbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'input', 'filter', 'rule', inp_ipv6_rule, 'action'], value='jump') + config.set(base + ['ipv6', 'input', 'filter', 'rule', inp_ipv6_rule, 'jump-target'], value=target_ipv6_chain) + inp_ipv6_rule = inp_ipv6_rule + 5 + + # Migrate: set firewall zone <zone> default-action <action> + # Options: drop or reject. If not specified, is drop + if config.exists(base + ['zone', zone, 'default-action']): + local_def_action = config.return_value(base + ['zone', zone, 'default-action']) + else: + local_def_action = 'drop' + config.set(base + ['ip', 'input', 'filter', 'rule']) + config.set_tag(base + ['ip', 'input', 'filter', 'rule']) + config.set(base + ['ip', 'input', 'filter', 'rule', inp_ipv4_rule, 'action'], value=local_def_action) + config.set(base + ['ipv6', 'input', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'input', 'filter', 'rule']) + config.set(base + ['ipv6', 'input', 'filter', 'rule', inp_ipv6_rule, 'action'], value=local_def_action) + if config.exists(base + ['zone', zone, 'enable-default-log']): + config.set(base + ['ip', 'input', 'filter', 'rule', inp_ipv4_rule, 'log'], value='enable') + config.set(base + ['ipv6', 'input', 'filter', 'rule', inp_ipv6_rule, 'log'], value='enable') + + else: + # It's not a local zone + group_name = 'IG_' + zone + # Add default-action== accept for compatibility reasons: + config.set(base + ['ip', 'forward', 'filter', 'default-action'], value='accept') + config.set(base + ['ipv6', 'forward', 'filter', 'default-action'], value='accept') + # intra-filtering migration. By default accept + intra_zone_ipv4_action = 'accept' + intra_zone_ipv6_action = 'accept' + + if config.exists(base + ['zone', zone, 'intra-zone-filtering', 'action']): + intra_zone_ipv4_action = config.return_value(base + ['zone', zone, 'intra-zone-filtering', 'action']) + intra_zone_ipv6_action = intra_zone_ipv4_action + else: + if config.exists(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'name']): + intra_zone_ipv4_target = config.return_value(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'name']) + intra_zone_ipv4_action = 'jump' + if config.exists(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'ipv6-name']): + intra_zone_ipv6_target = config.return_value(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'ipv6-name']) + intra_zone_ipv6_action = 'jump' + config.set(base + ['ip', 'forward', 'filter', 'rule']) + config.set_tag(base + ['ip', 'forward', 'filter', 'rule']) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'inbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'action'], value=intra_zone_ipv4_action) + config.set_tag(base + ['ipv6', 'forward', 'filter', 'rule']) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'inbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'action'], value=intra_zone_ipv6_action) + if intra_zone_ipv4_action == 'jump': + if config.exists(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'name']): + intra_zone_ipv4_target = config.return_value(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'name']) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'jump-target'], value=intra_zone_ipv4_target) + if intra_zone_ipv6_action == 'jump': + if config.exists(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'ipv6-name']): + intra_zone_ipv6_target = config.return_value(base + ['zone', zone, 'intra-zone-filtering', 'firewall', 'ipv6-name']) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'jump-target'], value=intra_zone_ipv6_target) + fwd_ipv4_rule = fwd_ipv4_rule + 5 + fwd_ipv6_rule = fwd_ipv6_rule + 5 + + if config.exists(base + ['zone', zone, 'interface']): + # Create interface group IG_<zone> + group_name = 'IG_' + zone + config.set(base + ['group', 'interface-group'], value=group_name) + config.set_tag(base + ['group', 'interface-group']) + for iface in config.return_values(base + ['zone', zone, 'interface']): + config.set(base + ['group', 'interface-group', group_name, 'interface'], value=iface, replace=False) + + if config.exists(base + ['zone', zone, 'from']): + for from_zone in config.list_nodes(base + ['zone', zone, 'from']): + from_group = 'IG_' + from_zone + if config.exists(base + ['zone', zone, 'from', from_zone, 'firewall', 'name']): + target_ipv4_chain = config.return_value(base + ['zone', zone, 'from', from_zone, 'firewall', 'name']) + if config.exists(base + ['zone', from_zone, 'local-zone']): + # It's from LOCAL zone -> Output filtering + config.set(base + ['ip', 'output', 'filter', 'rule']) + config.set_tag(base + ['ip', 'output', 'filter', 'rule']) + config.set(base + ['ip', 'output', 'filter', 'rule', out_ipv4_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'output', 'filter', 'rule', out_ipv4_rule, 'action'], value='jump') + config.set(base + ['ip', 'output', 'filter', 'rule', out_ipv4_rule, 'jump-target'], value=target_ipv4_chain) + out_ipv4_rule = out_ipv4_rule + 5 + else: + # It's not LOCAL zone -> forward filtering + config.set(base + ['ip', 'forward', 'filter', 'rule']) + config.set_tag(base + ['ip', 'forward', 'filter', 'rule']) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'inbound-interface', 'interface-group'], value=from_group) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'action'], value='jump') + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'jump-target'], value=target_ipv4_chain) + fwd_ipv4_rule = fwd_ipv4_rule + 5 + if config.exists(base + ['zone', zone, 'from', from_zone, 'firewall', 'ipv6-name']): + target_ipv6_chain = config.return_value(base + ['zone', zone, 'from', from_zone, 'firewall', 'ipv6-name']) + if config.exists(base + ['zone', from_zone, 'local-zone']): + # It's from LOCAL zone -> Output filtering + config.set(base + ['ipv6', 'output', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'output', 'filter', 'rule']) + config.set(base + ['ipv6', 'output', 'filter', 'rule', out_ipv6_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'output', 'filter', 'rule', out_ipv6_rule, 'action'], value='jump') + config.set(base + ['ipv6', 'output', 'filter', 'rule', out_ipv6_rule, 'jump-target'], value=target_ipv6_chain) + out_ipv6_rule = out_ipv6_rule + 5 + else: + # It's not LOCAL zone -> forward filtering + config.set(base + ['ipv6', 'forward', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'forward', 'filter', 'rule']) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'inbound-interface', 'interface-group'], value=from_group) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'action'], value='jump') + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'jump-target'], value=target_ipv6_chain) + fwd_ipv6_rule = fwd_ipv6_rule + 5 + + ## Now need to migrate: set firewall zone <zone> default-action <action> # action=drop if not specified. + if config.exists(base + ['zone', zone, 'default-action']): + def_action = config.return_value(base + ['zone', zone, 'default-action']) + else: + def_action = 'drop' + config.set(base + ['ip', 'forward', 'filter', 'rule']) + config.set_tag(base + ['ip', 'forward', 'filter', 'rule']) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'action'], value=def_action) + description = 'zone_' + zone + ' default-action' + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'description'], value=description) + config.set(base + ['ipv6', 'forward', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'forward', 'filter', 'rule']) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'outbound-interface', 'interface-group'], value=group_name) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'action'], value=def_action) + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'description'], value=description) + + if config.exists(base + ['zone', zone, 'enable-default-log']): + config.set(base + ['ip', 'forward', 'filter', 'rule', fwd_ipv4_rule, 'log'], value='enable') + config.set(base + ['ipv6', 'forward', 'filter', 'rule', fwd_ipv6_rule, 'log'], value='enable') + fwd_ipv4_rule = fwd_ipv4_rule + 5 + fwd_ipv6_rule = fwd_ipv6_rule + 5 + + # Migrate default-action (force to be drop in output chain) if local zone is defined + if local_zone == 'True': + # General drop in output change if needed + config.set(base + ['ip', 'output', 'filter', 'rule']) + config.set_tag(base + ['ip', 'output', 'filter', 'rule']) + config.set(base + ['ip', 'output', 'filter', 'rule', out_ipv4_rule, 'action'], value=local_def_action) + config.set(base + ['ipv6', 'output', 'filter', 'rule']) + config.set_tag(base + ['ipv6', 'output', 'filter', 'rule']) + config.set(base + ['ipv6', 'output', 'filter', 'rule', out_ipv6_rule, 'action'], value=local_def_action) + + config.delete(base + ['zone']) + +###### END migration zones v2 + +try: + with open(file_name, 'w') as f: + f.write(config.to_string()) +except OSError as e: + print("Failed to save the modified config: {}".format(e)) + exit(1)
\ No newline at end of file |