WireGuard DNS Not Working: Fix Device Resolution Across Your VPN Subnets
Why WireGuard Won’t Resolve Your Internal Hostnames
WireGuard is a lean protocol — it handles encrypted tunneling and nothing else. DNS is entirely your problem. Out of the box, a WireGuard client has no idea which DNS server to use for your internal network, and your DNS server probably has no idea it should be answering queries coming in over the tunnel. Both ends need fixing.
The setup described — WireGuard on 192.168.103.0/24, LAN subnets on 192.168.100–102.0/24 — is a common road-warrior or home-lab configuration. Getting name resolution working across all of them is a five-step job.
Step 1: Add DNS= to Your Client Config
Every WireGuard client config has an [Interface] section. Add a DNS = line pointing at your internal DNS server — usually the IP of your router or whatever is running dnsmasq, Pi-hole, or Unbound on the LAN:
[Interface]
PrivateKey = <client-private-key>
Address = 192.168.103.2/32
DNS = 192.168.100.1
Without this line the client falls back to whatever resolver it had before the tunnel came up — public DNS that knows nothing about your private hostnames. This is the single most common reason WireGuard clients can reach IP addresses but not names.
Step 2: Make Your DNS Server Listen on the WireGuard Interface
This is the step that catches most people. Your DNS server is almost certainly bound only to LAN interfaces. Queries arriving on wg0 get silently dropped before they’re processed.
If you’re running dnsmasq, add the WireGuard interface to the listen list. In /etc/dnsmasq.conf or a drop-in file under /etc/dnsmasq.d/:
interface=wg0
interface=eth0 # keep your existing LAN interface too
Restart dnsmasq after saving. Pi-hole users: go to Settings → DNS → Interface Listening Behavior. Set it to listen on all interfaces, or drop a custom config file in /etc/dnsmasq.d/ containing that interface=wg0 line.
For Unbound, add interface: and access-control: entries in unbound.conf:
server:
interface: 192.168.100.1
interface: 192.168.103.1
access-control: 192.168.103.0/24 allow
Without the access-control line, Unbound will refuse queries from the WireGuard subnet even if it’s listening on the right interface.
Step 3: Open Port 53 in Your Firewall
Even after the DNS server is listening on wg0, a host-based firewall can still block the traffic. Allow UDP and TCP port 53 from the WireGuard subnet:
iptables -A INPUT -i wg0 -p udp --dport 53 -j ACCEPT
iptables -A INPUT -i wg0 -p tcp --dport 53 -j ACCEPT
On routers running nftables, OpenWrt, pfSense, or OPNsense, add an equivalent rule permitting DNS from 192.168.103.0/24 to the gateway. The exact location varies by firmware, but the rule is the same concept everywhere. Both UDP and TCP matter — TCP is used for larger responses and zone transfers.
Step 4: Check That AllowedIPs Covers the DNS Server
WireGuard only routes traffic through the tunnel if the destination matches the peer’s AllowedIPs. If your DNS server is at 192.168.100.1 and that subnet isn’t listed, DNS queries go out the regular interface and bypass the VPN entirely. The tunnel can appear fully up while name resolution silently fails.
[Peer]
PublicKey = <server-public-key>
Endpoint = your-server.example.com:51820
AllowedIPs = 192.168.100.0/24, 192.168.101.0/24, 192.168.102.0/24, 192.168.103.0/24
All four subnets need to be present. A missing entry means traffic destined for that range never enters the tunnel, and no amount of DNS server configuration on the server side will compensate.
Step 5: Enable IP Forwarding on the Server
If WireGuard clients need to reach LAN hosts (not just the WireGuard server itself), the server must forward packets between interfaces. Check the current value first:
sysctl net.ipv4.ip_forward
If the output is 0, enable it. Create or edit /etc/sysctl.d/99-wireguard.conf:
# /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1
Apply it immediately with sysctl --system. Then add a masquerade rule so return traffic from LAN hosts finds its way back through the tunnel:
iptables -t nat -A POSTROUTING -s 192.168.103.0/24 -o eth0 -j MASQUERADE
Replace eth0 with your actual LAN-facing interface name. Running ip link will list all interfaces if you’re unsure.
Testing the Fix
From a connected WireGuard client, query your internal DNS server directly:
dig @192.168.100.1 some-local-hostname.lan
If that resolves, DNS is reaching the server. If it times out, revisit steps 2 and 3. If it resolves but plain nslookup some-local-hostname.lan still fails, the client isn’t using the right resolver — recheck the DNS = line and make sure the tunnel was restarted after the config change. WireGuard doesn’t hot-reload.
Getting a ping response by hostname through the tunnel is the final confirmation that all five pieces are in place.
Sources
- procustodibus.com
- amini.eu
- nickb.dev
- wiki.nixos.org
- stackharbor.com
- hacktobeer.eu
- dev.to
- linkconfig.com
