How to use dig

How to use dig


·December 4, 2021


It's worth noting that dig (and host) bypass the normal DNS resolution mechanism used by most programs on the host. i.e. These tools aren't using getaddrinfo/gethostbyname.

Sometimes, I want to see the results from getaddrinfo, which are impacted by caching on the host itself and/or OS-specific configuration settings that dig and host know nothing about. (scutil --dns on macOS, systemd-resolvedand nscd on Linux, etc.)

In that case, I usually use ping. e.g., waiting for a DNS change to propagate to a host, I might use:

    while :; do ping -c 1 hostname; sleep 1; done


You can directly query `getaddrinfo` with

  getent ahosts myhost


Thanks for this. I’ve always wanted to know how to replicate how the OS is resolving.


The OS X equivalent is: dscacheutil -q host -a name MYHOST


This has confused me before when trying to lookup mDNS/avahi/.local names. You can't use dig, host etc. to look them up because the answer doesn't come from a DNS server, but you can ping them.


If you have a particularly bad ISP or are on a controlled network, dig might not use the specified DNS server because the network is intercepting outgoing DNS traffic.

Edit: It's not necessarily something to be worried about, just that "strange results" may occur if unaware. E.g. "why and how does resolve a domain-local host?"


If you’re concerned about network interception and lack the ability to have a trusted ISP, then WireGuard your connection to a trusted endpoint (you should probably route everything over it). Normally you’d want your devices to use your pi hope so you can block malicious traffic (adverts, trackers etc) from all your devices.


That's not really a dig problem.


Dig is great and DNS is hella underrated. It seems like not nearly enough folks know how to wield it. At both $lastco and $thisco people just used a mess of configuration to point to service IPs/URIs. I showed them how to set private zones and records for both A and SRV and suddenly everything is just using sane defaults.

Side note: does anyone know why dig's output is so...eye-bleeding? Why does it show so much info by default? +short should be the default. Why the ;; "comment" prefix?


I always assumed its output was supposed to resemble a zone file.


Ahhh yup, that makes perfect sense given how zone files are formatted.

But that moves the question. Why do zone files use ; as comment? Some old assembly dialect? I've not worked much with assembly but it's always been # or //


The original DNS implementation (called JEEVES) was written by Paul Mockapetris to run on the PDP-10, which is why the zone file syntax is not very unixy. The ; comments are one example: and backslash escapes are decimal rather than octal, line continuation uses () instead of escaping.


> @jpmens @svnr2000 ; was chosen as a comment in zone files because that's what the PDP10 and other macro assemblers used in those days.





; is quite common in assembly as the comment marker. And zone files are old, so the // or # were not as standard as they are today.


Maybe the original creator was an Emacs fan? Lisp also uses semicolons for comments.


A blog post of what you describe would be greatly appreciated, i’ll probably learn a thing or two from it.


Great idea, I'll take a stab at it!


I never really got why people use `dig`. Its interface and output is awkward, and it seems all of its functionality can be more easily performed with `host`, which doesn't feel the need to print stuff like:

; <<>> DiG 9.16.20 <<>> -r ;; global options: +cmd ;; Got answer:

just try `host` or `host -t ns` -- it's the output you'd expect without all the verbosity.


Dig gives more information, such as TTL and the resolving server. If you also want that information from host, you need to use the `-v` flag, at which point the output is almost as verbose as that from dig.


I have the reverse opinion. Why do people keep insisting on using host, when dig does the same (if not more) and while being so easy to use.

Most of my co-worker prefer host, but continue to be supprised when I use dig and features like reverse lookup or dig @some-dns-server. I’m sure that host can do the same, but few seems to know how.


The comment you're replying to has an example of using a specific DNS server.

As for reverse lookups, it's as simple as host <ip-address>


Dig is/was part of bind - and I believe it output is conformant with textual representation from the rfc(s):


host is also part of BIND:

    # rpm -q -f `which host`


Sure, but they are different tools:

> host is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. When no arguments or options are given, host prints a short summary of its command-line arguments and options.

> dig is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. Most DNS administrators use dig to troubleshoot DNS problems because of its flexibility, ease of use, and clarity of output. Other lookup tools tend to have less functionality than dig.



> all of its functionality can be more easily performed with `host`

I've seen far too many junior admins accidentally change the hostname of a server when checking a DNS record...

Dig is verbose by default, which is usually what I want. It can be made as terse as host with the +short option. host -vt SOA is more typing than dig SOA. Neither dig or host is very good for use by other programs.


> I've seen far too many junior admins accidentally change the hostname of a server when checking a DNS record...

Why are they using a root shell for tasks that don't require it in the first place?


dig allows you to control things like retries and timeouts, choice of udp or tcp, choice of opcode (if you want to synthesise a NOTIFY message, say); it shows you the flags and the authority section so you can debug referrals, and the various EDNS options in case those matter.

