IPv6, point to point links, and subnet lengths

December 2, 2016

One of the things that my recent IPv6 work has given me is plenty of what we call 'learning experiences'. The latest one concerns a little detail of what I wrote earlier, where I casually said:

[...] I discovered my next configuration mistake, which was the subnet length on my IPv6 address configured on my DSL PPPoE link; for reasons lost in the depths of history, it had been configured with a /64 subnet length instead of being set to be a single IPv6 address. [...]

After I found and fixed that, at last everything worked [...]

That turned out to be a little bit optimistic.

In Linux IPv4 networking, you can definitely have the same IPv4 address attached to an Ethernet interface, with a /24 netmask, and to a point-to-point link, as a /32 single address. I have essentially this setup today on one machine with my IPSec tunnel. This works reliably and I've never had any problems with it.

As far as I can tell, this is not true of IPv6 on Linux. I believe that some of the time you can do this, because I'm pretty sure that I managed to do it at the time that I wrote that first entry. However, some of the time it appears that you can't, or at least I can't; if I have a given IPv6 address on an Ethernet interface as a /64 and I try to put it on a PPP interface as a /128, it quietly gets converted into a /64 (and then things explode, as before). This state seems to be at least somewhat sticky, in that I couldn't fix it with manual use of the ip command; instead I got various puzzling error messages (which I neglected to write down, because I was focused on solving the problem instead of writing a blog entry).

