Protect Your DNS Privacy on Ubuntu 20.04/18.04 (DNS over TLS)

This tutorial will be showing you how to protect your DNS privacy on Ubuntu 20.04/18.04 desktop with DNS over TLS. We will use a tool called stubby to achieve that. But first, let me tell you why DNS is not secure.

DNS Vulnerability

DNS is insecure because by default DNS queries are not encrypted, which can be exploited by middle entities. DNS cache poison is one of the DNS abuses that is widely used by the Great Firewall of China (GFW) to censor Chinese Internet. GFW checks every DNS query that is sent to a DNS server outside of China. Since plain text DNS protocol is based on UDP, which is a connection-less protocol, GFW can spoof both the client IP and server IP.  When GFW finds a domain name on its block list, it changes the DNS response. For example, if a Chinese Internet user wants to visit google.com, the Great firewall of China returns to the DNS resolver an IP address located in China instead of Google’s real IP address. Then the DNS resolver returns the fake IP address to the user’s computer.

What is DNS over TLS? How It Protects Your Privacy?

DNS over TLS means that DNS queries are sent over a secure connection encrypted with TLS, the same technology that encrypts HTTP traffic, so no third parties can see your DNS queries. Together with HTTPS and encrypted SNI (Server Name Indication), your browsing history is fully protected from ISP spying.

Stubby is an open-source DNS stub resolver developed by the getdns team. It uses the getdns library. A stub resolver is a small DNS client on the end-user’s computer that receives DNS requests from applications such as Firefox and forward requests to a recursive resolver like 1.1.1.1 or 8.8.8.8. Stubby is special in that it supports DNS over TLS. By default, it will only send DNS requests encrypted. There is another open-source stub resolver called cloudflared that supports DNS over HTTPS but stubby is already in Ubuntu 20.04/18.04 repository and is very easy to use.

How to Install and Use Stubby on Ubuntu 20.04/18.04 Desktop

Stubby is in Ubuntu 20.04/18.04 repository. Open up a terminal window and run the following command to install it.

sudo apt install stubby

This will install stubby and the getdns library. Once installed, stubby runs in the background. You you check its status with:

systemctl status stubby

ubuntu stubby

Stubby listens on TCP and UDP port 53 of localhost (127.0.0.1), as can be seen by running this command:

sudo netstat -lnptu | grep stubby

stubby dns over tls

The default stub resolver provided by systemd-resolved listens on TCP and UDP port 53 of 127.0.0.53.

sudo netstat -lnptu | grep systemd-resolv

systemd-resolved stub resolver

Note: If dnsmasq is listening on TCP port 53 of 127.0.0.1, then Stubby will listen only on UDP port 53 of 127.0.0.1.

The main configuration file is /etc/stubby/stubby.yml. Normally there’s no need to make changes to it unless you want to use another or your own recursive resolver. Let me explain some default configurations. You can open the file with:

sudo nano /etc/stubby/stubby.yml

The following line makes stubby run as a stub resolver instead of a full recursive resolver, which is why it’s named stubby.

resolution_type: GETDNS_RESOLUTION_STUB

The following configuration make stubby send DNS queries encrypted with TLS. It will not send quries in plain text.

dns_transport_list:
- GETDNS_TRANSPORT_TLS

This following line requires a valid TLS certificate on the remote recursive resolver.

tls_authentication: GETDNS_AUTHENTICATION_REQUIRED

The following lines set the listen addresses for the stubby daemon. By default, IPv4 and IPv6 are both enabled.

listen_addresses:
- 127.0.0.1
- 0::1

The following line make stubby query recursive resolvers in a round-robin fashion. If set to 0, Stubby will use each upstream server sequentially until it becomes unavailable and then move on to use the next.

round_robin_upstreams: 1

By default there are 3 recursive resolvers enabled in stubby configuration file. They are run by stubby developers and support DNS over TLS. You can see the full list of recommended servers on DNS Privacy website.

dnsovertls.sinodun.com     145.100.185.15
dnsovertls1.sinodun.com    145.100.185.16
getdnsapi.net              185.49.141.37

There are other DNS servers in the Additional Servers section that are disabled by default.

dns.quad9.net
unicast.censurfridns.dk
dnsovertls3.sinodun.com (supporting TLS1.2 and TLS 1.3)
dnsovertls2.sinodun.com
dns.cmrg.net
dns.larsdebruin.net
......