If you just want the answer then `host` is just fine - I use both of them a lot - but `dig` really shines when you need to get into the guts of the DNS.


What I've noticed is that people like the name of "dig". It has some advantages though (not described in this tutorial) like tracing and setting the DNS TTL but those are really edge cases. Host is indeed much more convenient!


If you want dig to be less verbose add +short

It’s mostly just habit mixed with the difference in inconvenience being quite small

Also doesn’t host use the local nss stack while dig exclusively queries dns?


Well, today I learned of `host`. Thanks !


> By the way: if you’ve ever wondered what IN means, it’s the “query class” and stands for “internet”. It’s basically just a relic from the 80s and 90s when there were other networks competing with the internet like “chaosnet”.

Reading things like this makes me feel better about the relics in my code that aren't really hurting anything but would take work to remove.


Related, CNAME is used casually in the opposite sense to it's expansion, "canonical name".

Also, in a hundred years there'll be people making up retronyms for .arpa.

  "Uhm maybe it stands for *address reverse protocol association*?"


> Also, in a hundred years there'll be people making up retronyms for .arpa.

We've already got one! It's been backronymed as "Address and Routing Parameter Area" by IANA[1].



dig supports doh natively, now.

    dig +https MX


Quite like using dog too


> dog is a command-line DNS client, like dig. It has colourful output, understands normal command-line argument syntax, supports the DNS-over-TLS and DNS-over-HTTPS protocols, and can emit JSON.

I especially like that last part.


You can also convert dig output to JSON with jc. (I’m the author)

$ jc dig | jq -r '.[].answer[].data'


dog is great. You can build a static Rust binary leveraging rustls with:

  cargo build --release --verbose --target x86_64-unknown-linux-musl --no-default-features --features=with_idna,with_tls,with_https,with_rustls

  alias dog "dog --edns=show --https --nameserver"


Missed an opportunity to call it dug [1]. Well, maybe not “missed.”



I wish the DNS RFC had included a MUST support for ANY requests on the server side, and wildcard domain support (e.g. ANY for label *.domain.tld).

That would have made life so much easier. The state now is that clients cannot even rely on multiple request questions to be answered correctly...and is the reason why every Browser sends out separate DNS questions for A and AAAA and TXT etc.

All the overhead for parsing message compression is also kinda useless when you have only one record with the same labels answered all the time.


QTYPE=ANY has very tricky interaction with caches. The standard semantics are that ANY means whatever the server has, not all the types at the qname. So, if you have a mixture of v4-only and dual stack clients, you can’t predict whether the cache will have just A or both A and AAAA, so ANY will be worse than just making both queries concurrently.

And because ANY interacts badly with UDP fragmentation and certain backend database design, and because it has been abused for DDoS attacks, it is increasingly common for it to return a subset of the records that the server has.

So I am afraid there is no realistic way to make ANY mean ALL.

Multiple questions don’t work because DNS packets only have one RCODE so there is no way to signal a mixture of success and failure. I don’t know why the DNS message format has a QDCOUNT field for multiple questions.

Yeah DNS compression is problematic in many ways, but in many cases it allows the answer name(s) to be represented by 0x000C. In another context, the domain looks unnecessarily verbose but having all the servers in the same domain makes good use of compression.


Multiple questions inside the same packet are quite common in DNS-SD based multicast queries.

The idea there is to save DNS packets so that you only ask for a pointer (PTR) to a service identifier and get as a response all information that you need (address via A/AAAA, hostname and port via SRV, API version and necessary parameters via TXT etc).

My point was exactly about the QDCOUNT field because its intent clearly was to be able to save unnecessary packets, but in practice, nobody uses it and wastes a lot of bandwidth. Note that technically, servers have to support TCP via port 53, too...but they never actually do :)

As a sidenote: 0x0c is only appearing because it's the start of the label identifier of the first question. This can be a byte pointer to anything, and, if labels of records are crafted maliciously, even lead to an infinite loop or buffer overflow on clients/resolvers with naive implementations (see NAMEWRECK vulnerability [1]).

Regarding the ANY problem and why it's disabled: I think this is the wrong point in the architecture to fix DDoS or amplification attacks and the abuse of a public resolver. ISPs or ASNs could simply block UDP traffic which has a different source/target network. That alone would reduce most of the DDoS traffic and probably fix most of the abuse.

I mean, at some point you have to wonder: What happens when hackers start to use TXT queries to DDoS a target because their buffer size is larger, too? Just disable TXT? I hope you understand my point.

A DNS server could also always block via a throttling mechanism or increase the TTL to limit the bandwidth to a specific target, additionally to the comparison of source/target addresses. If someone with a different origin keeps requesting DNS queries, you can likely assume that it's an amplification attack...there are literally dozens of ways to fix this in a better way than disabling ANY completely.



> Multiple questions inside the same packet are quite common in DNS-SD based multicast queries.

