The Domain Name System (DNS) was created in the early 80s, but still is one of the most important building blocks of the Internet. It allows mapping human-readable names to IP addresses. Any disruption of this service usually has a severe impact, since most systems and end users utilize name resolution instead of relying on fixed IP addresses.
Back in the days when the DNS protocol was born, the Internet was a different place and the original design didn’t include any particular security features. However, with the rapid growth of the Internet in the 90s, some major security flaws became apparent. One of the biggest problems was a lack of data integrity and origin assurance of DNS messages. A solution for that was provided in 1997 (with a significant improvement in 2005) and is called Domain Name System Security Extensions (DNSSEC).
The following article gives an insight into DNSSEC general principles. It provides practical examples, describing how DNSSEC works and how it can be used. Finally, it gives some information about the current adoption of this extension worldwide.
DNS architecture
There are several major components that make up DNS:
- The namespace – a tree-like structure where each leaf is a domain. Each domain may contain records used to map specific names to other values (usually to IP addresses).
- Authoritative DNS servers – these hold information about one or more domains and respond to queries for those domains.
- Resolvers – hosts that perform resolution. These might be both user computers which perform resolution for their own purposes (stub resolvers), but also dedicated servers located within organizations or arranged by ISPs, that perform resolution on behalf of other hosts (recursive resolvers).
The figure below shows the hierarchical structure of the DNS namespace:
At the very top resides the root domain indicated by a dot. The first level contains top-level domains (TLD), e.g. com, net, pl. Then we have second-level domains (2LD), e.g. google, codilime, etc. Next we can have third-level domains, and so on.
The term “domain” is somewhat ambiguous. It can refer to a specific leaf in the DNS namespace tree (e.g. com), but usually represents a whole branch. In such a case a domain name consists of names of specific leafs, separated by dots, and ordered from the lowest level, up to the root (e.g. codilime.com). Throughout this article we will be using the latter definition.
Another important term often used to describe DNS names is FQDN (fully qualified domain name). It is a host name that specifies its exact location within the DNS hierarchy. An FQDN is created by appending a domain to the original host name. So, if our host is named e.g. host1 and the domain is example.com, the FQDN of that host would be host1.example.com.
From a formal standpoint, to represent a full path in the DNS tree, we should always add a dot at the end, which means the root (e.g. codilime.com.). Otherwise the name is interpreted only as a domain prefix. For a human being it is quite obvious that codilime.com and codilime.com. means the same thing, but a resolver installed on a client machine is not that smart, and when querying codilime.com (without a dot at the end) it first tries to attach a locally configured DNS suffix. If the resolution fails, then it uses the original name. The figure below shows a Wireshark snippet depicting such a scenario, where a Windows computer with a configured mhlan.local DNS suffix (ipconfig output below) queries codilime.com (without a dot at the end):
> ipconfig /all Wireless LAN adapter Wi-Fi: Connection-specific DNS Suffix . : mhlan.local Description . . . . . . . . . . . : Intel(R) Wi-Fi 6 AX201 160MHz ... > nslookup -type=A codilime.com Non-authoritative answer: Name: codilime.com Addresses: 172.67.74.43 104.26.10.176 104.26.11.176
Note that each authoritative server has full knowledge only about its own set of domains. It means that the server responsible - e.g. for the com domain - doesn’t know anything about specific records within the google.com domain. Instead, it only has information about authoritative servers for that second-level domain. This is called “delegation”. Of course not every subdomain must be delegated to a different server or a set of servers.
DNS data stored on an authoritative server is organized into “zones”. Each zone represents a single domain and, optionally, all of its subdomains. So, a DNS administrator can create a single zone called example.com which contains records both from example.com, subdomain1.example.com and subdomain2.example.com, but also can create three separate zones, one for each mentioned domain.
As an example, let’s list all authoritative servers for the whole DNS tree branch represented by the infotest.com.pl name.
Zone | Authoritative name servers |
---|---|
. (root) | a.root-servers.net ... m.root-servers.net |
pl. | a-dns.pl b-dns.pl d-dns.pl f-dns.pl h-dns.pl j-dns.pl |
com.pl. | (same as for pl) |
infotest.com.pl. | ns1.cplab.tk ns2.cplab.tk |
Table 1 Authoritative servers for infotest.com.pl and upstream zones
As you can see, every zone has multiple authoritative name servers. Each server for a specific zone has exactly the same configuration, so there is no difference which one is queried. Usually within each domain there is one designated primary server. All other authoritative servers from that domain sync up to this device regularly in a process called “zone transfer”.
DNS protocol basics
DNS protocol realizes the “client/server” principle and uses two message types: query and response. Each DNS message contains up to five sections, depending on the type:
Name | Size (bytes) | Present in Query/Response (Q/R) | Description |
---|---|---|---|
Header | 12 | Q, R | Contains message ID, type, flags, number of other sections |
Question | variable | Q, R | Contains one or more queries; this section is replicated in a response message |
Answer | variable | R | Contains one or more responses with resource records |
Authority | variable | R | Contains one or more records with authoritative name servers |
Additional | variable | R | Additional records |
Table 2 DNS message
The header itself consists of the following fields:
Name | Size (bytes) | Description |
---|---|---|
ID | 2 | Message ID |
Flags | 2 | Place for different flags and response codes (e.g. indicating errors) |
QDCOUNT | 2 | Number of questions in a message |
ANCOUNT | 2 | Number of resource records in the Answer section |
NSCOUNT | 2 | Number of resource records in the Authority section |
ARCOUNT | 2 | Number of resource records in the Additional section |
Table 3 DNS header
Note that for every query/response pair, the ID value must be the same. This way, a client sending a specific question is able to distinguish a proper response from other messages coming from the same server.
DNS defines several record types, each containing a different set of information. The most popular are:
- SOA (start of authority) – record storing important information about the zone as a whole, e.g. the primary authoritative server, email address of the administrator, global timers, etc.
- NS (name server) – record indicating authoritative name server for a specific zone (a single zone may contain multiple NS records).
- A (address)– record containing mapping between a specific name (e.g. www) within a zone and IPv4 address. Equivalent for IPv6 is AAAA.
- MX (mail exchange)– record indicating a mail server for a specific zone.
- CNAME (canonical name) – alias that maps one name into another.
The figure below shows a typical response for a DNS query concerning a specific A record (www.infotest.com.pl). In the Answer section we can see a resolved IP address – 195.116.28.144.
DNS by default uses the UDP protocol and destination port 53 to exchange information. In this mode, messages are limited to 512 bytes by default. Longer messages (typically responses) are truncated, which is indicated by a by special flag in the header:
After receiving such a message, the client can try again, but this time using the TCP protocol (also on port 53).
There is however an extension to the standard DNS protocol, that allows us to use larger UDP messages (up to 4096 bytes) – EDNS0 (extension mechanism for DNS). It also provides support for additional DNS functionality – DNSSEC. By using a “pseudo-record” of the OPT type, described in the EDNS0 specification, hosts sending DNS messages (both clients and server) are able to communicate to each other the largest UDP payload that they can reassemble within their network stack. An OPT is called a “pseudo-record” because it doesn’t hold any information that would directly influence the resolution result, only auxiliary DNS metadata.
If we take a closer look at the DNS packets depicted in Figures 3 or 4, we will see additional OPT record, containing information about supported message length:
What is DNSSEC and why do we need it?
As you can see from the previous section, the DNS protocol doesn’t have any built-in security features, like message encryption or data integrity verification. Anyone who intercepts a DNS query can create a bogus reply which will be accepted by the client, as long as the IP addresses, UDP ports and the response message ID are correct.
Over the years, there have been multiple techniques developed for DNS spoofing – that is, injecting bogus DNS information. One of those methods is cache poisoning. This kind of attack is usually aimed at DNS resolvers – recursive DNS servers that query other (authoritative) servers, on behalf of hosts.
To understand how cache poisoning works, first we need to understand what “recursive” really means in terms of DNS. A recursive DNS server is a host that usually doesn’t have any DNS zones configured. Instead, it receives queries from other hosts and tries to resolve them by querying authoritative DNS servers.
Let’s see how all those components interact with each other using the example shown in Figure 6:
- The host (e.g. a computer or laptop) sends a request to a DNS server for the www.infortest.com.pl A-record. Information about the DNS server that needs to be used usually comes from the network configuration settings of a specific host.
- The recursive server doesn’t have an answer for that request in its internal cache, so it first queries one of the root authoritative servers (see Table 1), also for www.infotest.com.pl.
- The selected root server doesn’t have information about this specific domain; instead it sends a list of authoritative servers for the pl domain.
- The recursive server repeats the query, this time asking one of the authoritative servers of the pl domain.
- The authoritative server for pl doesn’t know anything about www.infotest.com.pl. Instead it knows the servers holding the infotest.com.pl domain and sends this information back to the resolver.
- The recursive server again repeats the query, this time asking one of the DNS servers responsible for the infotest.com.pl domain.
- The authoritative server of the infotest.com.pl domain responds with an A-record.
- The recursive server replies to the host with an answer containing an IP address of the requested resource.
In a distributed system like DNS, the resolution process may actually consist of many single query/response transactions performed with different servers. The example above presents only a simplified depiction of the process. In reality, the recursive server would have even more work to do. Information about authoritative servers in NS records is presented as names and not IP addresses. This means that the recursive server must also resolve these names into IP addresses before sending further queries. In our case, the name servers for the infotest.com.pl zone are from a completely different top-level domain than the requested name. The resolver must first find an IP of ns1.cplab.tk in order to finalize the resolution of www.infotest.com.pl. This means going through the whole process again, but this time for the name of the authoritative DNS server.
In reality, recursive servers cache information about different records for the time specified in the TTL (time to live) field defined for each record. And usually they don’t need to make a full cycle; instead they respond to hosts with cached information. This significantly reduces DNS traffic and speeds up the resolution time.
Having all that in mind we can now describe the nature of the DNS cache poisoning attack. The main goal of an attacker is to spoof responses from an authoritative server (steps 3, 5, 7 in Figure 6) and deliver them before legitimate answers arrive. Such spoofed information is then retained by the recursive server for the time specified by the TTL (usually hours or even days) and relayed to all its clients. Such clients can be now redirected to a malicious webpage, even if they enter a correct name in their browsers.
If communication between resolvers and authoritative servers is based on UDP, there are actually three things that the attacker needs to do to successfully perform such attack:
- send a response before the legitimate server,
- guess the message ID number (a 16-bit number = only 65536 combinations – susceptible to brute force attacks),
- guess the source UDP port (usually such ports are not completely random, making them quite easy to guess).
DNS cache poisoning attacks are not performed only on resolvers. Another common scenario is to directly attack the users' computers. Note that DNS clients also cache responses and the technique described above is also applicable to them.
The main problem here is that the DNS protocol itself doesn’t have any mechanism to validate DNS responses. There are ways to make cache poisoning attacks harder to perform (e.g. better randomization of source UDP ports), but still we can’t be sure if the received DNS response contains valid information.
This is where DNSSEC steps in. The first DNSSEC specification was published in 1997. Its refined version was released in 2005. It is short for Domain Name System Security Extension and it is a means of verifying DNS data integrity and origin. Similar to TLS/SSL, it uses public key cryptography to verify and authenticate data.
DNSSEC principles
DNSSEC adds cryptographic signatures to existing DNS records. These signatures are stored together with other well-known record types, like A or NS. By checking the signature that comes together with a specific record in the DNS response, you can be sure that the requested information wasn’t spoofed along the way. Note that DNSSEC doesn’t provide any encryption of DNS data. Queries and responses are still sent in clear text.
First of all, to facilitate DNS data validation, DNSSEC introduced several new record types:
- RRSIG (resource record signature) – contains a cryptographic signature.
- DNSKEY (DNS key) – contains a public key of a specific domain, used to verify signatures.
- DS (delegation signer) – contains a hash of a DNSKEY record, used to create trust between a child domain and its parent.
- NSEC, NSEC3, NSEC3PARAM (next secure record/parameters) – records used to confirm that specific records don't exist.
An important thing to note is that DNSSEC doesn’t sign single records, but sets of records related to the same resource (so-called resource record sets - RRsets):
Each zone on a DNSSEC-enabled server has two pairs of keys:
- Zone Signing Key (ZSK) pair – the private key is used to digitally sign RRsets. These signatures are then stored in RRSIG records among other records like A or NS. The public portion, on the other hand, is used to verify signatures and it is stored in a DNSKEY record.
- Key-Signing Key (KSK) pair – the public KSK key is published in a separate DNSKEY record. The private key is used to sign the DNSKEY RRset (with ZSK and KSK key), which creates an RRSIG record for DNSKEY.
ZSK keys are used more frequently and therefore are usually shorter than KSK keys (in general, shorter keys also mean better resolution times). It is also much easier to replace compromised ZSK keys than KSK. Rotation of the KSK key influences trust created between zones, as we will explore in more detail later. Therefore, as a general rule, KSK keys should be long enough to withhold longer rollover periods (usually years). They also should be treated with greater care.
The signing process, in general, consists of two steps:
- The Resource Record set is run through a hash function.
- The hashed value is then encrypted by a private key (KSK or ZSK, depending on the record type).
Validation in turn requires the following steps:
- The specific RRset that needs to be verified is run through a hash function.
- The value located within the associated RRSIG record is decrypted using a public ZSK or KSK key; we get a hashed value of a specific RRset.
- Both values are compared with each other. If they match, the RRset is positively verified.
When a DNS administrator wants to enable DNSSEC in a zone, he creates RRSIG records for every RRset within this zone. For traditional record types, like A, NS or MX, this is done by signing the RRset with a private ZSK key:
DNSKEY records are, in turn, signed by the KSK key:
Validation performed by a resolver includes checking both the requested RRset (e.g. of the NS type) but also the ZSK key that was used for that process. It consists of the following steps (Figure 12):
- The resolver requests a specific record (e.g. NS for the infotest.com.pl zone). It gets a response together with an associated RRSIG record.
- Next the resolver requests the DNSKEY record. Within the response it gets the RRset containing both ZSK and KSK DNSKEY records. The RRSIG record for the DNSKEY RRset is also sent along the way.
- The resolver verifies the NS RRset using the ZSK public key taken from the respective DNSKEY (it compares the NS RRset hash with a value obtained from decrypting the corresponding RRSIG using the public ZSK key).
- The resolver verifies the DNSKEY RRset itself (containing the ZSK public key) using the KSK public key, also delivered within that DNSKEY RRset (it compares the DNSKEY RRset hash with a value obtained from decrypting the corresponding RRSIG using the public KSK key).
It is worth noting that DNSSEC records can be cached like any other records, which saves authoritative servers from being constantly queried, and also speeds up the resolution time.
The Chain of Trust
When analyzing the validation process presented above you probably asked yourself a question: How would I know that the obtained KSK public key is legitimate? DNSSEC allows us to verify that by using a new record type – DS (delegation signer). This record contains a hash of the KSK public key and is installed at the parent domain level. To be able to verify the correctness of the DS record, the parent domain should also be secured by DNSSEC, which means that the DS record should be accompanied by its RRSIG record. The figure below shows the process of creating a hash from the child’s domain (infotest.com.pl) public KSK key and installing it at the parent domain level (com.pl) as a DS record, together with signing this record using the ZSK private key of the parent domain.
So now we can validate the KSK key of the child zone by verifying the DS record in the parent zone, using the same approach that was used for the NS RRset within the child zone. The KSK key of the parent zone can be verified by using the DS record located at the next level in the DNS namespace tree, and so on.
This process repeats until we reach the root zone. The root zone contains DS records for the top-level domain public KSK keys. These records are also signed by the root level private ZSK key. However, because the root domain is at the top of the DNS namespace tree, there is no other place where we can validate the public root KSK key. So the only thing that we can do is to arbitrarily trust the public root KSK key and hope that its private key is in the hands of really responsible people.
Fortunately, nothing is left to chance when it comes to handling root KSK keys. At the moment, IANA is the organization that keeps the private portion of the root KSK locked away. All operations that involve using the private key are strictly controlled and audited. They are performed periodically during so-called “Root DNSSEC KSK ceremonies” which are public and broadcasted live:
Usually there are four ceremonies each year. In a typical ceremony, the private root KSK key is used to sign a new set of ZSK keys that are valid for a period of three months. Other operations that may happen during these ceremonies include management of the KSK keys themselves (rollover, generation of new pairs, etc.). Note that such events are not very frequent and are always preceded by very detailed planning. For example the last KSK key rollover happened in 2018 and was followed by years of consultation, design and testing…
The most recent information about the root zone DNSSEC operations (including the current public KSK keys and archived ceremonies live streams) can be found here .
All DNS resolvers that are supposed to validate Internet domains should have the public root KSK key installed. Such a key is called a “trust anchor”. Of course it is possible to explicitly add other trust anchors on a particular resolver, which is especially useful when you use DNSSEC on your internal DNS servers.
Putting all the pieces together
Now that we know the main principles of DNSSEC, we can analyze an example of a real validation process done for the www.infotest.com.pl FQDN (Figure 15). We start from the point where we finished the resolution process depicted in Figure 6.
When a DNSSEC-enabled resolver receives a response requested by the client, it starts the validation process. In such a case, an authoritative server with a signed zone, besides the regular RRset (in our case A-record for the www.infotest.com.pl FQDN), also sends a signature for this RRset in the form of an RRSIG record. Next, our resolver requests for the infotest.com.pl zone’s DNSKEY RRset, containing the ZSK public key. This allows us to verify the correctness of the signed A-RRset. The ZSK key is also verified by the accompanying KSK public key.
Notice how the resolver balances queries between two authoritative servers for the infotest.com.pl zone. The A-record query is sent to ns1 and DNSKEY-record query to ns2.
In the next step, the resolver tries to verify the infotest.com.pl public KSK itself by sending a query for a DS-record to an authoritative server of the parent zone (com.pl). It gets a response together with a signature (RRSIG record). Next, it queries for the DNSKEY RRset containing the ZSK public key of the com.pl. zone, in order to verify the DS record. Here all the queries are also spread across multiple authoritative servers responsible for the com.pl zone.
After performing the validation at the com.pl level, resolver moves up the DNS tree and checks the com.pl DS-record at the pl level. The last stage is verification at the root level. Finally, the root KSK public key is verified by comparing it with a locally installed trust anchor.
As you can see, adding the DNSSEC layer complicates the resolution process even more. Without proper caching, going through that process for every query (obtaining proper records, performing cryptographic calculations), would be very lengthy and burdensome.
In our example, the resolver had its cache cleared out. In total, the whole resolution process took more than 2.5 seconds and required 256 packets to be sent or received.
Proof of non-existence
Sometimes we might ask for a domain name that actually doesn’t exist. In such a case we receive an answer (either directly from an authoritative server or relayed by a recursive resolver) with a response code set to NXDOMAIN (non-existent domain) in the flags section of the DNS header. Such a response is usually accompanied by information about the name servers responsible for the zone with the missing name:
$ dig not-existing-at-all.lol. ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> not-existing-at-all.lol. ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 57136 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: d5b9804cd51bd2989348148b6574521382defd97010e82f6 (good) ;; QUESTION SECTION: ;not-existing-at-all.lol. IN A ;; AUTHORITY SECTION: lol. 825 IN SOA ns0.centralnic.net. hostmaster.centralnic.net. 1702121116 900 1800 6048000 3600 ;; Query time: 5 msec ;; SERVER: 192.168.1.201#53(192.168.1.201) ;; WHEN: Sat Dec 09 12:40:07 CET 2023 ;; MSG SIZE rcvd: 145
Until now we have been discussing validation of specific resource records. It turns out that it would be also a good idea to confirm that NXDOMAIN responses are not tampered with. This is because NXDOMAIN responses are also cached by recursive servers and clients! So, if someone finds a way to fool a resolver and inject information about non-existing domain names, maybe he won’t be able to redirect the traffic to a malicious server, but instead he will deliver a decent DoS attack.
DNSSEC implements a special mechanism to assure that NXDOMAIN responses are legitimate by adding NSEC or NSEC3 records. NSEC works by returning the next existing record (in alphabetic order). For example if we have a zone with A-records for mail, ns and www, and we try to query for test, we will still get the NXDOMAIN response but in the authority section there will be also NSEC record (accompanied by RRSIG signature) with information about the ns name and www. Such information indicates that between those two names there is nothing more.
If we send a query for not-existing-at-all.lol once again, but this time with enabled DNSSEC, we will get the following NSEC record:
not--thi-s-one.lol. 900 IN NSEC not-game.lol. NS RRSIG NSEC
There is one major drawback of using NSEC records. When you start making many queries for random names, at some point you will be able to find all existing names within a specific zone, which is never a desirable thing. This is called “zone walking” or “zone enumeration”. Although this doesn’t pose a direct risk, it simplifies other attacks, e.g. subdomain hijacking. It is easy to imagine that an attacker may in this way find some unused, forgotten CNAME record pointing to an external cloud service. If that external domain (e.g. example-bucket.s3.amazonaws.com) is expired, the attacker can buy it and run his own service. This way a legitimate subdomain owned, e.g. by a bank or government institution, would eventually be pointing to a malicious server.
To overcome this issue, another record type can be used for verifying NXDOMAIN responses – NSEC3, accompanied by NSEC3PARAM. NSEC3 realizes the same concept, but instead of exposing real names, it contains only their hashed values. Of course this comes at additional cost – more cryptographic operations on authoritative servers, and more complicated troubleshooting.
DNSSEC in practice
Now it’s time to see how DNSSEC works (and looks) in reality. All DNS servers running DNSSEC are backward compatible with the legacy DNS. In order to get additional DNSSEC data, we must explicitly request that. To do that we use a special DO flag (DNSSEC OK) in the EDNS0 record (the one which is also used to extend DNS message length). In our example, the client (a Windows machine) is not able to perform DNSSEC validation on its own using a built-in stub resolver, but the external DNS resolver is capable of doing that.
After a successful validation, the resolver responds to a client with the requested information, but also sets the AD (authenticated data) flag (AD=1) within the DNS header. If the AD flag is not set, it means that the response has not been validated.
If a client is not doing the validation on its own, but still is DNSSEC-aware, it may use this flag to decide what to do with non-validated responses (AD=0): either reject them or accept them anyway. On Windows, you can control that behavior in the Name Resolution Policy Table (NRPT), configurable through GPO:
In order to obtain DNSSEC data we can also use DNS tools like “dig”. This can be helpful, especially when performing diagnostics or troubleshooting:
$ dig @8.8.8.8 iana.org. +dnssec +multiline ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> @8.8.8.8 iana.org. +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15879 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 512 ;; QUESTION SECTION: ;iana.org. IN A ;; ANSWER SECTION: iana.org. 2264 IN A 192.0.43.8 iana.org. 2264 IN RRSIG A 8 2 3600 ( 20231216164619 20231126002527 32983 iana.org. LReP0KlciB42w3tCNkk7fo2c2ub3t1XDZhMVAva8/TJC r1FVAKK+keTsw9ZHLsCy7ub2YLPmfAE2WqgAHI7alDdn oMhVMWMxsQPXOdbO9D2B2tsbgRI+25mJBihxIYqtcHOn r3Cght+xXEQPvZH45T5iqrzvETfbXHn06gH5Maw= ) ;; Query time: 13 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: Sat Dec 09 14:33:08 CET 2023
Here we are asking for the iana.org A-record with the DO bit set to 1 (“dnssec” option in dig). We get the requested record and an additional RRSIG-record with a digital signature. Of course we can also ask for any DNSSEC specific records, like DNSKEY:
$ dig @8.8.8.8 iana.org. DNSKEY +dnssec +multiline ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> @8.8.8.8 iana.org. DNSKEY +dnssec +multiline ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21966 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 512 ;; QUESTION SECTION: ;iana.org. IN DNSKEY ;; ANSWER SECTION: iana.org. 3022 IN DNSKEY 256 3 8 ( AwEAAZIdoTei11lq4r89/pGxqSaEN3I8M1g+kdY5W1sr GigsuywlZCnEA0V/cg6R6KFPQzfseYHlHRnLz107G5ly MCKzko1fkq00qJEuttAVYHV/LMe1Z5M3yALROOEseDpA 2IgorZthnLHjL4nb8hceT/W9OpjPz5OzPpR4JCtIIZAB ) ; ZSK; alg = RSASHA256 ; key id = 32983 iana.org. 3022 IN DNSKEY 257 3 8 ( AwEAAa02O9AMbFbTpcDedeuRuUKV82NGBPEJtMbS8TT5 +PwONcMSzsljUMToEogvz7DfNmlKEOj4Z2dm6JY6KEna od4QyI56ZJfssgwlE2r5+jouwcO7KzBHpVHQYsx9+909 k2VAQn8SOQjNVhhYNjVPnLp3R759cXnM1hpn9gNsgehM VoGRETXrLesTGUmrRyyZBgCiY/XJKLQuEm1t5THrgJWM 9WFO/IcaeBVBtkgj8IskOS2aAySGx4jAX5HLHJu6oOc/ L2zjXhXsRgYKN9TMaKnWqez1CeM4Sn/Ay//BFqU= ) ; KSK; alg = RSASHA256 ; key id = 21911 iana.org. 3022 IN DNSKEY 257 3 8 ( AwEAAb0i1jarxjgmjsOAO7IbXvhwe4yBSGWpUnjj9SLZ OguEbOY+6hrsLL5Xa9LKHDjgF/ovovtOj4t9JrKXQZ6c /kJdtaIkGcWzhACoNkum20mn2Ja3Zk1xJgEkMpOED5I3 N6IHNCALSNw8rxu3c3xVDpD6Tf10+Bcpr4sjge32lNeV DjVPs7D7yJSQrr0tBui4rtsMkeQ8jNT9Hna7C/5MRAxq jpueX0Z7kEqv4vevv1Y7xDi7yloRzY/tx8BdYEVRNOQ9 pbU2ERuFhUWmwT1DROUBwpK6husdOGbnPyGzCiHt14An 5wYpj6B4Jao9DuNTgTl6xg20oyR46pRM1roTeIk= ) ; KSK; alg = RSASHA256 ; key id = 39817 iana.org. 3022 IN RRSIG DNSKEY 8 2 3600 ( 20231224093426 20231203004804 21911 iana.org. hB0VKjszoSSMLidAXYbjMd1LbV+fWAUm16SkVxfh/JNr bVy9ZMW5sM17TSBynnbQeqgaRc6nJapNy8oETOGwhrP4 dSBky80W1MdzNb1yBhPiM7YOfD6Pdw5yqdadwfgzaDfp QhEQMTFj96CUnq0BIenMLzpOD3SgOtyzFl4pZnNZ7Y84 1biH7BchswfG4GYtkka0lrM5hmEqDqmGAPeiZ2934vXr HmyQg2h46ya1qUNXZI/zLlCR5/lvPyX/iUGOc8l7TpM5 qh5BdnQFuCdjDkhb2H0v6wG4WbDgLCPClLuoDsxjLrQn XQLu4DF6tnG/56lJzx2MMM7ipm3ntTkMng== ) iana.org. 3022 IN RRSIG DNSKEY 8 2 3600 ( 20231224093426 20231203004804 39817 iana.org. HVCAOuyqtTCzFbjEeE3uAWr7xW2gLlzwLCX7PVuMDVvC bBFjR49TPxeDJ06yHFdY3r9Y7lzlC4ltB7vfSjbtnHep hqhpaqjRP1oWVkbCWscbD0vNO/6CYcyPBkxIurFsOLRw I4f8heb6CW4dfjvSR7d7ZGWPPhgkXYQOwAdjrxgqcyUj fZgh0ZCfh5dQqTf49H1L9jELPLbQwFxlSOUx511JhIxD D9YDTGEPCTU+Fknp5/0siL60nKpmHwdLKKM+9+btvFIU 0k5vSqqUxL+BMnqw25fIMwQR8eGvmD9FSKmdlME5UmtR RtNxkUPKnTQfU4krN7esuy8kKuHKxw3KwA== ) ;; Query time: 10 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: Sun Dec 10 10:33:23 CET 2023 ;; MSG SIZE rcvd: 1329
Numbers marked in red, right after the DNSKEY record type, indicate the key type (256 is for ZSK, 257 is KSK). Here we can see that the iana.org zone holds two KSK keys, which might suggest that the zone is in the middle of the KSK rollover process. Every key has its own unique id and every RRSIG record contains information about the id of the signing key (both marked in blue). We can then easily distinguish which key was used to sign a specific record set. Here the DNSKEY RRset is signed both by the old and the new KSK key. Apart from that, every RRSIG signature has its own inception and expiration time (marked in green). DNSSEC-enabled authoritative servers must constantly renew RRSIG records in order to maintain their validity.
There is also a Windows PowerShell tool called Resolve-DnsName that can read DNSSEC information, however it doesn’t give as many details as the dig tool:
> Resolve-DnsName -name iana.org. -type A -dnssecok Name Type TTL Section IPAddress ---- ---- --- ------- --------- iana.org A 3030 Answer 192.0.43.8 Name : iana.org QueryType : RRSIG TTL : 3030 Section : Answer TypeCovered : A Algorithm : 8 LabelCount : 2 OriginalTtl : 3600 Expiration : 16.12.2023 16:46:19 Signed : 26.11.2023 00:25:27 Signer : iana.org Signature : {45, 23, 143, 208...}
Note that the standard nslookup tool is not DNSSEC-aware.
In case of any problems with the validation, a DNSSEC-enabled resolver won ’t return the requested record, instead it will send a response with an error code:
$ dig @8.8.8.8 www.dnssec-failed.org. ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> @8.8.8.8 www.dnssec-failed.org. ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 31758 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ; OPT=15: 00 09 4e 6f 20 44 4e 53 4b 45 59 20 6d 61 74 63 68 65 73 20 44 53 20 52 52 73 20 6f 66 20 64 6e 73 73 65 63 2d 66 61 69 6c 65 64 2e 6f 72 67 ("..No DNSKEY matches DS RRs of dnssec-failed.org") ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; Query time: 247 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: Sun Dec 10 10:10:57 CET 2023 ;; MSG SIZE rcvd: 101
If we want to disable validation on the upstream DNS resolver, we can set the CD flag (checking disabled), in the header of a query. We should then receive the response with the requested records, regardless of the DNSSEC state:
$ dig @8.8.8.8 www.dnssec-failed.org. +cd ; <<>> DiG 9.11.5-P4-5.1-Debian <<>> @8.8.8.8 www.dnssec-failed.org. +cd ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64088 ;; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;www.dnssec-failed.org. IN A ;; ANSWER SECTION: www.dnssec-failed.org. 7200 IN A 69.252.193.191 www.dnssec-failed.org. 7200 IN A 68.87.109.242 ;; Query time: 199 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: Sun Dec 10 10:15:42 CET 2023 ;; MSG SIZE rcvd: 82
As you can see from the examples presented in this article, the DNSSEC resolution process might be quite complicated, and so is the troubleshooting process. Fortunately, there are publicly available tools that can help DNS administrators to verify if the chain of trust is correctly set for their domains, or where the problem is located in case of any issues:
- DNSSEC Analyze : verifies the chain of trust and presents results in an easy to read tabular format:
- DNSViz – provides a visual analysis of the DNSSEC authentication chain for a specified domain, its resolution path in the DNS namespace, and lists configuration errors detected during the resolution process:
DNSSEC adoption
Although DNSSEC has been around since 2005 and provides a significant security improvement to the legacy DNS protocol, its overall adoption on the Internet is still quite low.
According to Verisign , at the end of 2023, the most popular top-level domain (TLD) – com (48% of all domains), contained around 7M signed domains. For the fourth most popular domain - net (3%) this number was 10 times smaller. But when we look at the percentage of signed domains, we will see that in both cases only around 5% of net or com domains are actually signed:
However, when compared to other TLDs, com still holds first place when it comes to the number of DNSSEC signed zones:
DNSSEC usage is not always so low for other domains. There are some honorable exceptions. As you can see in the graph above, the TLD with the second largest number of signed domains is nl (The Netherlands). One of the reasons is that more than 60% of all nl zones are signed using DNSSEC .
The graph below shows the European ccTLDs (country code TLDs) with the best adoption rates, as of August 2022 .
As you can see, DNSSEC usage varies a lot between particular TLDs. In many cases the adoption rate is highly dependent on the local authorities and their standards, the active role of the TLD registrars and the number of local providers with their respective policies.
It is worth noting that there are still some not-signed ccTLDs around the world (mostly in Africa), which means that it is also not possible to sign their subdomains.
The other side of DNSSEC adoption is the actual validation of signed domains. In this case the situation may also vary depending on a country. In the figure below we can see that there are some countries where the overall validation rate is almost 100% (e.g. Finland). On the other side of the scale we have countries like China with an almost 0% rate.
Note that popular public DNS resolvers in most cases support DNSSEC validation (including Google 8.8.8.8 and Cloudflare 1.1.1.1).
Over the last few years, other name resolution protocols emerged. They provide not only integrity and origin verification but also data encryption: DoT (DNS over TLS), DoH (DNS over HTTPS) or the latest one – DoQ (DNS over QUIC). The DoH protocol has recently been brought to wider attention following Google and Mozilla’s announcements to make this name resolution method the default in their browsers. Current Chrome versions have this feature enabled by default for computers not managed by any organization. Firefox has deployed it for several countries so far . The rapid growth of alternative name resolution methods will probably have a significant impact on further DNSSEC adoption in the near future.
Key takeaways
- DNSSEC provides data integrity and origin verification by creating cryptographic signatures of specific DNS records. Similar to TLS/SSL, it uses public key cryptography to verify and authenticate data. It is not used to encrypt DNS messages themselves. They are still exchanged in clear text.
- DNSSEC extends the current DNS implementation by adding new DNS record types (RRSIG, DNSKEY, NSEC, etc.) that facilitate DNS data validation.
- Domains in a particular branch of the DNS namespace form a chain of trust. It means that to properly verify data in one domain we must also rely on information provided by the parent domain.
- To properly perform DNSSEC validation, the resolver needs to install a trust anchor – a public key that allows verification of all domains down the trust chain. IANA manages the DNSSEC keys used in the root DNS domain.
- DNSSEC usage is not equal in different parts of the world and is highly dependent on local standards and policies. The most popular public DNS resolvers already validate DNS communication using DNSSEC.