WireGuard behind DS-Lite - wg-easy on TrueNAS, reachable over IPv6
Contents
Preface
The first part covered why only IPv6 gets into my home network from outside (DS-Lite), and the small script that keeps vpn.knng.de pointed at my NAS.
This part is about what sits behind that name: WireGuard.
The FRITZ!Box can do WireGuard itself, but its upload was too slow for me.
So WireGuard runs on the NAS instead, as the wg-easy app on TrueNAS.
The setup at a glance
| Setting | Value |
|---|---|
| Endpoint | vpn.knng.de, AAAA record only |
| Port | UDP 51820 |
| Tunnel | split tunnel, only 192.168.1.0/24 goes through it |
| DNS for clients | Pi-hole, 192.168.1.15 |
| MTU | 1280 |
| Persistent keepalive | 25 seconds |
Opening the FRITZ!Box
With IPv6 there’s no NAT, the NAS has its own public address.
The FRITZ!Box only has to let UDP 51820 through its firewall to that one device, which is a normal port sharing for the NAS:

That’s the only port that’s open from the outside.
wg-easy on TrueNAS
wg-easy comes straight from the TrueNAS app catalog.
Most of the interesting settings are in the web UI under Admin Panel -> Config:

- Host is
vpn.knng.de. That’s what ends up as the endpoint in every client config, so it has to resolve from anywhere, which is what the AAAA record from the first part is for. - Allowed IPs is only
192.168.1.0/24. Traffic to my home network goes through the tunnel, everything else on the phone or laptop goes out directly like it normally would. - DNS is Pi-hole on the NAS. That’s the nice part: the local DNS records from the first part work on the road too, so my internal
*.knng.denames resolve to the NAS, with a valid certificate.
The interface settings are under Admin Panel -> Interface:

Finding the right MTU
Instead of guessing the MTU, I measured it.
WireGuard over IPv6 adds 80 bytes to every packet (40 for the IPv6 header, 8 for UDP, 32 for WireGuard itself). The usual default of 1420 assumes a clean 1500 byte path, and mobile networks often don’t give you that.
So I tested it:
- Start an iperf3 server on the NAS
- Set an MTU in both places in wg-easy and restart the interface
- Connect the iPhone through the tunnel and run a test against the NAS with an iperf3 app from the App Store
- Watch for dropouts, then try the next value
1280 was the most consistent one.
It’s also the smallest MTU IPv6 allows, so even with the WireGuard overhead on top, the packets leave plenty of headroom for smaller paths along the way.
Persistent Keepalive is set to 25 seconds, the interval the WireGuard documentation uses as its example for peers behind NAT. It keeps the connection alive when nothing is being sent.
Why not MyFRITZ!?
My first attempt was the FRITZ!Box’s own MyFRITZ! address instead of my own domain.
The FRITZ!Box has one (<id>.myfritz.net), and devices can get their own name below it, like truenas.<id>.myfritz.net.
Except the device name didn’t resolve:
for h in truenas.<id>.myfritz.net <id>.myfritz.net; do echo "== $h"; host -t AAAA $h 2>&1 | head -3; done
echo '== NAS GUA'; ip -6 addr show scope global | grep 'inet6 2a00'
== truenas.<id>.myfritz.net
Host truenas.<id>.myfritz.net not found: 3(NXDOMAIN)
== <id>.myfritz.net
<id>.myfritz.net has IPv6 address 2a00:10:22bd:2300::1
== NAS GUA
inet6 2a00:10:22bd:2301:4a21:bff:fe62:1e72/64 scope global dynamic mngtmpaddr proto kernel_ra
The router’s name worked, but it points at the FRITZ!Box itself (...:2300::1), not at the NAS in ...:2301::/64. WireGuard would have been knocking on the wrong door.
It took me a while to figure out why the device name was missing:
the FRITZ!Box only creates truenas.<id>.myfritz.net while that device has an active MyFRITZ! sharing.
A normal port sharing, like the one for WireGuard, isn’t enough.
A MyFRITZ! sharing publishes a service on a device, with a scheme and a port.
To test it, I pointed one at the TrueNAS web UI:

With the sharing enabled, truenas.<id>.myfritz.net resolved to the NAS.
After disabling it, the name went back to NXDOMAIN.
So MyFRITZ! is a viable way too: create a MyFRITZ! sharing for the NAS under Internet -> Permit Access -> Port Sharing, and use <device>.<id>.myfritz.net as the host in wg-easy.
Just point that sharing at something you don’t mind being reachable from the internet, not at an admin panel like my test did…
I still went with my own domain:
- MyFRITZ! ties the endpoint to AVM. If I ever replace the router, every client config needs a new host, while
vpn.knng.destays the same. - The name depends on a sharing that has nothing to do with WireGuard itself.
- A small script and a domain I control is simply more homelab. :D
The catch: IPv6 only
The endpoint only has an IPv6 address, that’s the whole point of DS-Lite.
On a network without IPv6, like some hotel or guest WiFis, the tunnel simply can’t connect.
Cheers.