I recently got IPv6 connectivity at my house, so naturally I wanted to add IPv6 support for my server. I ran into some difficulties that I didn’t find documented in a single place so here is the solution I came up with.

The problem

I quickly discovered that my ISP is not doing the IPv6 support "right", they are not giving me a /56 prefix with prefix delegation but instead a /64 prefix that cannot be further divided into subnets. This is true for all mobile operators in Finland and I cannot get anything else in my current address so this will have to do.

The lack of prefix delegation means that I have to set RA and NDP to relay mode in OpenWRT and I have no control over the IPv6 addresses that are assigned to my devices. That in turn means I cannot create static firewall rules based on those addresses because they can change any time.

For a few weeks I got by with manually changing the firewall rules every time the prefix changed but that was not sustainable because I have a lot of firewall rules.

Turning off IPv6 SLAAC Privacy Extensions

While I couldn’t have a predictable prefix, I can have a predicatble suffix by turning off the IPv6 SLAAC Privacy Extensions on my server. This way the suffix (the host part) is derived from the MAC address of the device and it will always stay the same.

Privacy Extensions exist for a reason. It increases privacy by generating the host part of the IP randomly and changing the address from time to time. I don’t think that is a problem for my server because it is open to the public anyway. The main reason for Privacy Extensions is so that mobile devices can’t be tracked across networks and my server obviously stays in the same network all the time. It’s good to acknowledge that this effectively makes your MAC address public, but I don’t personally see an obvious risk in that.

I’m using NetworkManager on my server. You can turn off Privacy Extensions by locating your interface configuration under /etc/NetworkManager/system-connections/. On my server it was in the file Wired connection 1.nmconnection. Add/change the following lines in the [ipv6] section:

[ipv6]
addr-gen-mode=eui64
method=auto
ip6-privacy=0

After this, you can either restart NetworkManager or reboot the whole computer. Then your computer should have a new IPv6 address.

The logic by which the IPv6 address is calculated now is called EUI-64. I found a great tool to test and better understand it: the EUI-64 Calculator.

Dynamic prefix forwarding

I discovered that in OpenWRT firewall rules, part of the target address can be dynamic. This technique is called dynamic prefix forwarding. As I understand it, it is specific to OpenWRT, so this syntax doesn’t probably work in other firewalls. With this technique we can use the static host part we set for the server in the previous part as the firewall rule’s target IP address.

Server IPv6 address2001:14bb:8ad:6b:f279:59ff:fe65:f9e4
Firewall rule target address::f279:59ff:fe65:f9e4/-64

Here you can see the current IPv6 address of my server and the resulting firewall rule target address. The /-64 tells the firewall to ignore the first 64 bits of the address and only look at the 64 bits at the end, which is the host part.

For more information about the firewall configuration, you can refer to the OpenWRT wiki