On Mon, Jul 03, 2017 at 11:13:30PM +0200, Patrik Lundin wrote: > On Sun, Jul 02, 2017 at 06:04:30PM +0000, Florian Obser wrote: > > > It'd be nice if somebody could tell us what the RFCs say about this > > > case. Florian do you have an idea? Should we fix something or should > > > Marc tell his provider to fix his setup? > > > > this was introduced by claudio@ in rev. 1.53 of nd6_nbr.c: > > > > If a neighbor solictation isn't from the unspecified address, make sure > > that the source address matches one of the interfaces address prefixes. > > From NetBSD, tested by todd@ and naddy@ > > > > > > netbsd added this in their rev 1.89 and 1.90: > > > > If a neighbor solictation isn't from the unspecified address, make sure > > that the source address matches one of the interfaces address prefixes. > > > > and: > > Generalize previous fix so that both NS and NA packets are checked. > > > > However, I don't get why. Other than being extra paranoia defending > > against a misbehaving router maybe?. We already check a hop limit of > > 255, so the packet had to be generated on-link and not forwarded by a > > router. > > > > This discussion reminded me of a similar thread a few years back: > http://marc.info/?l=openbsd-misc&m=136057739111931&w=2 > > It among other things brings up CVE-2008-2476. Maby some of it is > relevant now as well?
Aha, now I get it. It defends against overriding the neighbour cache for something attached to interface0 from interface1. We could try to make this smarter, because it actually does more. Which is the problem here, it defends against overriding (or setting) the neighbour cache for interface0 from interface0. However, let's look at the tcpdump output again: 12:30:08.321097 2a01:4f8:212:216c::1:443 > ff02::1:ff00:1: icmp6: neighbor sol: who has fe80::1 12:30:08.321669 2a01:4f8::a:21:b > 2a01:4f8:212:216c::1:443: icmp6: neighbor adv: tgt is fe80::1 [class 0xc0] This is not working and I have some suspicions why we get that answer: 1) the router probably does not have an address out of 2a01:4f8:212:216c::/64 configured 2) it sees a neihgbour sol from a global address for a link local address 3) uh oh, what should I do, it's probably bad to answer with a link local address to a global address (so can't use fe80::1, it would probably work though) let's use another global address we have lying around 4) openbsd goes: no no, you are not a neighbor, who are you? then later: 12:30:32.363219 fe80::3285:a9ff:fea4:ce5e > ff02::1:ff00:1: icmp6: neighbor sol: who has fe80::1 12:30:32.363746 fe80::1 > fe80::3285:a9ff:fea4:ce5e: icmp6: neighbor adv: tgt is fe80::1 [class 0xc0] Note that this time around we ask the same neighbour sol question, but from a link local address, and everything works. Basically the upstream router is in source address selection hell. Let's use a link local address as source instead. Not sure if this is the best place to do it though. Marc, does this fix your problem? Comments, OKs? diff --git nd6_nbr.c nd6_nbr.c index fa8d3ed1472..086eeef87ba 100644 --- nd6_nbr.c +++ nd6_nbr.c @@ -445,7 +445,8 @@ nd6_ns_output(struct ifnet *ifp, struct in6_addr *daddr6, * We use the source address for the prompting packet * (saddr6), if: * - saddr6 is given from the caller (by giving "ln"), and - * - saddr6 belongs to the outgoing interface. + * - saddr6 belongs to the outgoing interface and + * - if taddr is link local saddr6 musst be link local as well * Otherwise, we perform the source address selection as usual. */ struct ip6_hdr *hip6; /* hold ip6 */ @@ -453,9 +454,12 @@ nd6_ns_output(struct ifnet *ifp, struct in6_addr *daddr6, if (ln && ln->ln_hold) { hip6 = mtod(ln->ln_hold, struct ip6_hdr *); - if (sizeof(*hip6) <= ln->ln_hold->m_len) + if (sizeof(*hip6) <= ln->ln_hold->m_len) { saddr6 = &hip6->ip6_src; - else + if (saddr6 && IN6_IS_ADDR_LINKLOCAL(taddr6) && + !IN6_IS_ADDR_LINKLOCAL(saddr6)) + saddr6 = NULL; + } else saddr6 = NULL; } else saddr6 = NULL; -- I'm not entirely sure you are real.