mDNS is DNS in name only. Yes the wire format is mostly the same but the semantics are not.

> Note that technically, servers have to support TCP via port 53, too...but they never actually do :)

No? I haven't come across a widely used server implementation that doesn't support TCP in a very long time. What server software are you referring to?

> ...there are literally dozens of ways to fix this in a better way than disabling ANY completely.

As fanf2 said, ANY isn't ALL, and so it doesn't do what most people would want it to do anyway.


Sounds similar to AXFR queries, which it is best practice to disable. It's not advisable in general to provide information about hosts that the querier didn't request specifically and individually.

"A remote unauthenticated user may observe internal network structure, learning information useful for other directed attacks."


Those requests are most often used in combination with spoofed packets to DDoS others. Many of us block those requests.


Nice article, I wish everyone, especially my devops guys, would learn to use dig. It's a lifesaver.

On tracing

> So it’ll make about 20 DNS queries

Not sure about this part. Most domains will hit root, tld, x.tlds nameservers, and maybe one more. Most traces should only be 3 to 5 queries.


Maybe she just edited it, but actually it's 30 DNS queries. 26 of them are to the 13 root nameservers.

> So it’ll make about 30 DNS queries. (I checked using tcpdump, it seems to make 2 queries to get A/AAAA records for each of the root nameservers so that’s already 26 queries. I’m not really sure why it does this because it should already have those IPs hardcoded, but it does.)


Interesting! Just tested and saw the same. I had no idea it did that, and to be honest, also have no idea why it does. Thanks for the update.


Comparable PowerShell Resolve-DnsName commands, though it's not overall as capable:

Basic lookup against specific DNS server:

    # dig @

    PS C:\> Resolve-DnsName -Server -Name

    Name                                           Type   TTL   Section    IPAddress
    ----                                           ----   ---   -------    ---------                                        AAAA   300   Answer     2606:4700:3031::ac43:b35a                                        AAAA   300   Answer     2606:4700:3033::6815:5bce                                        A      300   Answer                                        A      300   Answer
Lookup NS type only:

    # dig ns

    PS C:\> Resolve-DnsName -Name -Type NS

    Name                           Type   TTL   Section    NameHost
    ----                           ----   ---   -------    --------                        NS     20944 Answer                        NS     20944 Answer


    PS C:\> Resolve-DnsName NS
Reverse lookup:

    # dig -x
    PS C:\> Resolve-DnsName -Server -Name
    Name                           Type   TTL   Section    NameHost
    ----                           ----   ---   -------    --------    PTR    21600 Answer
Reverse lookup using PTR type (it will tab-complete through the available -Type options):

    PS C:\> Resolve-DnsName -server -Name -Type PTR
    Name                           Type   TTL   Section    NameHost
    ----                           ----   ---   -------    --------    PTR    21131 Answer
The output isn't actually a text table, it's an array of objects, so it's easy to filter and extract data without text parsing:

    PS C:\> resolve-dnsname ns |% namehost
There's also `-TCPOnly`, `-NoRecursion`, `-NoHostsFile` and other options.

NB. you can get BIND for Windows, and therefore dig.exe for Windows, at


Not related to the post, but the owner of this blog also makes small CS zines that act as cheat sheets for common tools: . They're small and cute and make good tech stocking stuffers.


dog is a nice modern take on dig


Is there a simple way to list all A, CNAME, TXT etc. records for all subdomains of a domain from the terminal? Like what you would see in the web interface for your domain registrar? There's lots of free and simple web services that do this to check if your DNS settings have propagated worldwide. I usually just use one of those because DNS changes and checks aren't something I do often enough to remember the terminal commands for.


Some resolvers will respond to the ANY type query, e.g., dig any …. This may not work with your default name server though, so look up some different servers to test. It’s common to disable this feature due to avoid it being abused as an amplifier for DDoS attacks (spoof a small query, get a large response sent to victim).


This is called zone transfer and is generally not enabled for obvious reasons.

The protocol to look for is IXFR and I’m pretty sure dig does it.


Apparently not obvious, or they wouldn't be asking.

DNS is public data, what harm can come from asking for all of it? It doesn't leak any secrets, it doesn't take a lot of bandwidth or server load, it doesn't give you any power to imitate the domain, and it's nothing you couldn't find by brute-force eventually.

It might speed up some recon "what does this company have?" but DNS caches the world over will know what the company has as soon as users reference it. For all anyone knows they could be malicious DNS caches selling the information behind the scenes. Don't put secrets in public DNS records.


Dynamic responses make transfers difficult to implement in some server architectures. Which is not to take away from your point - trying to hide things in the DNS is a fairly pointless exercise.


Good security practices dictate that you don't reveal any information that you don't have to.


IXFR is for incremental transfers in which the client asks for a series of diffs between a particular serial and the current one. AXFR requests a transfer of the full zone. dig supports supports both.