Mountain%20Landscape_edited_edited.jpg
  • Hannah Lee

DNSCrypt-Proxy2 Setup Tutorial to Secure the Last Mile of Your VPN Server (OpenVPN and WireGuard)

This tutorial will walk you through the setup of DNSCrypt-Proxy2 on your VPN server to bring your VPN security up-to-par with major VPN services. This tutorial is based on Centos 7 and OpenVPN 2.5.2/WireGuard, but the instructions are simple and you can easily translate these steps into other distributions of Linux.

If you were security-minded during your VPN installation, you might have changed the default OpenDNS servers. However, changing the DNS server alone does not secure your DNS traffic. The DNS protocol is plain-text, unsecure, and out dated. DNS attacks have been around for decades, and, fortunately, there are many efforts out there to secure DNS. One of them is DNSCrypt. DNSCrypt encrypts the traffic between your client (in this case, your VPN server) and the DNS server.


(Black Arrows = Encrypted Traffic; Blue Arrows = Unencrypted Traffic)

You see the difference? Your VPN server only encrypts traffic between the client and the server; once it receives the traffic, it decrypts and sends it off to its destination. This includes the client's DNS requests. If you want a summary on the different aspects of DNS security, check out my article here.

This tutorial is based on the DNSCrypt-Proxy documentation on GitHub for Linux. You can find the instructions for other OS's here.


STARTING CONFIGURATION

This tutorial is an extension of my VPN setup tutorials (OpenVPN and WireGuard). Here are the specifics of the configuration:



Step 1: Check for Running Services on Port 53

DNSCrypt-Proxy2 runs on port 53, the standard DNS port. First, let's see what you've already got going on.


a. Login as root.


b. Check port 53.

ss -lp 'sport = :domain'

If nothing is running, you'll just see the headers:

Netid  State     Recv-Q Send-Q Local Address:Port        Peer Address: 

c. Stop any running services on port 53.

If there is something running, stop and disable:

systemctl stop systemd-resolved
systemctl disable systemd-resolved

(repeat for each service running on port 53)



Step 2: Download DNSCrypt-Proxy2


a. Download the package from GitHub:

wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.0.45/dnscrypt-proxy-linux_x86_64-2.0.45.tar.gz

This is the latest release as of writing this. Check for the latest release here.


b. Extract the files:

tar -xf dnscrypt-proxy-linux_x86_64-2.0.45.tar.gz

c. Move the files:

mv linux-x86_64 /etc/dnscrypt-proxy

The tar file was named "linux-x86_64" once extracted, but update this filename if it is

not the same for you.



Step 3: Install and Test DNSCrypt


a. Edit resolv.conf:

nano /etc/resolv.conf

Delete the contents of this file and replace with this:

nameserver 127.0.0.1
options edns0

resolv.conf is often updated by other services. Run this to lock the file:

chattr +i /etc/resolv.conf

b. Change directory into dnscrypt-proxy:

cd /etc/dnscrypt-proxy

c. Copy the example configuration file:

cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml

This is the main configuration file for DNSCrypt-Proxy2.


d. Enable executable permissions for dnscrypt-proxy:

chmod 755 dnscrypt-proxy

e. Install the service:

./dnscrypt-proxy -service install

f. Start the service:

./dnscrypt-proxy -service start

g. Test the service:

./dnscrypt-proxy -resolve hannahtech.co

Once you get everything up and running, you have successfully set up DNSCrypt-Proxy2 for your VPN server (and your server only). Now let's update some configurations and give your VPN clients access to your encrypted DNS.



Step 4: Configure DNSCrypt


a.

1. (For OpenVPN) Find your VPN server's tun0 address:

ip a | grep tun0 | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"

If you didn't change your subnet in server.conf, it will probably be 10.8.0.1. I will now refer to this address as "LOCAL_VPN_IP".


2. (For WireGuard) Find your VPN server's wg0 address:

ip a | grep wg0 | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b"

If you didn't change your subnet's defualt, it will probably be 10.10.10.1. I will now refer to this address as "LOCAL_VPN_IP".


b. Edit the configuration file:

nano dnscrypt-proxy.toml

c. Set DNSCrypt to listen on your LOCAL_VPN_IP:

Find this line:

listen_addresses = ['127.0.0.1:53']

Change to:

listen_addresses = ['127.0.0.1:53', 'LOCAL_VPN_IP:53']

NOTE: If you are running both OpenVPN and WireGuard on the same server, you will need to add the local VPN IP's for both. Here's an example:

