[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAOdf3grDKBkYmt54ZAzG1zZ6zz1JXeoHSv67_Fc9-nRiY662mQ@mail.gmail.com>
Date: Thu, 20 Aug 2020 17:17:56 +0200
From: Etienne Champetier <champetier.etienne@...il.com>
To: netdev@...r.kernel.org, netfilter-devel@...r.kernel.org
Subject: bridge firewall "bypass" using VLAN 0 stacking
Hello Linux network folks,
On the input path, the kernel will remove any number of VLAN 0 headers
(priority tagging)
On the bridge firewalling path (iptables filter FORWARD or nftable
bridge table),
the kernel only looks at the current layer, except with
bridge-nf-filter-vlan-tagged=1 where it goes 1 layer deep.
This difference in behaviour makes any project using bridge
firewalling possibly vulnerable.
This was fixed in LXD via
https://github.com/lxc/lxd/commit/7599ff5834c4e0fedb3870a35ff457d342b2d1d8
Openstack Team just made their issue public:
https://bugs.launchpad.net/neutron/+bug/1884341
I haven't checked much more projects (libvirt has good rules but not
enabled by default), but I'm wondering if the current Linux behaviour
could be improved to be less surprising.
If we take the example of LXD (before the fix), enabling anti spoofing options
(security.ipv*_filtering) gives the following nft rules:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
table bridge lxd {
chain in.u1.eth0 {
type filter hook input priority filter; policy accept;
iifname "vethececeb08" ether saddr != 00:16:3e:14:12:03 drop
iifname "vethececeb08" arp saddr ether != 00:16:3e:14:12:03 drop
iifname "vethececeb08" icmpv6 type nd-neighbor-advert
@nh,528,48 != 95530783235 drop
iifname "vethececeb08" arp saddr ip != 10.242.217.2 drop
iifname "vethececeb08" ip saddr 0.0.0.0 ip daddr
255.255.255.255 udp dport 67 accept
iifname "vethececeb08" ip saddr != 10.242.217.2 drop
iifname "vethececeb08" ip6 saddr fe80::/10 ip6 daddr ff02::1:2
udp dport 547 accept
iifname "vethececeb08" ip6 saddr fe80::/10 ip6 daddr ff02::2
icmpv6 type nd-router-solicit accept
iifname "vethececeb08" icmpv6 type nd-neighbor-advert
@nh,384,128 != 336637795894033326396171405568628756995 drop
iifname "vethececeb08" ip6 saddr !=
fd42:14c6:68bf:9774:216:3eff:fe14:1203 drop
iifname "vethececeb08" icmpv6 type nd-router-advert drop
}
chain fwd.u1.eth0 {
type filter hook forward priority filter; policy accept;
iifname "vethececeb08" ether saddr != 00:16:3e:14:12:03 drop
iifname "vethececeb08" arp saddr ether != 00:16:3e:14:12:03 drop
iifname "vethececeb08" icmpv6 type nd-neighbor-advert
@nh,528,48 != 95530783235 drop
iifname "vethececeb08" arp saddr ip != 10.242.217.2 drop
iifname "vethececeb08" ip saddr != 10.242.217.2 drop
iifname "vethececeb08" ip6 saddr !=
fd42:14c6:68bf:9774:216:3eff:fe14:1203 drop
iifname "vethececeb08" icmpv6 type nd-neighbor-advert
@nh,384,128 != 336637795894033326396171405568628756995 drop
iifname "vethececeb08" icmpv6 type nd-router-advert drop
}
...
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some (many) people expect those rules to prevent ARP/IPv4/IPv6
spoofing, but they don't protect either the host or the Linux
neighbours.
Here is a simple scapy script to send router advertisements
encapsulated in 2 VLAN 0 headers. This will bypass all those rules but
be accepted:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ra = Ether()/Dot1Q(vlan=0)/Dot1Q(vlan=0)
ra /= IPv6(dst='ff02::1')
ra /= ICMPv6ND_RA(chlim=64, prf='High', routerlifetime=1800)
ra /= ICMPv6NDOptSrcLLAddr(lladdr=get_if_hwaddr('eth0'))
ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64,
validlifetime=1810, preferredlifetime=1800)
sendp(ra)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(this also works with 'Dot1AD(vlan=0)')
Some server NICs (at least Cisco UCS) use priority tagging by default
so just dropping VLAN 0 traffic is not an option, but here are some
questions / thoughts:
- should the input path drop packets with stacked VLAN 0 ?
- should there be a sysctl to not remove VLAN 0 on the input path ?
VLAN 0 stacking might allow to bypass anti spoofing / DHCP & NDP guard
on some switches in some configuration,
If your network doesn't use priority tagging there is no reason to
accept such traffic.
- should the bridge path have the same behaviour as the input path and
"remove" all the VLAN 0 headers by default ? (that would fix all
projects using bridge firewalling at once)
- are there any other headers that are automatically removed on the
input path that would allow a similar "bypass" ?
Best
Etienne Champetier
Powered by blists - more mailing lists