-
Notifications
You must be signed in to change notification settings - Fork 126
Home
A common question is "Why usezdns
over dig
or nslookup
?" For one-off queries, these tools or the DNS lookup functionality in your language of choice are more than sufficient.
However, zdns
is designed to efficiently handle large numbers of DNS queries in parallel as well as support more complex DNS queries like --all-nameservers
that aren't supported with dig
.
Several features to improve the performance of large volumes of DNS queries are:
- Shared Cache - each thread shares an LRU cache to store the most common domain name -> IP mappings. This greatly speeds up iterative lookups.
- UDP socket re-use -
dig
and friends will open new socket for each query. ZDNS re-uses the same socket for multiple queries, reducing overhead. - Efficient Multi-threading + Parallelism - ZDNS is designed to be multi-threaded by default leveraging light-weight goroutines.
You'll need to have the following installed in order to install ZDNS
Both of these should return the version if they're properly installed
git --version
go version
git clone https://github.com/zmap/zdns.git
cd zdns
make install
zdns --version
Starting off, you can use ZDNS similar to dig
.
If you want to query the A
record for google.com
from Cloudflare's recursive resolver, 1.1.1.1
.
zdns A google.com --name-servers=1.1.1.1
$ zdns A google.com --name-servers=1.1.1.1
{"name":"google.com","results":{"A":{"data":{"additionals":[{"flags":"","type":"EDNS0","udpsize":1232,"version":0}],"answers":[{"answer":"142.250.189.174","class":"IN","name":"google.com","ttl":173,"type":"A"}],"protocol":"udp","resolver":"1.1.1.1:53"},"duration":0.003042781,"status":"NOERROR","timestamp":"2024-12-26T17:06:31Z"}}}
00h:00m:00s; Scan Complete; 1 names scanned; 293.19 names/sec; 100.0% success rate; NOERROR: 1
Without specifying --name-servers
, ZDNS will read /etc/resolv.conf
to get your OS's default external resolvers. You can see in the below that this host had 127.0.0.53:53
configured as the local resolver (denoted with "resolver": "127.0.0.53:53"
).
$ zdns A google.com
00h:00m:00s; Scan Complete; 1 names scanned; 746.57 names/sec; 100.0% success rate; NOERROR: 1
{"name":"google.com","results":{"A":{"data":{"additionals":[{"flags":"","type":"EDNS0","udpsize":65494,"version":0}],"answers":[{"answer":"142.250.189.206","class":"IN","name":"google.com","ttl":145,"type":"A"}],"protocol":"udp","resolver":"127.0.0.53:53"},"duration":0.001102308,"status":"NOERROR","timestamp":"2024-12-26T17:10:08Z"}}}
Output is streamed to stdout
by default, so you can pipe into jq
for prettier output. You'll notice that the per-second status updates are not processed by jq
, those and any logs are sent to stderr
by default.
$ zdns A google.com | jq
00h:00m:00s; Scan Complete; 1 names scanned; 54.55 names/sec; 100.0% success rate; NOERROR: 1
{
"name": "google.com",
"results": {
"A": {
"data": {
"additionals": [
{
"flags": "",
"type": "EDNS0",
"udpsize": 65494,
"version": 0
}
],
"answers": [
{
"answer": "142.250.189.206",
"class": "IN",
"name": "google.com",
"ttl": 300,
"type": "A"
}
],
"protocol": "udp",
"resolver": "127.0.0.53:53"
},
"duration": 0.017919065,
"status": "NOERROR",
"timestamp": "2024-12-26T17:13:26Z"
}
}
}