Connecting a Fritzbox with a Unifi Cloud Gateway Ultra via WireGuard
Hey everyone! Today, I want to share a bit of a networking puzzle I recently tackled: setting up a WireGuard VPN between a Fritzbox that was stuck behind Carrier-Grade NAT (CGNAT) and a Unifi Cloud Gateway Ultra (UCG-Ultra) on a normal broadband line. The idea was to ensure remote access and maintain a secure connection between networks. As with many networking adventures, it didn’t come together without a few surprises.
The Setup
The initial plan was straightforward enough:
- The Fritzbox, located at a remote site, was connected to an ISP that only provides a CGNAT IPv4 address. Outbound connections are generally fine under CGNAT, but inbound direct connections usually aren’t possible.
- The UCG-Ultra at the other site had a standard, publicly reachable IPv4 address.
Since the UCG-Ultra currently doesn’t support WireGuard over IPv6, I first tried an IPv6-based setup, but it simply wouldn’t work. This is a known limitation right now, as discussed in the Ubiquiti community forums:
- UnifiOS-3-0-20-Wireguard-in-IPv6
- WireGuard-server-connection-through-ipv6-help-needed
- Feature Request: IPv6 support for Wireguard VPN
Because of these constraints, I settled on a pure IPv4 solution. There’s also a great guide discussing the Fritzbox quirks as a WireGuard client here:
Ubiquiti Networks Forum: Fritzbox as WireGuard Client
The Early Attempts and Hurdles
I set up the WireGuard server on the UCG-Ultra and configured the Fritzbox according to official AVM instructions (as much as possible). On the UCG side, a firewall rule allowed WireGuard UDP traffic on the chosen port. The Fritzbox configuration looked fine—at least in theory.
But in practice, the connection wouldn’t establish. The Fritzbox would attempt to connect, try a few handshakes, and then give up. On the UCG-Ultra side, I could see inbound and outbound packets via sudo tcpdump -i any udp port 51820
, which meant the server responded. So why no completed handshake on the Fritzbox?
Debugging the Issue
I started digging deeper. After verifying public keys, AllowedIPs, and making sure the WireGuard subnets were consistent, I tried something different. I replaced the domain name in the Fritzbox WireGuard config with the server’s raw IPv4 address. Suddenly, the connection worked flawlessly. It was night and day.
This was strange. The domain (example.com
) resolved properly on other machines behind the Fritzbox. No IPv6 trickery, no DNSSEC complexity. And yet, when the Fritzbox tried using that bare domain name as an endpoint, no packets were sent. It just wouldn’t even start the handshake.
The Subdomain Trick
A clue emerged from various community discussions: the Fritzbox can be quirky when it comes to certain domain names in WireGuard configurations. Using a “naked” domain (like example.com
) sometimes fails silently. But using a subdomain—such as vpn.example.com
—resolves the issue.
I adjusted my DNS:
- Created a new A record
vpn.example.com
pointing to the UCG’s public IP. - Updated the Fritzbox WireGuard config to use
vpn.example.com:51820
.
Sure enough, the handshake initiated, and the tunnel came right up. The Fritzbox was finally happy, and so was I.
Original vs Modified Configuration
Original UCG Configuration:
[Interface]
PrivateKey = *******
Address = 192.168.4.2/32
DNS = 192.168.4.1
[Peer]
PublicKey = 52c31hTFMLDcGrJ/dL7t0urMPs/JHdE6SDXTOyWMQnQ=
AllowedIPs = 192.168.4.1/32,192.168.4.2/32,0.0.0.0/0
Endpoint = example.com:51820
Modified UCG Configuration for FritzBox:
[Interface]
PrivateKey = *******
Address = 192.168.30.1/24
[Peer]
PublicKey = 52c31hTFMLDcGrJ/dL7t0urMPs/JHdE6SDXTOyWMQnQ=
AllowedIPs = 192.168.4.0/24,192.168.20.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25
Network Overview:
- The Fritzbox uses
192.168.30.1/24
as its WireGuard interface IP (this is the Fritzbox’s local WireGuard network). - The transfer network between the Fritzbox and the UCG is
192.168.4.0/24
. - The target network behind the UCG, which the Fritzbox should access via WireGuard, is
192.168.20.0/24
.
Key changes:
- Remove the
DNS
entry under[Interface]
. The Fritzbox implementation of WireGuard can be picky about DNS settings. - Adjust
AllowedIPs
to match the desired subnets. For example,192.168.4.0/24
for the transfer network, and192.168.200.0/24
for the network the Fritzbox should access. - Add
PersistentKeepalive = 25
to ensure the Fritzbox sends periodic packets, maintaining the NAT binding.
Why Does This Happen?
Unfortunately, no official explanation from AVM exists. My best guess: certain DNS lookups or the Fritzbox’s internal logic treats domain types differently. Perhaps it expects a dedicated hostname identifying the VPN service or has a quirk in how it prioritizes DNS queries for WireGuard endpoints.
Conclusion
If you’re setting up a Fritzbox behind CGNAT to connect via WireGuard to a Unifi Cloud Gateway Ultra, the combination can work well with IPv4. Remember that IPv6 currently isn’t supported, so don’t waste time there. If you run into a mysterious issue where direct IP addresses work but hostnames fail, consider introducing a subdomain dedicated to your VPN endpoint.
This small tweak solved my configuration woes and allowed the secure, stable, and reliable VPN connection I was looking for. Sometimes the simplest changes—in this case, a subdomain and a few config adjustments—can overcome the most perplexing network challenges.
Happy tunneling!