(I think it may have been 'RTNETLINK answers: Cannot assign requested address' when I was trying to delete the /64 IPv6 off the PPP link. In hindsight, maybe this meant that parts of the system thought it wasn't a /64 and parts felt otherwise.)

Since IPv6 addresses are extremely plentiful, my solution was simple; I just gave my inside Ethernet interface a different IPv6 address in my /64. This seems to have made everything happy, although it made me shuffle a few things around in my overall configuration; I changed Unbound to listen on this IPv6 address instead of the PPP one, and then I changed radvd to give out this address as the RDNSS address. My PPP link now has my 'router' IPv6 IP as a /128, my Ethernet has a /64, and things still do SLAAC and can talk to the world via IPv6.

(In thinking about it, possibly things would have worked just as well without changing the Unbound IPv6 address. After all, the 'router' IPv6 address is still perfectly reachable, it's just not the address associated with the Ethernet interface.)

One of the things I've discovered as a result of this is that I don't actually understand how IPv6 interacts with point to point links. A conventional IPv4 PtP link is intrinsically unicast to the peer IP; there is nothing else there, so a netmask doesn't really make sense in general. This is clearly not how my IPv6 PPP link is working; for a start, ifconfig and ip don't list a peer IPv6 address (and the link has a link-local IPv6 address too).

In fact now I wonder if my PPP link needs to have a public IPv6 address associated with it at all, or it's enough to have my default IPv6 route pointed through it. In the old days I had to put my public IPv6 address on the PPP link because I wasn't putting it anywhere else, but that's not applicable now that I'm also putting an IPv6 address on my Ethernet interface.

(Some brief testing suggests that it doesn't need a public IPv6 address. So it may be that I have been doing this totally backwards from the start and I'm now very slowly and incrementally evolving my configuration towards what it should be to be proper.)

I once did some reading about how IPv6 worked, but clearly not enough of it stuck in my head. I should probably do it again, although it's hard to feel motivated to take another slog at a large block of information that didn't stick well enough the first time around.

Comments on this page:

By Ewen McNeill at 2016-12-02 01:33:08:

Generally you can route straight down point-to-point links (such as PPP, SLIP, etc), just by telling your device to route into the point-to-point link. Being point to point, there's only one place the traffic can come out again, so there's no need to further identify where it's going -- the device at the other end of the point to point links is going to have to make its own routing decision anyway. Not everything actually supports unnumbered point-to-point links, but like IPv4 /31 linknets, supporting unnumbered point-to-point links is more common than it used to be due to IPv4 shortages. (And it's only your end that matters -- at the point you get it into the tunnel, the other end has no way to tell what it was routed to; it just receives a frame and decides what to do with it from the frame headers.)

On a broadcast medium (eg, Ethernet) you need a linknet in order to kick off the MAC lookup (ie, ARP, etc) to find out how to properly address it across the linknet so it'll go out the right switch port and be recognised by the destination NIC. But again, once the remote NIC has been persuaded to push it through to the internal processing... the remote device is making its own routing decision, so the address it was routed to no longer matters: you can route it to anything providing it goes to the right MAC address.

FWIW, "best practice" for IPv6 is to give each customer more than a /64 (eg, /60, /56, etc), so that they can have their own subnets, linknet ranges, etc. And across a broadcast medium people are leaning towards using /127s for linknets; since using a /64 for a linknet seems excessive! But a lot of the early end-consumer facing deployments are pretty stingy about address space and only allocated a /64, because... not sure. Maybe just IPv4-driven assumptions that they'd run out of addresses.

Anyway, yes, if your system works with an unnumbered PPP interface, and a default pointed down the PPP interface, then definitely just put the single /64 you got assigned on your internal interface. It appears your provider is routing that whole /64 to you down the PPP link anyway.


By dwfreed at 2016-12-02 13:13:51:

You can add /128 IPv6 addresses, you just need to be explicit about subnet mask, eg:

ip addr add 2001:db8::2/128 dev ppp0

By Alex at 2016-12-02 15:21:59:

I just gave my inside Ethernet interface a different IPv6 address in my /64

I generally like to treat p-t-p links the same as Ethernet links for addressing, because p-t-p lets you get away with things that you can't on a broadcast link and learning a method that doesn't work on both seems like a good way to have problems when you're dealing with an all-Ethernet network. If you do that, then this sentence should've set off a couple of red flags.

The PPP interface and the LAN are different networks and thus need separate /64s, in the same way they'd have separate /24s in v4. But also, you shouldn't be using addresses from your own allocation on your WAN. It's your provider's responsibility to number that interface, not yours! They could use a /64 (not one from the range you get routed, a different one), or use the link-locals, or indeed on a p-t-p link you can run without any addressing on the link at all (since you don't need the IP to look up a MAC like on Ethernet), but either way it should be them picking the addressing for it.

If you have no LAN interface at all, I'd argue that a /128 on lo would make the most sense (but on Linux, /128s function the same no matter what interface you put them on anyway).

how IPv6 interacts with point to point links

I believe the rule, for both v4 and v6, is basically "if the routing table selects the ppp interface, send the packet straight down the link instead of doing ARP/NDP for the IP". The peer IP is only there to give you an automatic route for that IP out of the ppp interface; it's never sent on the wire. (The logical conclusion is that you can set the peer IP to be whatever you like, and provided your routing table is still correct nothing will break.)

If you add an IP from a /64 to ppp0, then you get an automatic route for the /64 instead of for a single IP (which is exactly what you don't want when that /64 is your LAN /64), but it otherwise works the same.

(In fact I just discovered that you can do the same thing with v4. You could take from the LAN and put on ppp0 without specifying any sort of peer address, like with your previous non-functioning v6 setup... and get the predictable result.)

For PPP links, see "Using 127-Bit IPv6 Prefixes on Inter-Router Links":

On inter-router point-to-point links, it is useful, for security and other reasons, to use 127-bit IPv6 prefixes. Such a practice parallels the use of 31-bit prefixes in IPv4. This document specifies the motivation for, and usages of, 127-bit IPv6 prefix lengths on inter-router point-to-point links.

Basically you want a /127, not a /128.

In fact now I wonder if my PPP link needs to have a public IPv6 address associated with it at all [...]

Nope, not strictly necessary. You can have a "private" (ULA) address or a link-local (fe80::/10) address, and things should work just fine.

By cks at 2016-12-05 09:23:44:

My PPP software is assigning a link-local address to the PPP link already, so I think I'm set as far as that goes. I'm not sure where it's generating the address from, but presumably it knows what it's doing (or at least I hope it does; if I map the link-local address back to an Ethernet MAC using one of the online tools, the resulting OUI is unassigned).

Written on 02 December 2016.
« I suspect that lots of IPv6 hosts won't have reverse DNS
One reason why rogue wireless access points are a bigger risk at universities »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Dec 2 00:34:43 2016
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.