Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
From: Michael UlmerDate: Tue, 16 May 2017 15:37:39 + > Blast from the past. 10 years back Wei Dong submitted the patch found > (amongst several places) here: > http://lists.openwall.net/netdev/2007/01/30/20 > > Problem: > I have a firewall rule that DNATs ipv6 traffic from a destination address to > ::1. The route lookup gives me the Main table & forwards that DNAT'd traffic > instead of sending it to local process. > > Example: > Looking at this from a netfilter point of view, a client (IP of fd00::5) > requests a web page at [2000::25:0:0:1]:8080. The firewall rule DNATs it to > ::1 (note that I threw a -j TRACE in raw's REROUTING). > TRACE: nat:PREROUTING:rule:2 SRC=fd00::5 DST=2000::25:0:0:1 > TRACE: mangle:FORWARD:rule:1 SRC=fd00::5 DST=::1 > > The patch is verbatim (as is the subject line for this > email). Traffic DNAT'd to ::1 now goes to mangle's INPUT chain after > routing decision. I'm not sure why it was removed--I'm assuming it > was an accident--as I can't find a record in the mailing list > archive. It's not by accident, he received feedback from Yoshifuji and suggested alternative ways to fix his problem: http://marc.info/?l=linux-netdev=117020569620697=2 In fact, Yoshifuji stated that some of the behaviors are indeed intentional.
[Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Blast from the past. 10 years back Wei Dong submitted the patch found (amongst several places) here: http://lists.openwall.net/netdev/2007/01/30/20 Problem: I have a firewall rule that DNATs ipv6 traffic from a destination address to ::1. The route lookup gives me the Main table & forwards that DNAT'd traffic instead of sending it to local process. Example: Looking at this from a netfilter point of view, a client (IP of fd00::5) requests a web page at [2000::25:0:0:1]:8080. The firewall rule DNATs it to ::1 (note that I threw a -j TRACE in raw's REROUTING). TRACE: nat:PREROUTING:rule:2 SRC=fd00::5 DST=2000::25:0:0:1 TRACE: mangle:FORWARD:rule:1 SRC=fd00::5 DST=::1 The patch is verbatim (as is the subject line for this email). Traffic DNAT'd to ::1 now goes to mangle's INPUT chain after routing decision. I'm not sure why it was removed--I'm assuming it was an accident--as I can't find a record in the mailing list archive. diff --git a/gpl/kernel/linux/net/ipv6/route.c b/gpl/kernel/linux/net/ipv6/route.c index 3809ca2..2a2563f 100644 --- a/gpl/kernel/linux/net/ipv6/route.c +++ b/gpl/kernel/linux/net/ipv6/route.c @@ -611,7 +611,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int m; m = rt6_check_dev(rt, oif); - if (!m && (strict & RT6_LOOKUP_F_IFACE)) + if (!m && (rt->rt6i_flags & RTF_CACHE) && (strict & RT6_LOOKUP_F_IFACE)) return RT6_NUD_FAIL_HARD; #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; __ Mike Ulmer
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
From: YOSHIFUJI Hideaki [EMAIL PROTECTED] Date: Wed, 31 Jan 2007 14:42:50 +0900 (JST) [IPV6] ROUTE: Do not route packets to link-local address on other device. With help from Wei Dong [EMAIL PROTECTED]. Signed-off-by: YOSHIFUJI Hideaki [EMAIL PROTECTED] Applied, thank you. - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
In article [EMAIL PROTECTED] (at Tue, 30 Jan 2007 16:55:12 +0900), Wei Dong [EMAIL PROTECTED] says: Hello, Mr yoshfuji Take ping6 for example. Asumming there is a router which has 2 NICs. eth0 on router has ipv6 addr fe80::20c:29ff:fe24:fa0a, eth1 on router has ipv6 addr fe80::20c:29ff:fe24:fa14. Also there is a host connected to router's eth0, and the host's ipv6 addr is fe80::200:ff:fe00:100. We ping6 : I still need more precise figure. Please draw complete box for the 2-3 boxes (pinger, router (and the destination)), link(s) and interfaces. +-+ |Router | +---+-+---+ eth0| |eth1 | | eth0| +---+-+ |Host1| +-+ Host1 eth0: fe80: Router eth0: fe80: Router eth1: fe80:... Or, something like that I think you may use other tool such as tgif etc. --yoshfuji - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Hello, Mr yoshfuji: Thanks for your reply. The following is the figure. || || | Router | |||---| | |--| |--| || other | | | eth0 |---| eth1 |--||network| | |--| ||--| ||---| |--|--||-| | v| | fe80::20c:29ff:fe24:fa0a | | | | | | | | | | | | v | fe80::20c:29ff:fe24:fa14 | | |--|--| | |--| | | | eth0 |---|---fe80::200:ff:fe00:100 | |--| | | | |Host | |-| Host eth0: fe80::200:ff:fe00:100 Router eth0: fe80::20c:29ff:fe24:fa0a Router eth1: fe80::20c:29ff:fe24:fa14 We ping6 from host's eth0 to Router's eth1. Echo Request's src addr = fe80::200:ff:fe00:100, dst addr = fe80::20c:29ff:fe24:fa14. And Kernel just send ICMPv6 redirect packet and then forward the Echo Request to router's eth0. If we run tcpdump on Host eth0, we can receive the ICMPv6 Redirect packet. And if we send NA which advertises fe80::20c:29ff:fe24:fa14 MAC address(this is very easy for v6eval tool), we also can receive the forwarded Echo Request(src:fe80::200:ff:fe00:100 dst is fe80::20c:29ff:fe24:fa14). I dived into the kernel, and found that maybe function rt6_score_route() has problems. In rt6_score_route(), if rt6_check_dev() return 0, and the dst ipv6 addr is link local addr, rt6_socre_route() return -1 directly. I think this is not correct, we should return -1 only if the entry is in the route cache, and the dst addr is link local addr. Only entries in cache may select wrong IPv6 Link Local NIC for a link local dst addr. because they are copied from static IPv6 fib table entries. Hello, Mr yoshfuji Take ping6 for example. Asumming there is a router which has 2 NICs. eth0 on router has ipv6 addr fe80::20c:29ff:fe24:fa0a, eth1 on router has ipv6 addr fe80::20c:29ff:fe24:fa14. Also there is a host connected to router's eth0, and the host's ipv6 addr is fe80::200:ff:fe00:100. We ping6 : I still need more precise figure. Please draw complete box for the 2-3 boxes (pinger, router (and the destination)), link(s) and interfaces. +-+ |Router | +---+-+---+ eth0| |eth1 | | eth0| +---+-+ |Host1| +-+ Host1 eth0: fe80: Router eth0: fe80: Router eth1: fe80:... Or, something like that I think you may use other tool such as tgif etc. --yoshfuji - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
In article [EMAIL PROTECTED] (at Wed, 21 Feb 2007 09:57:12 -0500), weidong [EMAIL PROTECTED] says: The following is the figure. : Host eth0: fe80::200:ff:fe00:100 Router eth0: fe80::20c:29ff:fe24:fa0a Router eth1: fe80::20c:29ff:fe24:fa14 Other network | | eth1 +++ | Router | +++ | eth0 | | eth0 +++ | Host | +-+ We ping6 from host's eth0 to Router's eth1. Echo Request's src addr = fe80::200:ff:fe00:100, dst addr = fe80::20c:29ff:fe24:fa14. And Kernel just send ICMPv6 redirect packet and then forward the Echo Request to router's eth0. If we run tcpdump on Host eth0, we can receive the ICMPv6 Redirect packet. And if we send NA which advertises This is correct, and intended behavior. fe80::20c:29ff:fe24:fa14 MAC address(this is very easy for v6eval tool), we also can receive the forwarded Echo Request(src:fe80::200:ff:fe00:100 dst is fe80::20c:29ff:fe24:fa14). Well, this is known issue, actually. While this cannot happen in normal operation, we should NOT accept such traffic. :-) Here is the (untested) fix. - [IPV6] ROUTE: Do not accept traffic for link-local address on different interface. Signed-off-by: YOSHIFUJI Hideaki [EMAIL PROTECTED] --- diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5f0043c..a7468e0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -311,12 +311,19 @@ static inline void rt6_probe(struct rt6_info *rt) static int inline rt6_check_dev(struct rt6_info *rt, int oif) { struct net_device *dev = rt-rt6i_dev; + int ret = 0; + + if (dev-flags IFF_LOOPBACK) { + if (!WARN_ON(rt-rt6i_idev == NULL) + rt-rt6i_idev-dev-ifindex == oif) + ret = 1; + else + return 0; + } if (!oif || dev-ifindex == oif) return 2; - if ((dev-flags IFF_LOOPBACK) - rt-rt6i_idev rt-rt6i_idev-dev-ifindex == oif) - return 1; - return 0; + + return ret; } static int inline rt6_check_neigh(struct rt6_info *rt) -- YOSHIFUJI Hideaki @ USAGI Project [EMAIL PROTECTED] GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Hello, Mr yoshfuji Thanks for your patch. I think maybe we checking oif first is better, and WARN_ON in function rt6_score_route(). The following is my patch Signed-off-by: Wei Dong [EMAIL PROTECTED] diff -ruN old/net/ipv6/route.c new/net/ipv6/route.c --- old/net/ipv6/route.c2007-02-16 13:46:33.0 -0500 +++ new/net/ipv6/route.c2007-02-16 13:44:27.0 -0500 @@ -309,12 +309,21 @@ static int inline rt6_check_dev(struct rt6_info *rt, int oif) { struct net_device *dev = rt-rt6i_dev; - if (!oif || dev-ifindex == oif) + int ret = 0; + + if (!oif) return 2; + if ((dev-flags IFF_LOOPBACK) rt-rt6i_idev rt-rt6i_idev-dev-ifindex == oif) - return 1; - return 0; + ret = 1; + else + return 0; + + if (dev-ifindex == oif) + return 2; + + return ret; } static int inline rt6_check_neigh(struct rt6_info *rt) @@ -339,8 +348,11 @@ int m, n; m = rt6_check_dev(rt, oif); - if (!m (strict RT6_LOOKUP_F_IFACE)) + if (!m (strict RT6_LOOKUP_F_IFACE)) { + WARN_ON(rt-rt6i_dev-flags IFF_LOOPBACK); return -1; + } + #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt-rt6i_flags)) 2; #endif On Wed, 2007-01-31 at 13:00 +0900, Wei Dong wrote: In article [EMAIL PROTECTED] (at Wed, 21 Feb 2007 09:57:12 -0500), weidong [EMAIL PROTECTED] says: The following is the figure. : Host eth0: fe80::200:ff:fe00:100 Router eth0: fe80::20c:29ff:fe24:fa0a Router eth1: fe80::20c:29ff:fe24:fa14 Other network | | eth1 +++ | Router | +++ | eth0 | | eth0 +++ | Host | +-+ We ping6 from host's eth0 to Router's eth1. Echo Request's src addr = fe80::200:ff:fe00:100, dst addr = fe80::20c:29ff:fe24:fa14. And Kernel just send ICMPv6 redirect packet and then forward the Echo Request to router's eth0. If we run tcpdump on Host eth0, we can receive the ICMPv6 Redirect packet. And if we send NA which advertises This is correct, and intended behavior. fe80::20c:29ff:fe24:fa14 MAC address(this is very easy for v6eval tool), we also can receive the forwarded Echo Request(src:fe80::200:ff:fe00:100 dst is fe80::20c:29ff:fe24:fa14). Well, this is known issue, actually. While this cannot happen in normal operation, we should NOT accept such traffic. :-) Here is the (untested) fix. - [IPV6] ROUTE: Do not accept traffic for link-local address on different interface. Signed-off-by: YOSHIFUJI Hideaki [EMAIL PROTECTED] --- diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5f0043c..a7468e0 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -311,12 +311,19 @@ static inline void rt6_probe(struct rt6_info *rt) static int inline rt6_check_dev(struct rt6_info *rt, int oif) { struct net_device *dev = rt-rt6i_dev; + int ret = 0; + + if (dev-flags IFF_LOOPBACK) { + if (!WARN_ON(rt-rt6i_idev == NULL) + rt-rt6i_idev-dev-ifindex == oif) + ret = 1; + else + return 0; + } if (!oif || dev-ifindex == oif) return 2; - if ((dev-flags IFF_LOOPBACK) - rt-rt6i_idev rt-rt6i_idev-dev-ifindex == oif) - return 1; - return 0; + + return ret; } static int inline rt6_check_neigh(struct rt6_info *rt) - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
In article [EMAIL PROTECTED] (at Wed, 21 Feb 2007 23:51:45 -0500), weidong [EMAIL PROTECTED] says: Thanks for your patch. I think maybe we checking oif first is better, and WARN_ON in function rt6_score_route(). Please remove WARN_ON. Otherwise, I'm fine with it. --yoshfuji - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Hi, all When I tested linux-2.6.19.2, and found maybe there're some packet routing bugs in linux kernel. My test topology is shown as the following: eth0: fe80::20c:29ff:fe24:fa0a | eth1: fe80::20c:29ff:fe24:fa14 | | | | | | | LAN1 |LAN2 | | - ^ | Send Echo Request(src addr = fe80::200:ff:fe00:100) Now we send Echo Request to eth1(ipv6 src addr is fe80::200:ff:fe00:100, ipv6 dst addr is fe80::20c:29ff:fe24:fa14) on LAN1. Linux will send ICMPv6 Redirect Packet to us. And the TargetAddress = fe80::20c:29ff:fe24:fa14, DestinationAddress = fe80::20c:29ff:fe24:fa14. Obviously, Linux considers that fe80::200:ff:fe00:100 and fe80::20c:29ff:fe24:fa14 is on the SAME link(LAN0). In fact, kernel invoke function ip6_foward(). When Linux decides whether or not making use of a rt6_info entry, it will match the rt-rt6i_idev and rt-rt6_dev. This is done in function rt6_check_dev(). If nothing matched, rt6_check_dev() return 0. Then function rt6_score_route() will check whether the matched ipv6 addr (fe80::20c:29ff:fe24:fa14 in our example) is a link local ipv6 address. If it is a link local address, and rt-rt6i_idev rt-rt6_dev match failed -- rt6_check_dev() return 0. Function rt6_score_route() return -1 directly. I think here is a problem. When kernel match eth1 addr with rt6_info entries, it will lookup in local_table first. In rt6_check_dev() matching rt-rt6i_idev rt- rt6_dev will fail. The reason is oif = 2 , rt-rt6i_idev-dev-ifindex is 3 and rt-rt6i_dev-ifindex is 1. I think even this match failed, rt6_score_route() should not return -1, but return 0. And I think check for RT6_LOOKUP_F_IFACE flag isn't needed here. Checking for this flag is only needed in route cache when matching dst addr. Due to the reason mentioned above, all entries in local table matching dst addr fe80::20c:29ff:fe24:fa14 are failed. And then kernel matches main table. fe80::/64 entry in main table will match successfully. Later ip6_rt_copy() will copy the function pointer rt-u.dst.input. Obviously rt-u.dst.input in main table is ip6_forward(). The following is my patch. signed-off-by: Wei Dong [EMAIL PROTECTED] diff -ruN old/net/ipv6/route.c new/net/ipv6/route.c --- old/net/ipv6/route.c2007-01-10 14:10:37.0 -0500 +++ new/net/ipv6/route.c2007-01-17 18:24:51.336774016 -0500 @@ -343,7 +343,7 @@ int m, n; m = rt6_check_dev(rt, oif); - if (!m (strict RT6_LOOKUP_F_IFACE)) + if (!m (rt-rt6i_flags RTF_CACHE) (strict RT6_LOOKUP_F_IFACE)) return -1; #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt-rt6i_flags)) 2; - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Hello. In article [EMAIL PROTECTED] (at Wed, 21 Feb 2007 02:24:26 -0500), weidong [EMAIL PROTECTED] says: eth0: fe80::20c:29ff:fe24:fa0a | eth1: fe80::20c:29ff:fe24:fa14 | | | | | | | LAN1 |LAN2 | | - ^ | Send Echo Request(src addr = fe80::200:ff:fe00:100) Sorry, I could not understand this figure Would you elaborate this? --yoshfuji - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Patch][IPv6] Fix wrong routing mechanism for Link Local IPv6 packets
Hello, Mr yoshfuji Take ping6 for example. Asumming there is a router which has 2 NICs. eth0 on router has ipv6 addr fe80::20c:29ff:fe24:fa0a, eth1 on router has ipv6 addr fe80::20c:29ff:fe24:fa14. Also there is a host connected to router's eth0, and the host's ipv6 addr is fe80::200:ff:fe00:100. We ping6 to router's eth1(ipv6 addr fe80::20c:29ff:fe24:fa14). But now Linux kernel deals with this kind of packet incorrectly. Router forward the Echo request to eth0. And send ICMP redirect packet to the host. In ICMP redirect packt TargetAddress =fe80::20c:29ff:fe24:fa14, DestinationAddress = fe80::20c:29ff:fe24:fa14. So I think Linux kernel considers that fe80::200:ff:fe00:100 and fe80::20c:29ff:fe24:fa14 are neighbors. I dived into the kernel, and found that maybe function rt6_score_route() has problems. In rt6_score_route(), if rt6_check_dev() return 0, and the dst ipv6 addr is link local addr, rt6_socre_route() return -1 directly. I think this is not correct, we should return -1 only if the entry is in the route cache, and the dst addr is link local addr. Only entries in cache will select wrong IPv6 Link Local NIC for a link local addr, because they are copied from static IPv6 fib tables. - Original Message - Hello. In article [EMAIL PROTECTED] (at Wed, 21 Feb 2007 02:24:26 -0500), weidong [EMAIL PROTECTED] says: eth0: fe80::20c:29ff:fe24:fa0a | eth1: fe80::20c:29ff:fe24:fa14 | | | | | | | LAN1 |LAN2 | | - ^ | Send Echo Request(src addr = fe80::200:ff:fe00:100) Sorry, I could not understand this figure Would you elaborate this? --yoshfuji - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html