Before getting down to the nitty-gritty of how to configure DNS over TLS, also known as DoT, on a GNU/Linux system using systemd as the init system, let's take a look at the needs that DoT meets.
Mostly we are daily using the DNS service. To put it simple, DNS (Domain Name System) is a service that use the port 53 and mostly the UDP protocol. Its general purpose is to translate domaine names to IP addresses.
Concretely, if we want to connact to another system, that can be a website for example, we use a domain name (e.g. www.fsf.org or www.b42agov7.org). Nevertheless our systems use IP addresses (which are difficult to memorize for us humans) to connect to other systems.
In this way, when we want to connect to another system, we use a domain name that's easy for us to remember and the DNS service translates this domain name into an IP address so thaht our system can actually connect via an IP address to the system we want.
The DNS service which is a local DNS resolver on our system performs DNS resolutions ("translations") of domain names into IP addresses. It's done thanks to DNS queries toward others DNS servers, which are "DNS Recursive Resolver", that themselves interact with "DNS ROOT Nameserver", "DNS TLD Nameserver" and "Authoritative Nameserver" They will make the translation of domain names into IP addresses gradually.
You can use the command dig +trace @"your dns server" "target domain"
to see how a DNS resolution is accomplished.
The DNS service is defined in RFC 1034 and RFC 1035.
However, the DNS service sends these DNS requests to the DNS servers in plain text on port 53 using the UDP protocol. Because of this, a malicious person who perform a MITM (Man In The Middle) attack can know exactly what are you doing.
This has an impact on confidentiality, privacy and security!
For example, with the Wireshark tool, I'm able to easily retrieve all DNS requests made at a given time when I listen to network traffic with this filter:
dns.flags.response == 1 && dns.a || dns.aaaa
.
Let's say I'm a vicious attacker and I've managed to monitor Bob's traffic and applied the Wireshark filter mentioned above, I can deduce that Bob wants to visit Berlin, he'll take a flight via Lufthansa and that he intends to take an accommodation available on Booking.com.
But how do you prevent this kind of breach of confidentiality, privacy and security?
That's where DoT comes in. DoT stands for DNS over TLS (Transport Layer Security). DoT enables us to encrypt our DNS requests via TLS. DoT is defined in RFC 7858 and RFC 8310.
DoT adds a layer of TLS encryption and uses TCP port 853 to secure our DNS queries.
As a result, our DNS queries will no longer be in plain text, and no malicious actor will be able to see or even attack our DNS requests.
We're going to implement DoT on a GNU/Linux system whose init system is systemd, just follow a few simple steps! In this article, the configured system will be Fedora.
Systemd has a name resolution service. It's called systemd-resolved. We'll use this service to configure and use DoT on our system.
We can see its status with the command systemctl status systemd-resolved.service
.
To check the status of our DNS configuration via systemd-resolved, we use the resolvectl status
command.
The DNS servers we're querying (1.1.1.1 in our case), as well as the status of DoT (-DNSOverTLS) or DNSSEC (which we'll look at in another article) and the mode of our local resolver (stub) are all shown.
To configure DoT with systemd-resolved, let's read the revolved.conf manual man 5 revolved.conf
.
We learn that we need to configure a file called revolved.conf.
The options we're interested in are: DNS= (so we're going to configure DNS manually) and DNSOverTLS=.
Here's an extract about the DNSOverTLS= option:
Takes a boolean argument or "opportunistic". If true all connections to the server will be encrypted. Note that this mode requires a DNS server that supports DNS-over-TLS and has a valid certificate. If the hostname was specified in DNS= by using the format "address#server_name" it is used to validate its certificate and also to enable Server Name Indication (SNI) when opening a TLS connection. Otherwise the certificate is checked against the server's IP. If the DNS server does not support DNS-over-TLS all DNS requests will fail.
To enable DoT, we must must put DNSOverTLS on yes.
Under Fedora, by default the revolved.conf file is located in /usr/lib/systemd/resolved.conf.
This file gives us this information:
Local configuration should be created by either modifying this file (or a copy of it placed in /etc/ if the original file is shipped in /usr/), or by creating "drop-ins" in the /etc/systemd/resolved.conf.d/ directory. The latter is generally recommended. Defaults can be restored by simply deleting the main configuration file and all drop-ins located in /etc/.
We'll take the last option, which is to create a file in the /etc/systemd/resolved.conf.d/ directory. In this file, we'll configure the DNS and DNSOverTLS options.
sudo mkdir /etc/systemd/resolved.conf.d
echo '
[Resolve]
DNS=1.1.1.1
DNS=2606:4700:4700::1111
DNS=1.0.0.1
DNS=2606:4700:4700::1001
DNSOverTLS=yes
' | sudo tee /etc/systemd/resolved.conf.d/dns.conf
sudo systemctl restart systemd-resolved.service
Note that the DNS servers used here are those of Cloudflare. These servers support DoT.
Now, if we run the resolvectl status
command again, our new DNS are configured and DNSOverTLS is enabled (+DNSOverTLS).
Implementing DoT on a system using an init system other than systemd is completely different from the procedure presented here!
If we run a Wireshark capture again, we can't see DNS queries in plain text since they are now encrypted!
In this article, we discovered the importance of protecting our DNS requests. We learned that DoT enables us to encrypt our DNS requests using TLS and port 853 on TCP.
We also studied how to implement DoT on a Fedora system (the process for implementing DoT on other systems such as Debian, Gentoo (with systemd), Arch Linux, Red Hat, Ubuntu, Linux Mint, etc... is pretty much the same).
However, you'll notice that a network administrator can tell that DoT is being used, since it's a specific port.
If we want to hide the fact that we're encrypting our DNS requests, we should use DoH (DNS over HTTPS) instead. DoH encrypts DNS requests and uses the HTTP or HTTP/2 protocol. So DoH enables us to encrypt our DNS requests and hide them in an HTTPS stream, making the task of discovering the use of encrypted DNS requests very complicated.
There is a system-wide implementation of DoH. It is available at this git repository here.