There are also DNS servers listening on port 443. If port 853 is blocked in your network, you can uncomment them to use these servers.

dnsovertls.sinodun.com
dnsovertls1.sinodun.com
dns.cmrg.net
dns.neutopia.org

Now you can exit nano text editor by pressing Ctrl+X.

Switching to Stubby

Editing the /etc/resolve.conf file to change name server is not recommended any more. Follow the instructions below to make systemd-resolved send DNS queries to stubby.

GNOME Desktop

Click the Network Manager icon on the upper-right corner of your desktop. Then select wired settings. (If you are using Wi-fi, select Wi-fi settings.)

encrypt dns

Click the gear button.

cloudflare dns over tls

Select IPv4 tab, then in DNS settings, switch Automatic to OFF, which will prevent your Ubuntu system from getting DNS server address from your router. Enter 127.0.0.1 in the DNS field. Click Apply button to save your changes.

dns over tls port 853

Then restart NetworkManager for the changes to take effect.

sudo systemctl restart NetworkManager

Once you are reconnected, you can see that your Ubuntu system is now using 127.0.0.1 as the DNS server in the Details tab.

stub resolver dns over tls

Unity Desktop

Recommended reading: how to install Unity desktop environment on Ubuntu 20.04/18.04.

Click the Network Manager icon on the upper-right corner of your desktop, then click edit connections.

network manager change DNS

Select your connection name and click the gear icon.

stubby systemd-resolved

Select IPv4 settings tab, change method from Automatic(DHCP) to Automatic(DHCP) addresses only, which will prevent your Ubuntu system from getting DNS server address from your router. Then specify a DNS server (127.0.0.1). Stubby listens on 127.0.0.1.

ubuntu dns over tls

Save your changes. Then restart NetworkManager for the changes to take effect.

sudo systemctl restart NetworkManager

Once you are reconnected, click the Network Manager icon again and select connection information. You can see that your Ubuntu system is now using 127.0.0.1 as the DNS server.

ubuntu 18.04 dns over tls

Change DNS Server From Command Line

You can use the method below to change DNS server as long as your desktop environment is using NetworkManager.

Open a terminal window and go to the Network Manager connections profile directory.

cd /etc/NetworkManager/system-connections/

Then list connection names available on your system.

ls

network manager change dns server from command line

As you can see, I have several connections on my system, one of which is wired connection. Some are wireless connections and one is VPN connection. Because my desktop computer is connected to my router via an Ethernet cable, so I need to edit the wired connection profile with the nano command line text editor.

sudo nano 'Wired connection 1'

If your computer is connected via Wi-fi, then you need to edit the wireless connection profile. In this file, find the [ipv4] configurations. By default, it should look like this:

[ipv4]
dns-search=
method=auto

To make your system use Stubby, change the configurations to the following.

[ipv4]
dns=127.0.0.1;
dns-search=
ignore-auto-dns=true
method=auto

To save the file in Nano text editor, press Ctrl+O, then press Enter to confirm. Press Ctrl+X to exit. Then restart Network Manager for the changes to take effect.

sudo systemctl restart NetworkManager

You can now check your current DNS server by running the following command:

systemd-resolve --status

Sample output:

Link 2 (enp5s0)
Current Scopes: DNS
LLMNR setting: yes
MulticastDNS setting: no
DNSSEC setting: no
DNSSEC supported: no
DNS Servers: 127.0.0.1

If 127.0.0.1 is listed as the DNS server, then your system is using Stubby.

Ignore the DNS Settings Provided by DHCP Server

If you use Ubuntu server edition, you can configure systemd to ignore the DNS settings provided by the DHCP server, so your system won’t be accidentally using the wrong DNS server.

First, check the status of your network interface.

networkctl status enp5s0

It will show you the network file for this interface. Edit this network file.

sudo nano /run/systemd/network/10-netplan-enp5s0.network

Find the [DHCP] section and add the following line.

UseDNS=false

Like this:

[DHCP]
RouteMetric=100
UseMTU=true
UseDNS=false

Save and close the file. Then restart systemd-netweorkd.service for the change to take effect.

sudo systemctl restart systemd-networkd

Run the following command to check the DNS servers for each network interface. If everything is correct, you won’t see the DNS server provided by your DHCP server.

