Linux – how to configure radvd for linux ipv6 router towards upstream dsl gateway

ipv6linuxradvdrouter

I am trying to get my home Linux router to also support ipv6 on the home network.

I have a NVG599 DSL router acting as a GW to the public internet, and then my Linux router with two interfaces: eth0 towards the home network and eth1 towards the DSL router.

HOME network <—-eth0—–> LinuxRouter <——eth1——>DSLrouter –>>>>>

The DSL router is configured with a /64 network prefix from my ISP (assume it is 2001:0:0:1234::/64) and the DSL router has an ipv6 global address of 2001:0:0:1234::1. I have setup the Linux router with radvd to advertise this same /64 network prefix to eth0 towards the home LAN, and indeed I see the hosts on the LAN are able to auto configure their IP addresses. The advertisement also lists the Linux router as the default router for ::/0, and forwarding is setup so that it will send the packets to the DSL router.

The issue I have is that the DSL router is sending neighbor solicitations packets on eth1 when it gets inbound packets from the internet, and those neighbor solicitations are not being passed from eth1 -> eth0 on the Linux router. I am thinking that this is occurring because the DSL router thinks it is directly connected to the home network (which is how it would normally be in 99% of home networks without a Linux router in the middle).

After spending 2 days trying to figure it out, the answer so far has eluded me. I am hoping that there is some way to send a router advertisement using radvd to the DSL router to tell it to route all packets for the /64 prefix via the Linux Router. Currently the router advertisement sent by the Linux Router is configured with the /64 prefix being sent towards the DSL router with:

interface eth1
{
    AdvSendAdvert on;
    MinRtrAdvInterval 3;
    MaxRtrAdvInterval 10;
    route 2001:0:0:1234::/64 {
    };

};

I would think that this should be enough to get the DSL router to forward all packets to the network, but I still see the neighbor soliciations.

I see the DSL router has IP pass through settings with ability to set a "default server", but those seem to apply only to IPv4. Assuming that the DSL router is not honoring my RA, I suppose I could setup ipv6 multicast forwarding using 'xorb' on my Linux router but wondering if there are other options.

Best Answer

The issue I have is that the DSL router is sending neighbor solicitations packets on eth1 when it gets inbound packets from the internet, and those neighbor solicitations are not being passed from eth1 -> eth0 on the Linux router.

That's normal. Neighbour solicitations work just like ARP queries – they translate an IP address to a MAC address, and therefore they only make sense within the same broadcast domain. It makes no sense for a router to forward them.

(Though in some situations a router can proxy them, as described at the end, but... leave that for plan C.)

I am thinking that this is occurring because the DSL router thinks it is directly connected to the home network (which is how it would normally be in 99% of home networks without a Linux router in the middle).

Yes, and you never told it otherwise.

So your current situation is that the same IP subnet is being used by two different networks, and you're expecting the Linux router to work as a bridge... Which is almost the exact opposite of a router.

(If the confusing part is IPv6, think about the whole setup in IPv4 terms, as routing is more or less the same in both, and ND is mostly equivalent to ARP. So if you wouldn't use the same 192.168.1.0 subnet in v4...)


Your best course of action is to obtain a second /64, and use that for your Linux router's eth1 network. (If the DSL router obtains its prefix via DHCPv6-PD, it might be possible to trick it into requesting a second one.) The difference though is that the 2nd /64 wouldn't be used directly on an interface but instead routed towards the Linux router's address.

For example:

  • DSL router has 2001:db8:0:0:a:b:c:d on the WAN interface.
  • DSL router obtains 2001:db8:10:0::/64 from the ISP, self-assigns 2001:db8:10:0::1/64 on the LAN interface, and sends Router Advertisements for it.
  • Linux router autoconfigures 2001:db8:10:0:x:y:z:t on eth1 based on RAs.
  • Linux router obtains 2001:db8:10:1::/64 from the ISP (somehow), self-assigns 2001:db8:10:1::1/64 on the eth0 interface, and radvd sends Router Advertisements for that – not for the first subnet.
  • The DSL router needs a route like "2001:db8:10:1::/64 via 2001:db8:10:0:x:y:z:t" so that all traffic for the 2nd subnet is forwarded towards the Linux router.

(Apologies for the not-very-clear example.)

Sometimes the ISP delegates a whole /60 or even /56 to you, and routes all of it towards the DSL router. In that case you could just set up the 2nd subnet without any DHCPV6-PD magic. Really though I cannot provide an good "generic" answer here as it's both ISP-dependent and CPE-dependent.


If obtaining a second /64 prefix is impossible, other possible options are:

  • Turn the Linux system into a pure bridge, without any routing functionality.

  • Use other sources for obtaining additional /64's, such as a tunnel provider (or 6to4). The existing tunnel services are going to work much more reliably (except for some extra latency) than the hacks described below.

  • Make the DSL router only obtain the /64 but not configure it for LAN. (Depends on how flexible the router is.) Instead, again set up a route for that /64 via your Linux system's eth0 link-local address, and likewise set up a route on the Linux system for ::/0 via the DSL router's LAN link-local address. As a result, the /64 will be only used in the 2nd subnet, and the 1st one won't have any public prefix at all.

  • Continue with your current setup, but install 'ndppd' to perform Neighbour Discovery proxying. (No, multicast forwarding won't do as ND packets often have link-local source addresses.) Be careful with this, it can make things really confusing.

  • Use private (ULA) addresses for the 2nd LAN, and enable 1-to-many NAT (masquerading) on the Linux router...losing most of IPv6's usefulness in the process. (Yes, officially NAT doesn't exist in IPv6, but that didn't stop Linux netfilter/iptables from giving in and implementing it.)

Related Question