DNSCrypt is an open specification for a method of authenticating communications between a DNS client and a DNS resolver. It uses cryptographic signatures to verify that responses originate from the chosen DNS resolver and haven’t been tampered with while still sending the messages over UDP.
DNSCrypt provides increased privacy by encrypting the DNS message content and preventing DNS spoofing with authentication. While DNSCrypt has not yet been standardized, fortunately, multiple implementations and a set of DNSCrypt servers are available. For example, OpenDNS offers DNSCrypt.
In this guide, we show you how to install and configure the DNSCrypt server on your Cloud Server.
Deploying Cloud Server
To get started, you will first need to deploy a Cloud Server e.g. Ubuntu 20.04 or Debian 8. Log into your UpCloud Control Panel and click the Deploy server button.
If you are new to UpCloud, you can get started with the free trial by signing up.
The deployment page shows a number of options for customizing your new Cloud Server.
- Choose the server location from the available data centres
- Pick a configuration, the $5 per month plan is a good starting point
- Select your operating system, we are using Ubuntu 20.04
- Add any SSH keys you want to use
- Give your server a hostname and description
Deploy!
You can find more in-depth deployment instructions in a separate tutorial.
Installing DNSCrypt
Once your Cloud Server is up and running, connect to it over SSH to continue. Commonly, you should set up your own username and firewall rules but we’ll skip them in this tutorial for brevity.
Follow the steps below after initialising your UpCloud instance and securing it.
First, make a directory to store files associated with the DNSCrypt server.
sudo mkdir -p /opt/encrypted-dns
Go to the newly created directory and download the latest precompiled package.
cd /opt/encrypted-dns sudo wget https://github.com/jedisct1/encrypted-dns-server/releases/download/0.3.22/encrypted-dns_0.3.22_amd64.deb
Then install the downloaded package.
sudo dpkg -i encrypted-dns_0.3.22_amd64.deb
Configuring DNSCrypt
A sample configuration file is made available by the package. Copy it and make changes according to your needs.
sudo cp /usr/share/doc/encrypted-dns/example-encrypted-dns.toml /opt/encrypted-dns/encrypted-dns.toml
Then to configure your DNSCrypt server, make the following changes to the parameters in the encrypted-dns.toml file.
You should modify the listen_addrs parameter to your public IP address. You can find these at your UpCloud Control Panel.
listen_addrs = [ { local = "0.0.0.0:443", external = "public_ipv4_address:443" }, { local = "[::]:443", external = "[public_ipv6_address]:443" } ]
You can also change the upstream_addr to point towards your internal recursive DNS server or leave it as is.
Set your provider_name especially if you’re planning to make the service public.
You also have the option to adjust the following parameters:
[dnscrypt] ## Provider name (with or without the `2.dnscrypt-cert.` prefix) provider_name = "example.com" ## Does the server support DNSSEC? dnssec = true ## Does the server always returns correct answers (no filtering, including ad-blocking)? no_filters = true ## Set to `true` if the server doesn't keep any information that can be used to identify users no_logs = true
I also recommend you enable [anonymized_dns] option.
Running DNSCrypt as a system service
Now that you have DNSCrypt installed and the configuration file set, you are almost ready to run the server. However, to make running the DNS server a lot more convenient, you should set it up as a systemd service.
Create a systemd unit file to manage the service. Here I am using the name encrypted-dns. Simply copy and paste the entire code bit below into your SSH terminal.
sudo bash -c 'cat << EOF > /etc/systemd/system/encrypted-dns.service # /etc/systemd/system/dnscrypt-server.service [Unit] Description=DNSCrypt v2 server ConditionFileIsExecutable=/usr/bin/encrypted-dns After=syslog.target network-online.target [Service] StartLimitInterval=5 StartLimitBurst=10 ExecStart=/usr/bin/encrypted-dns -c /opt/encrypted-dns/encrypted-dns.toml WorkingDirectory=/opt/encrypted-dns/ Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF'
Then enable and start the service with the next command.
sudo systemctl enable --now encrypted-dns
If everything went right, you should now be able to verify that the DNSCrypt server is running.
Check the status of the service with the command below.
sudo systemctl status encrypted-dns
● encrypted-dns.service - DNSCrypt v2 server Loaded: loaded (/etc/systemd/system/encrypted-dns.service; disabled; vendor preset: enabled) Active: active (running) since Sat 2021-04-24 12:15:00 UTC; 34min ago Main PID: 44255 (encrypted-dns) Tasks: 3 (limit: 2282) Memory: 23.4M CGroup: /system.slice/encrypted-dns.service └─44255 /usr/bin/encrypted-dns -c /opt/encrypted-dns/encrypted-dns.toml Apr 24 12:15:00 example.com systemd[1]: Started DNSCrypt v2 server. Apr 24 12:15:00 example.com encrypted-dns[44255]: [INFO ] State file [encrypted-dns.state] found; using existing provider key Apr 24 12:15:00 example.com encrypted-dns[44255]: [INFO ] Public server address: 83.136.252.155:443 Apr 24 12:15:00 example.com encrypted-dns[44255]: [INFO ] Provider public key: f18c59e9697b1981ba1a2a44b65f5bded4f0463a58ddf9ff6ec45dedf74b94eb Apr 24 12:15:00 example.com encrypted-dns[44255]: [INFO ] Provider name: 2.dnscrypt-cert.example.com Apr 24 12:15:00 example.com encrypted-dns[44255]: [INFO ] DNS Stamp: sdns://AQcAAAAAAAAAEjgzLjEzNi4yNTIuMT...
If you see an output similar to the example above, your DNSCrypt server is all set.
At the end of the status output, you can see the DNS Stamp of your DNSCrypt server. The DNS Stamp encodes all the parameters required to connect to a secure DNS server as a single string. You can think of the stamps as a QR code for DNS.
Make note of your DNS Stamp e.g. by copying it to your own computer. You’ll need it later to connect to your DNSCrypt server.
Next, you’ll need to be able to utilise the server. Follow on in the next section on how to install a DNSCrypt client on your local system or another Linux Cloud Server and configure it to use your DNSCrypt server.
Enabling secure DNS on your local device
Now that your DNSCrypt server is up and running, you’ll probably want to use it to query DNS requests. To do so, you’ll need to install a DNSCrypt client.
The following DNSCrypt implementing clients support adding custom servers.
- Linux: DNSCrypt-Proxy
- iOS: DNSCloak (GUI)
- Android: RethinkDNS (GUI)
- macOS: DNSCrypt-Proxy
- Windows: YogaDNS (GUI)
You can find an extensive list of DNSCrypt client implementations on the DNSCrypt info page.
For this example, we are installing the DNSCrypt Proxy on another Linux system. This can be used on any local Linux machine as well as all Linux Cloud Servers to utilise your new DNSCrypt server.
First, download a release version of the client.
wget https://github.com/DNSCrypt/dnscrypt-proxy/releases/download/2.0.45/dnscrypt-proxy-linux_x86_64-2.0.45.tar.gz -O ~/dnscrypt-proxy-linux_x86_64-2.0.45.tar.gz
Next, extract the files and change into the resulting directory.
tar -C ~/ -xzf ~/dnscrypt-proxy-linux_x86_64-2.0.45.tar.gz cd ~/linux-x86_64/
Then make a copy of the example configuration file and open the copy for edit.
cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml nano dnscrypt-proxy.toml
Near the beginning of the file under Global settings, you’ll find an example of how to define which DNSCrypt server the proxy will use. By default, the proxy would use every DNSCrypt enabled resolver on the list of public resolvers.
To test your new DNSCrypt server, ignore the other providers for now and enter the following.
server_names = ['myserver']
Then scroll right to the end of the file to create a static listing for a custom server.
Remove the ‘#‘ from the start of the static server definition lines and enter the DNS Stamp of your DNSCrypt server.
[static]
[static.’myserver’]
stamp = ‘sdns://AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg‘
If you didn’t save your DNS stamp anywhere yet, you can always get it by running the sudo systemctl status encrypted-dns command on your DNSCrypt server.
Once done, save the config file and exit.
Lastly, start the DNSCrypt proxy.
sudo ./dnscrypt-proxy --config dnscrypt-proxy.toml
When the proxy starts, it will attempt to connect to your DNSCrypt server. Check the output to see that it was successful.
[2021-04-25 08:06:48] [NOTICE] dnscrypt-proxy 2.0.45
[2021-04-25 08:06:48] [NOTICE] Network connectivity detected
[2021-04-25 08:06:48] [NOTICE] Now listening to 127.0.0.1:53 [UDP]
[2021-04-25 08:06:48] [NOTICE] Now listening to 127.0.0.1:53 [TCP]
[2021-04-25 08:06:48] [NOTICE] Source [public-resolvers] loaded
[2021-04-25 08:06:48] [NOTICE] Source [relays] loaded
[2021-04-25 08:06:48] [NOTICE] Firefox workaround initialized
[2021-04-25 08:06:48] [NOTICE] [myserver] OK (DNSCrypt) - rtt: 19ms
[2021-04-25 08:06:48] [NOTICE] Server with the lowest initial latency: myserver (rtt: 19ms)
[2021-04-25 08:06:48] [NOTICE] dnscrypt-proxy is ready - live servers: 1
You can then start sending DNS queries from your devices to this instance to keep your DNS queries private and secure.
Test it by querying the DNSCrypt server.
nslookup example.com
Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: Name: example.com Address: 93.184.216.34 Name: example.com Address: 2606:2800:220:1:248:1893:25c8:1946
If you are not seeing the live server, make sure your firewall is not blocking the required ports 53 and 443. Also, confirm that your DNS stamp is set correctly and in full. The stamp is much longer than the place holder in the DNSCrypt proxy example configuration file.
Summary
Congratulations! If you’ve made it this far, you should now have a secure DNS resolver running in the cloud and a local proxy client connecting to it. With the DNSCrypt server and client, it’s easy to provide privacy and security for server clusters and home networks alike.