DEV Community

Cover image for WireGuard DoV (DNS-over-VPN)
xeptore
xeptore

Posted on

WireGuard DoV (DNS-over-VPN)

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

If dummy module isn't already enabled:

modprobe dummy
Enter fullscreen mode Exit fullscreen mode

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 or dummy0)
    • Apply the respective firewall rule
    • Update both DNS, and AllowedIPs of peers to match the new DNS server IP
  • 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)

Collapse
 
zahra_mirkazemi profile image
Zahra Mirkazemi

Very insightful👏🔥✨