[Bug 1221] New: "fib" produces strange results with an IPv6 default route
bugzilla-daemon at netfilter.org
bugzilla-daemon at netfilter.org
Tue Jan 30 15:40:00 CET 2018
https://bugzilla.netfilter.org/show_bug.cgi?id=1221
Bug ID: 1221
Summary: "fib" produces strange results with an IPv6 default
route
Product: nftables
Version: unspecified
Hardware: x86_64
OS: Debian GNU/Linux
Status: NEW
Severity: major
Priority: P5
Component: kernel
Assignee: pablo at netfilter.org
Reporter: f30 at f30.me
I am trying to implement reverse path filtering using "fib" rules like `fib
saddr . iif oif 0 drop`.
I don't understand why exactly (see #1220), but this generally works for IPv4
and IPv6 without a default route. However, "fib" starts to behave strangely
with a v6 default route.
Assume a host with two interfaces, enp0s5 and enp0s6, and the following IP
addresses:
> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group
default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state
UP group default qlen 1000
link/ether 00:1c:42:87:bf:33 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 brd 10.0.0.255 scope global enp0s5
valid_lft forever preferred_lft forever
inet6 fd00::3/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::21c:42ff:fe87:bf33/64 scope link
valid_lft forever preferred_lft forever
3: enp0s6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state
UP group default qlen 1000
link/ether 00:1c:42:5c:28:c0 brd ff:ff:ff:ff:ff:ff
inet 10.1.1.3/24 brd 10.1.1.255 scope global enp0s6
valid_lft forever preferred_lft forever
inet6 fd11::3/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::21c:42ff:fe5c:28c0/64 scope link
valid_lft forever preferred_lft forever
The routing table for v6 looks fairly unsurprising:
> ip -6 r
fd00::/64 dev enp0s5 proto kernel metric 256 pref medium
fd11::/64 dev enp0s6 proto kernel metric 256 pref medium
fe80::/64 dev enp0s5 proto kernel metric 256 pref medium
fe80::/64 dev enp0s6 proto kernel metric 256 pref medium
Let's add some "fib" rules to get the following ruleset.
(Only using counter statements and adding matches for "enp0s5" and "enp0s6" for
demonstration purposes. I'm using the "inet" family here, but the behavior can
also be replicated with "ip6".)
> nft list ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
table inet raw {
chain prerouting {
type filter hook prerouting priority -300; policy accept;
fib saddr . iif oif 0 udp dport 1337 counter packets 0 bytes 0
fib saddr . iif oif "enp0s5" udp dport 1337 counter packets 0 bytes 0
fib saddr . iif oif "enp0s6" udp dport 1337 counter packets 0 bytes 0
}
}
Using Scapy on another host, we now send some packets to the wrong interface
(to enp0s6 with a source address belonging to enp0s5's net):
>>> e = Ether(dst='00:1c:42:5c:28:c0')
>>> i = IPv6(src='fd00::1', dst='fd11::3')
>>> u = UDP(dport=1337)
>>> sendp(e / i / u, iface='vnic3')
.
Sent 1 packets.
In this case, everything works as expected and the first "fib" rule matches:
> nft list chain inet raw prerouting
table inet raw {
chain prerouting {
type filter hook prerouting priority -300; policy accept;
fib saddr . iif oif 0 udp dport 1337 counter packets 1 bytes 48
fib saddr . iif oif "enp0s5" udp dport 1337 counter packets 0 bytes 0
fib saddr . iif oif "enp0s6" udp dport 1337 counter packets 0 bytes 0
}
}
Let's add a default route now:
> ip -6 r add default via fd11::1
> ip -6 r
fd00::/64 dev enp0s5 proto kernel metric 256 pref medium
fd11::/64 dev enp0s6 proto kernel metric 256 pref medium
fe80::/64 dev enp0s5 proto kernel metric 256 pref medium
fe80::/64 dev enp0s6 proto kernel metric 256 pref medium
default via fd11::1 dev enp0s6 metric 1024 pref medium
We reset the counters, repeat the Scapy `sendp()` from above and look at the
counters again:
> nft list chain inet raw prerouting
table inet raw {
chain prerouting {
type filter hook prerouting priority -300; policy accept;
fib saddr . iif oif 0 udp dport 1337 counter packets 0 bytes 0
fib saddr . iif oif "enp0s5" udp dport 1337 counter packets 0 bytes 0
fib saddr . iif oif "enp0s6" udp dport 1337 counter packets 1 bytes
48
}
}
By adding a route which should have nothing to do with the respective lookup,
we were able to change the result of our "fib" expressions!
For reference, here's a route lookup for the source address:
> ip -6 r get fd00::1
fd00::1 from :: dev enp0s5 proto kernel src fd00::3 metric 256 pref medium
No surprises here, so I suppose the bug is in Netfilter or nftables.
Everything works as expected for IPv4. I observed this with Kernel
4.14.0-3-amd64 and nft 0.8.1 on Debian Testing.
--
You are receiving this mail because:
You are watching all bug changes.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.netfilter.org/pipermail/netfilter-buglog/attachments/20180130/288f3232/attachment.html>
More information about the netfilter-buglog
mailing list