IPv6 adventures 3: IPv6 only hosts
Go watch these videos for more in depth information about IPv6-only troubles and transition techniques. For me the problem is twofold:
- Some services are IPv4 only, but use proper DNS / hostnaming. This can be solved with NAT64 and DNS64. These will translate an IPv4 address to IPv6 so the IPv6 only host can still connect.
- Other services use IPv4 literals, hard-coded ip adresses, which cannot be "intercepted" by DNS and thus not translated to IPv6. This can be solved with CLAT.
References:
- https://en.wikipedia.org/wiki/IPv6_transition_mechanism
- https://nicmx.github.io/Jool/en/index.html
- https://github.com/NICMx/Jool
- https://forum.netgate.com/topic/158084/how-to-setup-nat64-using-pfsense-with-jool
- https://cooperlees.com/2020/12/nat64-using-jool-on-ubuntu-20-04/
1a. NAT64 with Jool
I'm using pfSense as my router/internet gateway, so the second video above was not for me. However, the first NAT64 he mentions is Jool, which he will not be using as it is for Linux, not FreeBSD. So that's the one I configured and am using now. This is how.
Virtual machine
Start by creating a Debian or Ubuntu VM. Don't use LXC as Jool attaches to the kernel and gets confused when the LXC kernel version differs from the host version. I made my life easier by just installing Jool in a VM. I initially gave the VM 2 GB of memory for installation, but afterwards dialed that back to 1024MB, which should be more than plenty.
joep@jpl-nat64:~$ free -h
total used free shared buff/cache available
Mem: 960Mi 224Mi 728Mi 492Ki 140Mi 735Mi
Swap: 974Mi 0B 974Mi
Jool install
- Install kernel headers
sudo apt install linux-headers-$(uname -r)
- Install Jool
sudo apt install jool-dkms jool-tools
sudo modprobe jool
Jool config
- Enable network forwarding:
- Create file
/etc/sysctl.d/90-forwarding.conf
:
- Create file
sudo nano /etc/sysctl.d/90-forwarding.conf
- Add lines:
net.ipv4.conf.all.forwarding=1
net.ipv6.conf.all.forwarding=1
- Apply:
sudo sysctl -p /etc/sysctl.d/90-forwarding.conf
- Add Jool config (https://nicmx.github.io/Jool/en/config-atomic.html)
- Create Jool config file:
sudo mkdir /etc/jool
sudo nano /etc/jool/jool.conf
- Add minimal config:
{
"instance": "nat64-minimal",
"framework": "netfilter",
"global": {
"pool6": "64:ff9b::/96"
}
}
- Enable and start Jool
sudo systemctl enable jool --now
pfSense config
Now we need to route all traffic to 64:ff9b::/96
to the NAT64 VM. The VM lives on VLAN 30
and has ULA: fdc3:xxxx:xxxx:30:xxxx:xxxx:xxxx:xxxx
.
In pfSense:
- Go to System ā Routing ā Gateways
- Copy the Gateway address of the IPv4 WAN gateway:
xxx.xxx.xxx.xxx
- Click the add button and enter:
Address Family:
IPv6
Name:
NAT64_GW
Gateway:
fdc3:xxxx:xxxx:30:xxxx:xxxx:xxxx:xxxx
Monitor IP:
64:ff9b::xxx.xxx.xxx.xxx
Description:
NAT 64 Gateway
- Save
- Go to System ā Routing ā Static Routes
- Click the add button and enter:
64:ff9b::
/ 96
Gateway:
NAT64_GW - fdc3:xxxx:xxxx:30:xxxx:xxxx:xxxx:xxxx
Description:
NAT 64 Gateway
- Save
1b. DNS64
If you use the DNS resolver in pfSense, go to Services ā DNS Resolver ā Advanced Settings. Then scroll all the way down and enable DNS64 Support by checking the box Enable DNS64 (RFC 6147).
I use Technitium which uses a DNS64 "App".
- Go to Apps ā App store
- Look for "DNS64" and press Install
1c. Results
If I now ping a site that is IPv4-only on a IPv6-only machine I get a proper response:
joeplaa@jpl-grafana:~$ ping -c 1 github.com
PING github.com (64:ff9b::8c52:7904) 56 data bytes
64 bytes from lb-140-82-121-4-fra.github.com (64:ff9b::8c52:7904): icmp_seq=1 ttl=52 time=11.7 ms
--- github.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 11.669/11.669/11.669/0.000 ms
On a dual-stack machine it still pings the IPv4 address directly:
joep@PCJOEP:~$ ping -c 1 github.com
PING github.com (140.82.121.4) 56(84) bytes of data.
64 bytes from lb-140-82-121-4-fra.github.com (140.82.121.4): icmp_seq=1 ttl=53 time=10.1 ms
--- github.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.091/10.091/10.091/0.000 ms
2a. CLAT / 464XLAT
Some applications have hardcoded IP addresses in their code. On mobile phones this is solved by using CLAT/464XLAT see the Wikipedia article about transistioning mechanisms. On PC's/servers, this is not (yet) implemented. For Linux you can install CLAT's (see Apalrd videos), on Windows you're screwed. Windows 10 only supports this for mobile devices (WWAN), Windows 11 support has been promised, but isn't there yet. So the only option so far is to keep your desktops dual-stack. Which is fine for me at home.
Spotify
I noticed that when I disabled IPv4 on my Window 10 machine in the living room, Spotify refused to connect. I tried to reproduce this scenario on my Ubuntu Desktop to try CLAT, but there Spotify works fine on IPv6. This seems to be an "old" issue, Spotify engineers already wrote about this in 2015:

There are also multiple requests which have been passed to the "internal teams" in 2021.
However, it seems this still isn't fixed.
- 2024: "Content not available" on IPv6
- 2024: Spotify App can play 0.5% songs on IPv6. It seems to be App UI bug.
This Reddit thread discusses some issues back in 2019-2020. I tried to ping
and nslookup
the mentioned addresses and they all return IPv6 addresses. So I'm a bit confused why Spotify seems to work fine on Ubuntu, but not on Windows 10.
Other
When disabling IPv4 on my Ubuntu desktop, I noticed my Windows VM didn't start. The Virtual Machine Manager gives an error that it cannot to the spice address. It happens that Spice only listens on IPv4 localhost by default. This can be changed quite easily.
- Open
/etc/libvirt/qemu.conf
- Find the line
spice_listen = "0.0.0.0"
. This line should be commented out, if not, do so - Add line
spice_listen = "::1"
# SPICE is configured to listen on 127.0.0.1 by default.
# To make it listen on all public interfaces, uncomment
# this next option.
#
# NB, strong recommendation to enable TLS + x509 certificate
# verification when allowing public access
#
#spice_listen = "0.0.0.0"
spice_listen = "::1"