Setting up an IPv6 gateway on an Ubuntu 22.04 server with WireGuard

November 16, 2023

Recently we enabled IPv6 on one of our networks here (for initial testing purposes), but not the network that my office workstation is on. Naturally I decided that I wanted my office workstation to have IPv6 anyway, by using WireGuard to tunnel IPv6 to it from an IPv6 enabled Ubuntu 22.04 server on that network. For my sins, I also decided to do this the more or less proper way, which is to say through systemd-networkd, instead of through hand-rolled scripts.

(The absolutely proper way would be through Canonical's netplan, but netplan doesn't currently support WireGuard or some of the other features that I need, so I have to use systemd-networkd directly.)

The idea of the configuration is straightforward. My office workstation has an IPv6-only WireGuard connection to the Ubuntu server, a static IPv6 address in the subnet's regular /64 that's on the WireGuard interface, and a default IPv6 route through the WireGuard interface. The server does proxy NDP for my office workstation's static IPv6 address and then forwards traffic back and forth as applicable.

On the server, we have three pieces of configuration. First, we need to configure the WireGuard interface itself, in a networkd .netdev file:

[NetDev]
Name=ipv6-wg0
Kind=wireguard

[WireGuard]
PrivateKey=[... no ...]
ListenPort=51821

[WireGuardPeer]
PublicKey=[... also no ...]
AllowedIPs=<workstation IPv6>/128,fe80::/64
Endpoint=<workstation IPv4>:51821

We have to allow fe80::/64 as well as the global IPv6 address because in the end I decided to give this interface some IPv6 link local IPs.

The second thing we need is a networkd .network file to configure the server's side of the WireGuard interface. This must both set our local parameters and configure a route to the global IPv6 address of my workstation:

[Match]
Name=ipv6-wg0

[Network]
# Or make up a random 64 bit address
Address=fe80::1/64
IPForward=yes
# Disable things we don't want
# Some of this may be unnecessary.
DHCP=no
IPv6AcceptRouterAdvertisements=no
LLMNR=false

[Route]
Destination=<workstation IPv6>/128

[Link]
# Not sure of this value, safety precaution
MTUBytes=1359
RequiredForOnline=no

(If I was doing this for multiple machines, I think I would need one [Route] section per machine.)

The one thing left to do is make the server do proxy NDP, which has to be set on the Ethernet interface, not the WireGuard interface. In Ubuntu 22.04, server Ethernet interfaces are managed through netplan, but netplan has no support for setting up proxy NDP, although networkd .network files support this. So we must go behind netplan's back. In Ubuntu 22.04, netplan on servers creates systemd-networkd control files in /run/systemd/network, and these files have standard names; for example, if your server's active network interface is 'eno1', netplan will write a '10-netplan-eno1.network' file. Armed with this we can create a networkd dropin file in /etc/systemd/network/10-netplan-eno1.network.d that sets up proxy NDP, which we can call, say, 'ipv6-wg0-proxyndp.conf':

[Network]
IPForward=yes
IPv6ProxyNDP=yes
IPv6ProxyNDPAddress=<workstation IPv6>

With all of this set up (and appropriate configuration on my office workstation), everything appears to work fine.

(On my office workstation, the WireGuard interface is configured with both the workstation's link local IPv6 address, with a peer address of the server's link-local address, and its global IPv6 address.)

All of this is pretty simple once I write it out here, but getting to this simple version took a surprising amount of experimentation and a number of attempts. Although it didn't help that I decided to switch to link local addresses after I'd already gotten a version without them working.


Comments on this page:

There is a perhaps more general alternative, which is to use 6to4, either with the special address 192.88.99.1 or any other chosen locally:

http://www.sabi.co.uk/blog/12-two.html?120210#120210 http://www.sabi.co.uk/blog/12-fou.html?121029#121029

By cks at 2023-11-19 17:10:19:

I used 6to4 a fair while ago and wound up unhappy with it for an assortment of reasons, so I stopped after a while. It looks like I probably stopped using it in 2015 after using it for at least a couple of years.

In general one of my goals is to play around with real IPv6 at work, or as close to it as possible, including living within the university's IPv6 space and IPv6 connectivity. 6to4 would give me IPv6 in general, but it would rely on the IPv4 layer for routing into the IPv6 Internet. With the WireGuard approach I'm still relying on a bit of IPv4, but it's only between two of our subnets; once I get to the second subnet, it's true university IPv6 all the way out.

(And at some point we'll push IPv6 to the subnet that my office workstation lives on and I'll drop the IPv6 WireGuard tunnel.)

By Walex at 2023-11-20 18:28:15:

«it would rely on the IPv4 layer for routing into the IPv6 Internet [...] With the WireGuard approach I'm still relying on a bit of IPv4, but it's only between two of our subnets»

But that is what a VPN still does for you. With 6to4 you can have an IPv4 interface on a host for IPv4 and a native IPv6 one too (as long as the 6to4 gateway routes into it). That is described at the end of http://www.sabi.co.uk/blog/12-two.html?120210#120210

All 6to4 does is to allow IPv6 packets to traverse IPv4 areas by encapsulating them. Some years ago in a big university that could not yet afford to have dual-stack routers everywhere I even proposed it as a replacement for buying the expensive IPv6 upgrade. Fortunately the funding for the IPv6 upgrade arrived, but it would have worked well.

