The introduction of bridge firewalling has brought about a long trail of strange problems that have successively led to the creation of per-protocol workarounds in firewall global-options apply-to-bridged-traffic accept-invalid to make things like ARP and DHCP work.
While figuring out why VyOS receives STP BPDUs from my switch, but my switch does not receive any from VyOS, I eventually realized that the frames are being dropped by ct_state invalid on the bridge.
I tried to work around that by setting up the following rule:
[edit firewall bridge output filter]
pngu@r0# sh r 100
action accept
destination {
/* IEEE 802.1d STP/RSTP/MSTP destination MAC */
mac-address 01:80:c2:00:00:00
}
Unfortunately that also doesn’t work, as it is inserted after the conntrack state policy:
root@r0:/home/pngu# nft list chain bridge vyos_filter VYOS_OUTPUT_filter
table bridge vyos_filter {
chain VYOS_OUTPUT_filter {
type filter hook output priority filter; policy accept;
ct state invalid ether type arp counter packets 0 bytes 0 accept
ct state invalid ether type 8021q counter packets 14 bytes 392 accept
ct state invalid udp sport 67 udp dport 68 counter packets 0 bytes 0 accept
ct state invalid ether type 0x0842 counter packets 0 bytes 0 accept
ct state invalid ether type 0x8864 counter packets 0 bytes 0 accept
ct state invalid ether type 0x8863 counter packets 0 bytes 0 accept
jump VYOS_STATE_POLICY
ether daddr 01:80:c2:00:00:00 counter packets 0 bytes 0 accept comment "bri-OUT-filter-100"
counter packets 0 bytes 0 accept comment "OUT-filter default-action accept"
}
}
Once I manually insert that rule ahead of the state policy jump, my switch starts receiving BPDUs:
root@r0:/home/pngu# nft insert rule bridge vyos_filter VYOS_OUTPUT_filter ct state invalid ether daddr 01:80:c2:00:00:00 counter accept
root@r0:/home/pngu# nft list chain bridge vyos_filter VYOS_OUTPUT_filter
table bridge vyos_filter {
chain VYOS_OUTPUT_filter {
type filter hook output priority filter; policy accept;
ct state invalid ether daddr 01:80:c2:00:00:00 counter packets 90 bytes 4680 accept
ct state invalid ether type arp counter packets 0 bytes 0 accept
ct state invalid ether type 8021q counter packets 251 bytes 7028 accept
ct state invalid udp sport 67 udp dport 68 counter packets 0 bytes 0 accept
ct state invalid ether type 0x0842 counter packets 0 bytes 0 accept
ct state invalid ether type 0x8864 counter packets 0 bytes 0 accept
ct state invalid ether type 0x8863 counter packets 0 bytes 0 accept
jump VYOS_STATE_POLICY
ether daddr 01:80:c2:00:00:00 counter packets 0 bytes 0 accept comment "bri-OUT-filter-100"
counter packets 0 bytes 0 accept comment "OUT-filter default-action accept"
}
}
There are several possible future options to get STP working:
A: Another firewall global-options apply-to-bridged-traffic accept-invalid option, this time for stp
B: An option similar to the above, but for allowing any kind of bridge traffic that conntrack marks as invalid, regardless of “protocol”, e.g. firewall global-options apply-to-bridged-traffic accept-invalid all
C: An option to disable conntrack on bridge interfaces, e.g. firewall global-options apply-to-bridged-traffic disable-conntrack
D: An option to disable all nftables handling of bridge interfaces (i.e. don’t register table bridge at all if the firewall global-options apply-to-bridged-traffic config element is not present)
There are probably other ways to do this, but I’m trying to make a case for option D here, as it would be intuitive behaviour and a sane default. There are valid use cases for filtering bridge traffic when doing things like L2 tunneling, which I believe the original PR introducing bridge firewall was geared towards, but in its current form the feature seems to be doing more harm than good.
As a side note, it seems that all the stuff conntrack complains about as invalid is involving broadcast or link-local addressing of some sort (DHCP, ARP, STP, etc) and it might be possible to fix it by using per-physical-interface conntrack zones instead of the current series of “accept invalid” workarounds, but I’m not familiar enough with conntrack as a whole to be sure, it’s just something that kept coming up during my research.