resolvectl status

Changes in the network file can be overridden by a new package update. If your server uses netplan to manage network connection, you can also configure netplan to ignore DHCP DNS settings.

sudo nano /etc/netplan/50-cloud-init.yaml

Add the following two lines to the file.

       dhcp4-overrides:
           use-dns: no

Like this:

network:
    ethernets:
        eth0:
            dhcp4: true
            dhcp4-overrides:
                use-dns: no
            optional: true
            set-name: eth0
            nameservers:
               search: [ invalid ]
               addresses: 127.0.0.1
    version: 2

Save and close the file. Then apply the changes.

sudo netplan apply

How to Check if Your DNS Traffic is Encrypted

We can use WireShark to monitor DNS traffic. Install WireShark from Ubuntu 20.04/18.04 repository.

sudo apt install wireshark

If you are asked “Should non-superusers be able to capture packets?”, answer Yes. Once it’s installed, run the following command to add your user account to the wireshark group so that you can capture packets.

sudo adduser your-username wireshark

Log out and log back in for the changes to take effect. Then open WireShark from your application menu, select your network interface in WireShark. For example, my Ethernet interface name is enp5s0. Then enter port 853 as the capture filter. This will make WireShark only capture traffic on port 853, which is the port used by DNS over TLS.

ubuntu 18.04 stubby

Click the button on the upper-left corner to start capturing. After that, in terminal window, run the following command to query domain name by using the dig utility. For instance, I can query the A record of my domain name.

dig A linuxbabe.com

Now you can see the captured DNS traffic in WireShark. As you can see, my DNS query was sent to 185.49.141.37, 145.100.185.15 and 145.100.185.16, which are the 3 default DNS resolvers defined in stubby configuration file. Connections were made over TCP and encrypted with TLS, which is what I want.

secure dns

If DNS queries are sent without encryption, then the computer would contact DNS server on port 53. You can capture packets again with port 53 as the capture filter, but you won’t see any packets in WireShark, which means stubby is encrypting your DNS queries.

How to Add CloudFlare DNS to Stubby

I found that there is high latency (over 200ms) between my computer and the 3 default DNS servers, whereas CloudFlare DNS servers (1.1.1.1, 1.0.0.1) give me very low latency (below 20ms). CloudFlare also supports DNS over TLS. To add CloudFlare DNS server, edit stubby configuration file.

sudo nano /etc/stubby/stubby.yml

Scroll down to the upstream_recursive_servers: section and add the following text above other DNS servers.

#CloudFlare servers
  - address_data: 1.1.1.1
    tls_auth_name: "cloudflare-dns.com"
  - address_data: 1.0.0.1
    tls_auth_name: "cloudflare-dns.com"

Then find the following line:

round_robin_upstreams: 1

Change 1 to 0. This will make stubby always use CloudFlare DNS server. If CloudFlare is not available, stubby will use other DNS servers. Save the file and restart stubby for the changes to take effect.

sudo systemctl restart stubby

DNS over HTTPS Support

Stubby will support DNS over HTTPS in version 0.3. Ubuntu 20.10 ships with version 0.2.6. To check Stubby version, run

stubby -V

Wrapping Up

I hope this tutorial helped you protect your DNS privacy on Ubuntu 20.04/18.04 with DNS over TLS. As always, if you found this post useful, then subscribe to our free newsletter to get more tips and tricks. Take care.

Rate this tutorial
[Total: 41 Average: 4.4]