PS there is an interesting extension that I described later where it is even possible to use 6to4 with IPv4 NAT (if the IPv4 gateways helps a bit): http://www.sabi.co.uk/blog/16-two.html?161103#161103

PS BTW one interesting thing about WireGuard is that actually it works like IPsec-with-SSH-keys in "tunnel" mode and over UDP instead of over packet type 41. When I was reading the WireGuard docs I started to suspect that the author does not fully get the difference between IKE SAs in IPsec. However precisely because WireGuard works so much like IPsec I like it.

BTW in your configurations there is a controversial detail: some argue that IPv6 routable (not link-local) addresses should be at most /64 rather than /128.

From 193.219.181.219 at 2023-11-23 01:36:38:

All 6to4 does is to allow IPv6 packets to traverse IPv4 areas by encapsulating them.

Pedantically, that's 6in4. The term "6to4" is used specifically for 6in4 with the anycast 2002:: prefix and anycast 192.88.99.1 gateway. (Unless you're on Mikrotik RouterOS.)

PS BTW one interesting thing about WireGuard is that actually it works like IPsec-with-SSH-keys in "tunnel" mode and over UDP instead of over packet type 41.

That's not particularly surprising; it's not the first UDP-based tunnel and not even the 20th of its kind.

Of course, it would not make any sense for WireGuard to use protocol 41 because protocol 41 is "IP inside IP", with the raw inner IP header starting at payload offset 0, whereas as soon as you use any kind of encryption or other encapsulation that's no longer the case. Even IPsec does not use protocol 41 for ESP or AH encapsulated packets; (and for that matter, even IPsec supports ESP-over-UDP.)

BTW in your configurations there is a controversial detail: some argue that IPv6 routable (not link-local) addresses should be at most /64 rather than /128.

I don't think I've seen it being a controversial point for a very long time. You reserve a /64 per link, but you route whatever you want, with /127 seemingly being the accepted practice nowadays.

“All 6to4 does is to allow IPv6 packets to traverse IPv4 areas by encapsulating them.”

«Pedantically, that's 6in4. The term "6to4" is used specifically for 6in4 with the anycast 2002:: prefix and anycast 192.88.99.1 gateway.»

That seems to me looking at it in a purely formal way: it is the 2002:: prefix is what makes 6to4 really useful, not just granting each IPv4 address an IPv6 /48, pretty much transparently, but effectively marking 6to4 packets to be handled specially, again pretty much transparently; while the 192.88.99.1 is an optional detail, added just to have a common default.

Also as to formality, this document refers throughout to "6to4" and "2002::" but never mentions the optional 192.88.99.1 address:

https://www.rfc-editor.org/rfc/rfc3056 “IPv6 sites or hosts connected using this method do not require IPv4 compatible IPv6 addresses [MECH] or configured tunnels. In this way IPv6 gains considerable independence of the underlying wide area network and can step over many hops of IPv4 subnets. The abbreviated name of this mechanism is 6to4”

The optional address is defined as an optional extension of 6to4 in a different document:

https://www.rfc-editor.org/rfc/rfc3068 “This memo introduces a "6to4 anycast address" in order to simplify the configuration of 6to4 routers.”

"some argue that IPv6 routeable (not link-local) addresses should be at most /64 rather than /128."

«I don't think I've seen it being a controversial point for a very long time. You reserve a /64 per link, but you route whatever you want, with /127 seemingly being the accepted practice nowadays.»

Routing a prefix longer than /64 on the routeable internet is still rather unwise, some extensions/flavourings still like to stick stuff in the lower 64 bits. The only exception I can think of is indeed /127 for static P2P and to route /128 as an "identifier" in non-public intranets.

https://www.sabi.co.uk/blog/13-two.html?130712#130712

The "best practices" RFC talks about /64 for subnets, and it is unwise to route less than subnets on the public routable internet.

https://www.rfc-editor.org/rfc/rfc5375.html#page-10 “Based on RFC 3177 [RFC3177], 64 bits is the prescribed subnet prefix length to allocate to interfaces and nodes. [...] it might be possible that some future autoconfiguration mechanisms would allow longer than 64-bit prefix lengths to be used, the use of such prefixes is not recommended at this time.”

“On links where all the addresses are assigned by manual configuration, and all nodes on the link are routers (not end hosts) that are known by the network, administrators do not need any of the IPv6 features that rely on /64 subnet prefixes, this can work. Using subnet prefixes longer than /64 is not recommended for general use, and using them for links containing end hosts would bean especially bad idea, as it is difficult to predict what IPv6 features the hosts will use in the future.”

By Walex at 2023-11-24 04:34:37:

BTW as to 6to4 the RFC 3056 and following ones keep repeating it is a "transitory" mechanism to be discarded as soon as possible once the full transition to IPv6 has happened.

Reading that always made be laugh because IPv4 is one of those things that perhaps will dwindle in usage but will widely used for a long time, certainly several more decades, and likely for some centuries.

Sumerian, one of the first written languages was used for 1,200 years as a means of communicating, including long after it ceased to be used as a live language, and the same for latin, and IPv4 has the same role.

Of all the "dual stack" compatibility modes 6to4 seems to be by far the best. Perhaps one day 4to6 will become as popular when most of the internet core will have become IPv6-only, but I would not expect that to happen soon :-).

Written on 16 November 2023.
« WireGuard and the question of link-local IPv6 addresses
My first Django database migration worked fine »

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

Last modified: Thu Nov 16 22:59:19 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.