[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <3D696DFB-7D22-44A6-9869-D2EFDEBDDEEB@juniper.net>
Date: Wed, 2 Dec 2020 11:31:42 +0000
From: Preethi Ramachandra <preethir@...iper.net>
To: "dsahern@...il.com" <dsahern@...il.com>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Jimmy Jose <jimmyj@...iper.net>,
Reji Thomas <rejithomas@...iper.net>,
Yogesh Ankolekar <ayogesh@...iper.net>
Subject: Linux IPV6 TCP egress path device passed for LOCAL_OUT hook is
incorrect
Hi David Ahren,
In TCP egress path for ipv6 the device passed to NF_INET_LOCAL_OUT hook should be skb_dst(skb)->dev instead of dst->dev.
https://elixir.bootlin.com/linux/latest/source/net/ipv6/ip6_output.c#L202
struct dst_entry *dst = skb_dst(skb); >>> This may return slave device.
In this code path the DST Dev and SKB DST Dev will be set to VRF master device.
ip6_xmit->l3mdev_ip6_out->vrf_l3_out->vrf_ip6_out (This will set SKB DST Dev to vrf0)
However, once the control passes back to ip6_xmit, https://elixir.bootlin.com/linux/latest/source/net/ipv6/ip6_output.c#L280
Slave device is passed to LOCAL_OUT nf_hook instead of skb_dst(skb)->dev.
return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
net, (struct sock *)sk, skb, NULL, dst->dev, <<<< Should be skb_dst(skb)->dev
dst_output);
This will cause a bug in firewall filters. nf_hook->ip6table_mangle_hook->ip6table_filter_hook (Device passed is slave device). If the firewall filter rule is configured with device as VRF it will fail to apply the filter. As per Linux documentation filters should work for VRF devices.
Firewall Rule:
ip6tables -A OUTPUT -o vrf0 -m comment --comment F-outer6_T-B-lo0_I-1001 -j outer6 (or -A OUTPUT -o vrf0 -m mark --mark 0x1000000 -m comment --comment F-outer6_T-B-lo0_I-1001 -j outer6 (Rule fails to apply for TCP packets)
Linux firewall doc:
https://www.kernel.org/doc/Documentation/networking/vrf.txt
[2] Iptables on ingress supports PREROUTING with skb->dev set to the real
ingress device and both INPUT and PREROUTING rules with skb->dev set to
the VRF device. For egress POSTROUTING and OUTPUT rules can be written
using either the VRF device or real egress device.
Comparison on device passed to LOCALOUT hook for IPV4 TCP and IPV6 raw/udp scenarios.
TCP IPV4 egress : In __ip_local_out to NF_INET_LOCAL_OUT skb_dst(skb)->dev is passed.
https://elixir.bootlin.com/linux/latest/source/net/ipv4/ip_output.c#L115
return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
net, sk, skb, NULL, skb_dst(skb)->dev, << will be set to vrf0
dst_output);
}
Raw/UDP V6 egress path: skb_dst(skb)->dev is passed onto NF_INET_LOCAL_OUT
rawv6_sendmsg-> ip6_send_skb-> ip6_local_out-> __ip6_local_out (LOCAL_OUT hook, device passed is SKB DST which is VRF)->nf_hook-> ip6table_mangle_hook->ip6table_filter_hook
https://elixir.bootlin.com/linux/latest/source/net/ipv6/output_core.c#L167
return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
net, sk, skb, NULL, skb_dst(skb)->dev,
dst_output);
Thanks,
Preethi
Juniper Business Use Only
Powered by blists - more mailing lists