38 Responses to “Protect Your DNS Privacy on Ubuntu 20.04/18.04 (DNS over TLS)

  • Stephen McGregor
    3 years ago

    I am on Xubuntu 16.04… as such, stubby is not in the repository. I am a relatively amateur Linux user, so I was wondering if I could get some alternative instructions for my scenario. TIA. (I’ve included what happens when I go to install stubby).

    “sudo apt-get install stubby
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    E: Unable to locate package stubby”

  • sir, what about opendns, whether it can be used as DNS over TLS. how to use stubby under Ubuntu 16.04 LTS desktop. It is not in the repository.

    • whether stubby can be installed from the following for Ubuntu 16.04 (https://gist.github.com/LeeiFrankJaw/0735005da8ecbb730861ea03b7af261b). going for fresh install of 18.04 always there. would like to use opendns or ibm quad or googld dns or native dns provider. how to check whether native dns provider supports dns over tls?

  • Hi
    I have got Stubby install and config the file as above mention but when I issue the command “systemd-resolve –status” I got this output as below. Is my traffic DNS over TLS? I am using Linux Mint 19 Tara XFCE

    [email protected]:~$ systemd-resolve –status
    Global
    DNSSEC NTA: 10.in-addr.arpa
    16.172.in-addr.arpa
    168.192.in-addr.arpa
    17.172.in-addr.arpa
    18.172.in-addr.arpa
    19.172.in-addr.arpa
    20.172.in-addr.arpa
    21.172.in-addr.arpa
    22.172.in-addr.arpa
    23.172.in-addr.arpa
    24.172.in-addr.arpa
    25.172.in-addr.arpa
    26.172.in-addr.arpa
    27.172.in-addr.arpa
    28.172.in-addr.arpa
    29.172.in-addr.arpa
    30.172.in-addr.arpa
    31.172.in-addr.arpa
    corp
    d.f.ip6.arpa
    home
    internal
    lines 1-23

    • If the output of systemd-resolve --status contains DNS Servers: 127.0.0.1, then your system is using Stubby.

    • I’m not using XFCE desktop, but I added instructions on changing DNS server from command line. Please see “A Desktop-Agnostic Way to Change DNS Server” section in this article.

  • Dear Xiao Guo
    Thank you.

  • Thank you Xiao, very useful resource.

  • Below page claims Stubby doesn’t have a cache and it provided a guide on how to enable it on dnsmasq. But what should be done in Ubuntu?

    https://wiki.archlinux.org/index.php/Stubby#Local_DNS_cache_configuration

    • Omnominous
      2 years ago

      Stubby may not include any caching abilities, but I’m pretty sure systemd-resolved does.

  • Wow this so easy than install dnscrypt. I don’t know this software works like dnscrypt or not. But i tried using this software, and i can access reddit again. Thank you.

  • Thanks, great! Now I am DNSoverTLS secured! (

    systemd-resolved

    already can support some of it, but has no certificate verification, to name only one problem).

    sudo netstat -lnptu | grep systemd-resolve

    only works when the process ID has at most 3 digits. Once the PID grows to 4 (or 5) digits, 1 (or 2) letters are cut off from the end. So one should

    grep systemd-resol

    only.

  • Chosing one of the quad-{1,8,9} DNS providers may be convenient, but we do not know for sure what they are doing with our data.

    To reduce delays, chose a trustworthy organization nearby. In Switzerland, this could be e.g. Digitale Gesellschaft, an association that merged with the Swiss Privacy Foundation. Their public DoT/DoH servers are described here: https://www.digitale-gesellschaft.ch/dns

  • I edited my yml file to just two providers and 5 addresses. 2 IPv4 for each server and one IPv6 for one server. I kept “round_robin_upstreams: 1”. My DNS is working, but how can I check that all 5 entries are working? Is there a log somewhere I can check? I have done numerous checks and have seen both of the servers in my settings be listed, but never concurrently. I just wanted to ensure all 5 addresses are correct. Thanks.

  • 兄弟,搞一篇文章 ,谈谈如何搭建‘dns-over-tls’ server吧。我搞了好久,都没搞好

    Hey bro, how to set up a dns-over-tls server? I can’t manage to configure it properly.

    • 想写一篇,但暂时有其他事。

      I intended to write an article on this, but I don’t have time right now.

    • Setting up a DNS-over-TLS server is actually very simple.

      First, you need to set up a dns resolver using BIND, unbound, or whatever DNS software you prefer. You can check out my BIND tutorial below.

      Then you can set up Nginx to act as a DNS proxy for BIND. Add the following lines in /etc/nginx/nginx.conf file. They need to be placed outside of the http context.

      stream {
          # DNS upstream pool
          upstream dns {
              zone dns 64k;
              server 127.0.0.1:53;
          }
      
         # DoT server for decryption
         server {
              listen 853 ssl;
              ssl_certificate /etc/letsencrypt/live/dot.example.com/fullchain.pem;
              ssl_certificate_key /etc/letsencrypt/live/dot.example.com/privkey.pem;
              proxy_pass dns;
          }
      }
      

      Nginx will terminate TLS on port 853, then it will redirect DNS requests to the local DNS resolver listening on 127.0.0.1:53. You need to obtain your own TLS certificate from Let’s Encrypt.

      Save and close the file. Then test Nginx configuration and restart.

      sudo nginx -t
      sudo systemctl restart nginx

      Note that if you use CentOS, you need to allow Nginx to listen on port 853 with the following command.

      sudo dnf install policycoreutils-python-utils
      sudo semanage port -m -t http_port_t -p tcp 853

      Open port 853 in firewall.

      Ubuntu:

      sudo ufw allow 853/tcp

      CentOS:

      sudo firewall-cmd --permanent --zone=public --add-port=853/tcp
      sudo systemctl restart firewalld

      Since we are using DNS over TLS, there’s no need to worry about DNS amplification attack.

      Now configure Stubby to use your own DNS over TLS server.

  • Serhan
    1 year ago

    Thank you, it was quite easy to do with your instructions…

    • Serhan
      1 year ago

      I’ve just realized that youtube does not work… Do you have any idea why?

      • Serhan
        1 year ago

        🙂 Very sorry, it is kind of sown in my country at the moment…

  • If I used your previous tutorial when creating a local DNS server on linux, the queries from that DNS server don’t have TLS encryption by default as I understand. So using this tutorial on top of the previous one will work right?

    • To use your own DNS over TLS resolver, you need to set up one at a remote location like a VPS (virtual private server). To set up a DNS over TLS resolver on a VPS, please read this comment.

  • Koutheir
    10 months ago

    Thank you for the detailed explanations!

  • I assume these instructions work for 20.04 just as well? Maybe even using the same yml file?

  • Hi, I’m running Ubuntu server 20.04.1 with no desktop. How can I change the nameserver?

  • Thanks for this, was having problems with dnscrypt. This is working great on ubuntu server 20.04. I also use it with dnsmasq for caching and for local dns/dhcp. See the link that Mahdi left.

    To set the dns/nameserversd with no GUI or Network nameager in Ubuntu edit the netplan yaml file probably called:

    sudo nano /etc/netplan/00-installer-config.yaml

    network:
      ethernets:
        enp0s8:
          addresses:
          - 192.168.1.2/24
          gateway4: 192.168.1.1
          nameservers:
            addresses:
    # This is the setting you are after
            - 127.0.0.1
      version: 2
    
  • hello I’m using stubby version 0.3.0, however I couldn’t find a way to use DoH instead of DoT do you have any tutorial/documentation about it?

    • There’s currently no documentation for DoH in Stubby. You can use dnscrypt-proxy to enable DoH. Simply run the following command on your Ubuntu desktop and you are done.

      sudo apt install dnscrypt-proxy

      By default, dnscrypt-proxy uses Cloudflare DoH resolver.

  • xperimental
    2 months ago

    I need to restart NetworkManager every boot in order for Stubby to work, any solution? i think the DNS is reset to default on every boot

  • thank you, LinuxBabe, for an excellent tutorial.

    Does anyone know if Stubby will work on non-systemd linux? And what would have to be done? Everything I’ve seen entails systemd.

    • You can check if Stubby is your distro’s repository. If not, you have to manually compile it from source. Read the Stubby documentation.

      • Xiao,
        Thanks. Yes, it is there. But the base repository is from Debian, and I think systemd is the default there. Whereas MX, which is based on Debian, offers both systemd and initd boot options, but defaults to Initd, and thus far I have stuck to initd.

        So I installed DNSCrypt-proxy via the repo, for instance, but have been unable to get it to start.

    • On initd systems, the command is usually sudo service stubby start.

      Linux beginners should use systemd in my opinion. If you don’t know how to use initd, then it’s likely you don’t really know why it’s better than systemd. I have been a Linux user for more than 10 years and I don’t use initd distros anymore.

      • I did try that for dnscrypt, but it brought an error I don’t recall. Trying just now with stubby brought:

        stubby: unrecognized service

        I have a strong anti-centralization tendency, and have resisted the move to systemd. But it seems the world has gone there. I might need to capitulate.

        Thanks for you input!

      • After consideration, I’ve taken your advice and switched to the systemd boot option. My machine actually runs a bit better now, which for a Vista-era C2D tower surprises me. I then installed the NextDNS client, rebooted, and now have DoH DNS.

        Thanks much for your input.

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded.