Why?
To preserve DNS privacy, and prevent sniffing/spoofing, which is a common technique used by ISPs to restrict internet access in countries like mine, we can tunnel DNS traffic through WireGuard and use a remote, private, and trusted DNS server. Keep in my that this will only tunnel DNS traffic.
Setup
In this guide, I'll use Adguard dnsproxy as the DNS resolver, which is easy to setup and get it to work. Of course you can use any DNS server of your choice. Some alternatives that I can remember are (in no specific order):
WireGuard Server Config
# wgdns.conf
[Interface]
PrivateKey = server_prv
Address = 10.3.3.1/24
Address = 10.0.0.1/32
ListenPort = 64539
MTU = 1280
[Peer]
PublicKey = client_pub
PresharedKey = psk
AllowedIPs = 10.3.3.2/32
Subnet 10.3.3.0/24
is used for WireGuard peers, and 10.0.0.1/32
will be assigned to the DNS server.
WireGuard Client Config
[Interface]
PrivateKey = client_prv
Address = 10.3.3.2/32
MTU = 1280
DNS = 10.0.0.1
[Peer]
PublicKey = server_pub
PresharedKey = psk
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 15
Endpoint = server_ip:64539
dnsproxy
Download and extract the latest release of dnsproxy
, and spin it up:
./dnsproxy \
--cache \
--ipv6-disabled \
--pending-requests-enabled \
--refuse-any \
--udp-buf-size=4096 \
-l 10.0.0.1 \
-p 53 \
-u udp://1.1.1.1:53 \
-u udp://1.0.0.1:53
Firewall Rules
-
Allow WireGuard inbound connections:
ufw rule allow in on eth0 proto udp to SERVER_PUBLIC_IP/32 port 64539 comment 'WireGuard Inbound'
Where
eth0
is the public-facing network interface of the server. -
Allow WireGuard peers to query DNS server:
ufw rule allow in on wgdns proto udp from 10.3.3.1/24 to 10.0.0.1/32 port 53 comment 'WireGuard DNS'
Where
wgdns
is the name of WireGuard interface.
Limitations
Spinning up the dnsproxy
server(s) should happen after WireGuard interface is up as IP(s) are not available otherwise. One solution for having a separate DNS interface is to use the dummy
network kernel module like the following:
ip link add dummy0 type dummy
ip addr add 10.0.0.1/32 dev dummy0
ip link set dummy0 mtu 1280 up
If dummy
module isn't already enabled:
modprobe dummy
Note: This is not persistent against reboots. Ask ChatGPT for ways to make it so.
Moving Forward
-
You can spin up multiple
dnsproxy
servers on different IPs. In order for peers to access it, you'll need to:- Assign a new IP to the DNS interface (
wgdns
ordummy0
) - Apply the respective firewall rule
- Update both
DNS
, andAllowedIPs
of peers to match the new DNS server IP
- Assign a new IP to the DNS interface (
You can use port-forwarded UDP, or TCP (DoH, or DoT for example) ports instead of local process to escape network restrictions (e.g., by using tools like rathole)
Top comments (1)
Very insightful👏🔥✨