Last Updated: 2021-03-01 13:37:50 UTC
by Rob VandenBrink (Version: 1)
Going back a few weeks, we discussed how DNS over HTTPS (DoH) works (https://isc.sans.edu/forums/diary/Fun+with+NMAP+NSE+Scripts+and+DOH+DNS+over+HTTPS/27026/) - very much as an unauthenticated API over HTTPS. But DNS over TLS (DoT) has been with us for a fair bit longer (May 2016), why haven't we heard about it so much?
After wrestling with it for a bit, I can tell you why!
DoH is easy to work with, since we have so many HTTPS tools at our disposal. Plus DoH was first implemented in browsers, and the browser developers *live* in HTTPS, so DoH is a cake-walk for them. DNSSEC is basically plain old unencrypted DNS, but with signature records.
DoT on the other hand is a whole 'nother beast. It's still basic DNS, but encapsulated in TLS. So to make DoT calls we need a toolset to create TLS packets, then send and validate them using the certificate at the server side. So the first tool that came to my mind of course was scapy, but read on, I used an easier method ..
To allow all of the mentioned DNS protocols to live on one server, DoT lives on tcp/853. This makes for an easy NMAP scan if you're looking for this service. NMAP tags the port correctly, but an NMAP version scan (-sV) won't identify the DoT service. It will however find some critical strings in the fingerprint, things like "DNSVersionBindReqTCP" and "DNSStatusRequestTCP" - so a version scan will validate the service enough for your eyes to see it, without calling it out definitively. You can also of course validate the certificate on port tcp/853 using NMAP's ssl-cert.nse script or openssl:
nmap -p853 --script ssl-cert 18.104.22.168
Starting Nmap 7.80 ( https://nmap.org ) at 2021-03-01 07:55 Eastern Standard Time
Nmap scan report for 22.214.171.124
Host is up (0.012s latency).
PORT STATE SERVICE
853/tcp open domain-s
| ssl-cert: Subject: commonName=dns.google/organizationName=Google LLC/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:dns.google, DNS:*.dns.google.com, DNS:8888.google, DNS:dns.google.com, DNS:dns64.dns.google, IP Address:2001:4860:4860:0:0:0:0:64, IP Address:2001:4860:4860:0:0:0:0:6464, IP Address:2001:4860:4860:0:0:0:0:8844, IP Address:2001:4860:4860:0:0:0:0:8888, IP Address:126.96.36.199, IP Address:188.8.131.52
| Issuer: commonName=GTS CA 1O1/organizationName=Google Trust Services/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2021-01-26T08:54:07
| Not valid after: 2021-04-20T08:54:06
| MD5: 9edd 82e5 5661 89c0 13a5 cced e040 c76d
|_SHA-1: 2e80 c54b 0c55 f8ad 3d61 f9ae af43 e70c 1e67 fafd
Nmap done: 1 IP address (1 host up) scanned in 24.43 seconds
Me, I took the easy way out for DoT queries and installed the knot-dnsutils (sudo apt-get install knot-dnsutils), which installs kdig to do all the heavy lifting for me. As the name implies, kdig does just about everything that dig does, but for this task gives you parameters to make DoT queries.
So an A record query over DoT from kdig looks just very much like DOS query outpuyt from dig:
$ kdig @dns.google.com +tls-ca isc.sans.edu A
;; TLS session (TLS1.3)-(ECDHE-X25519)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 57540
;; Flags: qr rd ra; QUERY: 1; ANSWER: 2; AUTHORITY: 0; ADDITIONAL: 1
;; EDNS PSEUDOSECTION:
;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR
;; PADDING: 391 B
;; QUESTION SECTION:
;; isc.sans.edu. IN A
;; ANSWER SECTION:
isc.sans.edu. 4 IN A 184.108.40.206
isc.sans.edu. 4 IN A 220.127.116.11
;; Received 468 B
;; Time 2021-03-01 04:58:51 PST
;; From 18.104.22.168@853(TCP) in 38.9 ms
Note all the TLS session info at the top, and the port number in the last line.
As you'd expect, if you're just after answers you can use the +short parameter:
# kdig @dns.google.com +tls-ca +short www.coherentsecurity.com AAAA
.. yup, I host my website on github, handiest github feature ever (ok, maybe not the handiest, but still pretty darned handy)
Other handy parameters in kdig?
- Just as in dig, you can always tack on the "-d" parameter for debug output
- +tls-hostname can be used to over-ride the server name during TLS negotiation. This means you can even use the server's IP address when you use this parameter.
- Related to tls-hostname, +tls-sni adds the Server Name Indication field to the request
Without constructing the TLS packet, how can I use DoT in an NMAP script? I again took the easy way out and used kdig, in combination with the lua command os.execute. Yup, in the time honoured tradition of coding laziness I shelled out and executed the matching OS command! In the DoH script I wrote I did a quick check to make sure that the host was running HTTP services on port 443 with "shortport.http". In the DoT script I changed this, to ensure that TLS is running on the scanned port, using the "shortport.ssl" check. An example scan is shown below:
$ nmap -p853 --script dns-dot.nse 22.214.171.124 --script-args target=www.cisco.com,query=AAAA
Starting Nmap 7.80 ( https://nmap.org ) at 2021-03-01 05:13 PST
Nmap scan report for dns.google (126.96.36.199)
Host is up (0.017s latency).
PORT STATE SERVICE
853/tcp open domain-s
Nmap done: 1 IP address (1 host up) scanned in 0.40 seconds
You can find the DoT script here: https://github.com/robvandenbrink/dns-dot . Because is calls kdig, you'll need the knot-dnsutils package installed before this script will run. If you're interested in combining NMAP scans with different OS commands you're welcome to review the source code and use whatever you need!
Do you have a handy nmap script that uses os.execute to do the "behind the scenes" work? Please, share a link in our comment form!
DoT RFD: https://tools.ietf.org/html/rfc7858
Usage Profiles for DNS over TLS and DNS over DTLS: https://tools.ietf.org/html/rfc8310