listen_addresses = ['127.0.0.1:53', '10.8.0.1:53', 10.10.10.1:53']

d. Require your DNS Servers to implement DNSSEC:

Find this line:

require_dnssec = false

Change to:

require_dnssec = true

e. Save and exit dnscrypt-proxy.toml.



Step 5a: Configure server.conf (OpenVPN Only)


a. Edit server.conf:

nano /etc/openvpn/server/server.conf

b. Set your DNSCrypt server (which is your VPN server) as the DNS server:

Find this line:

push "dhcp-option DNS 208.67.222.222"

Change to:

push "dhcp-option DNS LOCAL_VPN_IP"

YOU SHOULD NOT PUSH A SECONDARY DNS SERVER TO YOUR CLIENTS.


c. Block outside DNS servers:

Add this line:

push "block-outside-dns"

d. Set your clients' default gateway to the VPN (pushing all internet traffic through the VPN by default).

Ensure this is included:

push "redirect-gateway def1 bypass-dhcp"

e. Save and exit server.conf.



Step 5b: Configure Client Configurations (WireGuard Only)


Unfortunately, WireGuard servers cannot (currently) push DNS configurations to clients as easily as OpenVPN servers can. You will need to set your LOCAL_VPN_IP as your DNS server in your client configuration files. Here's an example of a client configuration file:

[Interface]
Address = 10.10.10.9/24
DNS = LOCAL_VPN_IP
PrivateKey = ksdfjhas8fuaworjnwrnfkfjas98fuaosfhasdfjsdfasdfaas=

[Peer]
PublicKey = alsdjfa8fsjfoasfjasdkfjosifjaosfhaksjfhlasjfsdfsdfas=
AllowedIPs = 0.0.0.0/0
Endpoint = 123.123.12.23:51820
PersistentKeepalive = 25

NOTE: "AllowedIPs = 0.0.0.0/0" pushes all of your internet traffic through this tunnel.


If you followed my WireGuard tutorial, you will have a script that generates client configuration files with preset variables. In this script, you simply have to update your DNS variable to your LOCAL_VPN_IP. If you have this script, find this section and update:

#Optional; this is your VPN DNS server. Set to your server's VPN IP (e.g.
#10.10.10.1) if you are running DNSCrypt-Proxy (or another resolver) on
#this server.
DNS="LOCAL_VPN_IP"

If you want this script, head over to my WireGuard tutorial and skip to Step 3. However, ensure:

1. You create the /etc/wireguard/client/conf and /etc/wireguard/client/keys directories.

2. Your server files (public key, private key, wg0.conf) are located in /etc/wireguard/.



Step 6: Update Firewall and Restart


a. Open UDP port 53 on your firewall:

firewall-cmd --add-port=53/udp --zone=public --permanent
firewall-cmd --reload

If you're having issues, also open UDP port 53 on your external firewalls, such as your cloud security firewall if you are running this on a VPS, or your router firewall if you a running this on a machine at home.


b. Restart the services:

./dnscrypt-proxy -service restart
systemctl restart openvpn-server@server


Step 7: Check Enforcement


a. Connect to the VPN with a client.


b. Run a DNS leak test.

If you left the other configurations in dnscrypt-proxy.toml to the defaults, you'll probably have a bunch of different servers listed. Check the this list with the /etc/dnscrypt-proxy/public-resolvers.md to ensure these servers are listed and that they meet the requirements you set in dnscrypt-proxy.toml (such as DNSSEC, unfiltered, non-logged).If you don't like having this many servers see your traffic, you can specify which servers you like in dnscrypt-proxy.toml.


c. Run a DNSSEC test.



Step 8: DONE!


There are plenty of settings you can mess around with in dnscrypt-proxy.toml to meet your security needs. You can also check out Anonymized DNS to anonymize your traffic to the DNS servers. It's a pretty light-weight attachment to DNSCrypt.

If you want to be extra secure, you can keep it all in-house and setup your own authoritative DNS server. I don't recommend this for personal VPN's, since this is a lot of extra overhead and there are easier solutions (like DNSCrypt!), but it's definitely an option. If you have other home networking projects, a DNS server might be a natural addition.

Most of the big VPN services host their own local DNS servers, so they don't have to worry about the DNS requests in transit and therefore do not need to provide encryption specific to DNS.



Troubleshooting


Here are some troubleshooting tips to help you along:


1. Problem: Clients can't resolve DNS when connected to the VPN.

Run tcpdump on tun0 port 53:

tcpdump -i tun0 port 53

Then, from your client, try to browse different webpages. If you are seeing your client's traffic on tcpdump, that means you are properly configured and connected. If this is the case, ensure you are not sharing an OpenVPN client profile with another device; if profiles are shared, they may be assigned the same IP, and the DNS traffic does not know who to return to.


2. Problem: dnscrypt-proxy service wont start.

You probably have a misconfiguration in dnscrypt-proxy.toml. Check:

systemctl status dnscrypt-proxy -l

3. Problem: "./dnscrypt-proxy -resolve hannahtech.co" won't resolve.

If "systemctl status dnscrypt-proxy -l" doesn't help, try the syslog:

cat /var/log/messages

Also, ensure your resolv.conf file hasn't reverted back.


4. More troubleshooting tips can be found in the documentation.