summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdata/templates/firewall/nftables.j28
-rwxr-xr-x[-rw-r--r--]interface-definitions/include/firewall/common-rule-bridge.xml.i1
-rwxr-xr-x[-rw-r--r--]interface-definitions/include/firewall/global-options.xml.i6
-rwxr-xr-xinterface-definitions/include/firewall/match-ether-type.xml.i30
-rwxr-xr-xpython/vyos/firewall.py14
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py11
6 files changed, 68 insertions, 2 deletions
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 155b7f4d0..034328400 100755
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -376,8 +376,14 @@ table bridge vyos_filter {
{% if bridge.output is vyos_defined %}
{% for prior, conf in bridge.output.items() %}
- chain VYOS_OUTUT_{{ prior }} {
+ chain VYOS_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
+{% if global_options.apply_to_bridged_traffic is vyos_defined %}
+{% if 'invalid_connections' in global_options.apply_to_bridged_traffic %}
+ ct state invalid udp sport 67 udp dport 68 counter accept
+ ct state invalid ether type arp counter accept
+{% endif %}
+{% endif %}
{% if global_options.state_policy is vyos_defined %}
jump VYOS_STATE_POLICY
{% endif %}
diff --git a/interface-definitions/include/firewall/common-rule-bridge.xml.i b/interface-definitions/include/firewall/common-rule-bridge.xml.i
index 9ae28f7be..80088bbec 100644..100755
--- a/interface-definitions/include/firewall/common-rule-bridge.xml.i
+++ b/interface-definitions/include/firewall/common-rule-bridge.xml.i
@@ -10,6 +10,7 @@
#include <include/firewall/limit.xml.i>
#include <include/firewall/log.xml.i>
#include <include/firewall/log-options.xml.i>
+#include <include/firewall/match-ether-type.xml.i>
#include <include/firewall/match-ipsec.xml.i>
#include <include/firewall/match-vlan.xml.i>
#include <include/firewall/nft-queue.xml.i>
diff --git a/interface-definitions/include/firewall/global-options.xml.i b/interface-definitions/include/firewall/global-options.xml.i
index cee8f1854..05fdd75cb 100644..100755
--- a/interface-definitions/include/firewall/global-options.xml.i
+++ b/interface-definitions/include/firewall/global-options.xml.i
@@ -49,6 +49,12 @@
<help>Apply configured firewall rules to traffic switched by bridges</help>
</properties>
<children>
+ <leafNode name="invalid-connections">
+ <properties>
+ <help>Accept ARP and DHCP despite they are marked as invalid connection</help>
+ <valueless/>
+ </properties>
+ </leafNode>
<leafNode name="ipv4">
<properties>
<help>Apply configured IPv4 firewall rules</help>
diff --git a/interface-definitions/include/firewall/match-ether-type.xml.i b/interface-definitions/include/firewall/match-ether-type.xml.i
new file mode 100755
index 000000000..abfa9034d
--- /dev/null
+++ b/interface-definitions/include/firewall/match-ether-type.xml.i
@@ -0,0 +1,30 @@
+<!-- include start from firewall/match-ether-type.xml.i -->
+<leafNode name="ethernet-type">
+ <properties>
+ <help>Ethernet type</help>
+ <completionHelp>
+ <list>802.1q 802.1ad arp ipv4 ipv6</list>
+ </completionHelp>
+ <valueHelp>
+ <format>802.1q</format>
+ <description>Customer VLAN tag type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>802.1ad</format>
+ <description>Service VLAN tag type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>arp</format>
+ <description>Adress Resolution Protocol</description>
+ </valueHelp>
+ <valueHelp>
+ <format>_ipv4</format>
+ <description>Internet Protocol version 4</description>
+ </valueHelp>
+ <valueHelp>
+ <format>_ipv6</format>
+ <description>Internet Protocol version 6</description>
+ </valueHelp>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/python/vyos/firewall.py b/python/vyos/firewall.py
index f0cf3c924..b1978c1fa 100755
--- a/python/vyos/firewall.py
+++ b/python/vyos/firewall.py
@@ -151,6 +151,20 @@ def parse_rule(rule_conf, hook, fw_name, rule_id, ip_name):
proto = '{tcp, udp}'
output.append(f'meta l4proto {operator} {proto}')
+ if 'ethernet_type' in rule_conf:
+ ether_type_mapping = {
+ '802.1q': '8021q',
+ '802.1ad': '8021ad',
+ 'ipv6': 'ip6',
+ 'ipv4': 'ip',
+ 'arp': 'arp'
+ }
+ ether_type = rule_conf['ethernet_type']
+ operator = '!=' if ether_type.startswith('!') else ''
+ ether_type = ether_type.lstrip('!')
+ ether_type = ether_type_mapping.get(ether_type, ether_type)
+ output.append(f'ether type {operator} {ether_type}')
+
for side in ['destination', 'source']:
if side in rule_conf:
prefix = side[0]
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index b8031eed0..e4f9b14be 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -707,6 +707,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'group', 'ipv6-address-group', 'AGV6', 'address', '2001:db1::1'])
self.cli_set(['firewall', 'global-options', 'state-policy', 'established', 'action', 'accept'])
self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'ipv4'])
+ self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'invalid-connections'])
self.cli_set(['firewall', 'bridge', 'name', name, 'default-action', 'accept'])
self.cli_set(['firewall', 'bridge', 'name', name, 'default-log'])
@@ -731,6 +732,9 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.cli_set(['firewall', 'bridge', 'prerouting', 'filter', 'rule', '1', 'action', 'notrack'])
self.cli_set(['firewall', 'bridge', 'prerouting', 'filter', 'rule', '1', 'destination', 'group', 'ipv6-address-group', 'AGV6'])
+ self.cli_set(['firewall', 'bridge', 'prerouting', 'filter', 'rule', '2', 'ethernet-type', 'arp'])
+ self.cli_set(['firewall', 'bridge', 'prerouting', 'filter', 'rule', '2', 'action', 'accept'])
+
self.cli_commit()
@@ -750,9 +754,14 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
['chain VYOS_INPUT_filter'],
['type filter hook input priority filter; policy accept;'],
['ct state new', 'ip saddr 192.0.2.2', f'iifname "{interface_in}"', 'accept'],
+ ['chain VYOS_OUTPUT_filter'],
+ ['type filter hook output priority filter; policy accept;'],
+ ['ct state invalid', 'udp sport 67', 'udp dport 68', 'accept'],
+ ['ct state invalid', 'ether type arp', 'accept'],
['chain VYOS_PREROUTING_filter'],
['type filter hook prerouting priority filter; policy accept;'],
- ['ip6 daddr @A6_AGV6', 'notrack']
+ ['ip6 daddr @A6_AGV6', 'notrack'],
+ ['ether type arp', 'accept']
]
self.verify_nftables(nftables_search, 'bridge vyos_filter')