Hosting a website at home behind a Fritzbox with IPv6 enabled
Hosting a website at home behind a Fritzbox with IPv6 enabled
Originally published on Medium, May 11, 2021
My "web-server infrastructure" at home is composed of:
- a Fritzbox acting as a DSL modem and a network Router
- a Raspberry Pi as my web-server with Ubuntu 20.04
On this Raspberry Pi I host a few web applications including my homepage. As my home IP changes every night, I use a dynamic DNS service (ydns.eu) as the target for a CNAME on www.oglimmer.de.
As we know hosting a website at home, on a Raspberry Pi for example, is very simple and making it available on the Internet via IPv4 is super straight forward.
Let us recap the situation for IPv4
- The browser resolves www.oglimmer.de and finds a CNAME for oglimmer.ydns.eu, which returns an A entry pointing on my Fritzbox's public and dynamic IPv4
- The Fritzbox forwards a request on port 443 to the Raspberry Pi's web-server, because a port forwarding for 443 to the private and fixed IPv4 of my Raspberry Pi is configured
Things are more complicated with IPv6
As there is no NAT for IPv6, the Fritzbox does not have a port forwarding, instead it has port permissions on routing configurations. So for my scenario the web-server's IPv6 is given permission to be routed on port 80/443 on incoming requests.
Here is the problem
My Ubuntu 20.04 assigns two global unicast IPv6 addresses and both of those IPs have randomly generated interface ids.
While this is very good for privacy reasons, this is a problem for my setup, as the Fritzbox needs a static interface id for its routing permission.
The solution
Enable EUI-64 on the standard address to avoid a randomly generated interface id, that means Ubuntu will use "a MAC address derived" interface id instead.
Where this configuration needs to be applied depends on which component is responsible for SLAAC.
If SLAAC done by the Kernel
You need to use sysctl to enable EUI-64 via:
net.ipv6.conf.default.addr_gen_mode = 0
net.ipv6.conf.eth0.addr_gen_mode = 0
If SLAAC is done by dhcpcd
You need to change dhcpcd.conf like this:
slaac hwaddr
If SLAAC is done by NetworkManager
You need to change the configuration via:
nmcli con modify "Connection name" ipv6.addr-gen-mode eui64
This is my IP setup after applying EUI64. As you can see the MAC address is reflected in the interface id of the second global unicast IPv6 address.
A shout-out needs to go to the user Grawity on qastack.co who pointed us to the right solution. See this post.
Configuration on the Fritzbox
The Fritzbox has under "Internet" → "Permit access" → "Port sharing" a configuration dialog where you can set sharing options.
Most notably is the setting for "IPv6 Interface ID" which must reflect the MAC address.
Updating ydns.eu
To complete the process we need a script on the web-server to update the dynamic DNS service with both IPs when my ISP updates my public IP.
A simple cgi-bin is called from the Fritzbox (as a custom dynamic DNS provider):
#!/bin/bash
set -f
echo "Content-type: text/plain; charset=iso-8859-1"
echo
IPV4=$(curl -s ifconfig.me)
curl -u 'user:password' "https://ydns.io/api/v1/update/?host=oglimmer.ydns.eu&record_id=164921&ip=$IPV4"
IPV6=$(ip -6 address show dev enp2s0f0 | grep -v " 0sec" | grep "sec" -B 1 | grep inet | grep -v 'temporary' | grep -v 'inet6 fd' |cut -d ' ' -f6|cut -d '/' -f1)
curl -u 'user:password' "https://ydns.io/api/v1/update/?host=oglimmer.ydns.eu&record_id=173613&ip=$IPV6"
Conclusion
Running an IPv6 enabled web-server at home is a bit more complicated than thought, but still pretty doable.
The main problem comes from the fact that enabling EUI-64 on Ubuntu depends on your configuration, but once you understood how it works it's quite straight forward again.