Set up Cloudflare DNS over HTTPS on your Wireguard VPN server


Once you’ve set up a Wireguard VPN server, you’ll also want to protect your DNS requests. One method of achieving this is to set up a DNS over HTTPS resolver on your VPN server and route your DNS traffic over the VPN tunnel.

This follows on from the last post Set up a Wireguard VPN on Ubuntu and connect from Mac and Android so check that out first if you don’t already have a Wireguard VPN server set up.

Cloudflare provide a DNS over HTTPS (DoH) resolver to use with their 1.1.1.1 public DNS service. We’ll install this on our Wireguard server and then configure each client use it.

Install the Cloudflared DoH Server

  1. Download the Cloudflared service for your Linux platform. For Ubuntu/Debian download the .deb package:

    1
    
    wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-amd64.deb
    
  2. Install the package:

    1
    
    dpkg -i cloudflared-stable-linux-amd64.deb 
    
  3. Confirm that it installed correctly:

    1
    2
    
    cloudflared --version
    cloudflared version 2019.2.1 (built 2019-02-28-0010 UTC)
    
  4. Configure the service to use Cloudflare’s 1.1.1.1 and 1.0.0.1 resolvers:

    1
    2
    3
    4
    5
    6
    7
    
    mkdir -p /usr/local/etc/cloudflared
    cat << EOF > /usr/local/etc/cloudflared/config.yml
    proxy-dns: true
    proxy-dns-upstream:
        - https://1.1.1.1/dns-query
        - https://1.0.0.1/dns-query
    EOF
  5. Install the service:

    1
    
    sudo cloudflared service install
    
  6. The service should now be running on localhost. Test it by querying for a DNS record:

    1
    2
    3
    
    dig +short @127.0.0.1 tau.gr AAAA
    2606:4700:30::681b:9ecf
    2606:4700:30::681b:9fcf
    

Configure Wireguard Server

In order to correctly route DNS requests across the VPN we need to amend some of the firewall rules created in the PostUp phase.

Edit your Wireguard config /etc/wireguard/wg0.conf and append the following to the PostUp and PostDown commands:

1
2
PostUp = <other PostUp commands>; iptables -A PREROUTING -t nat -i %i -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:53; sysctl -w net.ipv4.conf.%i.route_localnet=1
PostDown = <other PostDown commands>; iptables -D PREROUTING -t nat -i %i -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:53

The first command in PostUp adds a NAT rule to redirect DNS (i.e. traffic destined to port 53) to the Cloudflared server running on 127.0.0.1. The second command enables the route_localnet setting on the Wireguard server’s network interface. We need to enable this because by default the Linux kernel will drop packets destined to localhost, as it deems them to be ‘martian packets’.

The PostDown command simply deletes the NAT firewall rule that was created in PostUp. We don’t need to clear the route_localnet setting because it was only configured on the Wireguard interface, which gets destroyed when you shut down Wireguard.

Save the config file and restart Wireguard for the new changes to take effect:

1
2
wg-quick down wg0
wg-quick up wg0

Configure Wireguard Clients

On each client edit the Wireguard config and change the DNS address to be the Wireguard internal IP address of the server. If you used the settings in the Set up a Wireguard VPN on Ubuntu and connect from Mac and Android guide then this is 10.0.0.1:

1
DNS = 10.0.0.1

Save the config and restart your VPN connection. To verify everything’s working, use Cloudflare’s Browsing experience check.

References