I have used nslookup for years to access information in the Domain Name Systems (DNS), and was sad to see that it was moved to the “deprecated” state when dig (domain information groper) was released. Since I knew nslookup(1m) inside and out, I put off learning about dig, and instead focused on learning other interesting technologies. I recently wanted to add TSIG support to a DNS server, and needed to be able to test signing keys. I didn’t see support in nslookup, so I decided to sit down and learn everything there was to know about dig.
To get started with dig, you can execute dig with the “-h” (help) option:
$ dig -h
Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}
{global-d-opt} host [@local-server] {local-d-opt}
[ host [@local-server] {local-d-opt} [...]]
Where: domain are in the Domain Name System
q-class is one of (in,hs,ch,...) [default: in]
q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]
(Use ixfr=version for type ixfr)
q-opt is one of:
-x dot-notation (shortcut for in-addr lookups)
(nibble form for reverse IPv6 lookups)-f filename (batch mode)
-b address (bind to source address)
-p port (specify port number)
-t type (specify query type)
-c class (specify query class)
-k keyfile (specify tsig key file)
-y name:key (specify named base64 tsig key)
d-opt is of the form +keyword[=value], where keyword is:
+[no]vc (TCP mode)
+[no]tcp (TCP mode, alternate syntax)
+time=### (Set query timeout) [5]
+tries=### (Set number of UDP attempts) [3]
+domain=### (Set default domainname)
+bufsize=### (Set EDNS0 Max UDP packet size)
+ndots=### (Set NDOTS value)
+[no]search (Set whether to use searchlist)
+[no]defname (Ditto)
+[no]recursive (Recursive mode)
+[no]ignore (Don't revert to TCP for TC responses.)
+[no]fail (Don't try next server on SERVFAIL)
+[no]besteffort (Try to parse even illegal messages)
+[no]aaonly (Set AA flag in query)
+[no]adflag (Set AD flag in query)
+[no]cdflag (Set CD flag in query)
+[no]cmd (Control display of command line)
+[no]comments (Control display of comment lines)
+[no]question (Control display of question)
+[no]answer (Control display of answer)
+[no]authority (Control display of authority)
+[no]additional (Control display of additional)
+[no]stats (Control display of statistics)
+[no]short (Disable everything except short
form of answer)
+[no]all (Set or clear all display flags)
+[no]qr (Print question before sending)
+[no]nssearch (Search all authoritative nameservers)
+[no]identify (ID responders in short answers)
+[no]trace (Trace delegation down from root)
+[no]dnssec (Request DNSSEC records)
+[no]multiline (Print records in an expanded format)
global d-opts and servers (before host name) affect all queries.
local d-opts and servers (after host name) affect only that lookup.
This will print all of the availble options along with a short description of the option. When used to lookup information in DNS, dig takes the following form:
$ dig [@name server to use] [domain] [record-type]
“@server” represents the DNS server to query, “domain” represents the domain entry to query (e.g., www.daemons.net), and “record-type” indicates the type of record to retrieve. To lookup the A record for the host www.daemons.net, dig can be executed with the domain entry to resolve:
$ dig www.daemons.net
; <<>> DiG 9.2.2 <<>> www.daemons.net
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19436
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
;; QUESTION SECTION:
;www.daemons.net. IN A
;; ANSWER SECTION:
www.daemons.net. 16140 IN A 66.148.84.65
;; AUTHORITY SECTION:
daemons.net. 28078 IN NS olympus.daemons.net.
daemons.net. 28078 IN NS elysium.daemons.net.
;; ADDITIONAL SECTION:
elysium.daemons.net. 121832 IN A 206.222.17.178
olympus.daemons.net. 35432 IN A 66.148.71.8
;; Query time: 22 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Oct 20 16:12:51 2005
;; MSG SIZE rcvd: 125
This will cause dig to retrive the A record (the default record type) from one of the servers defined in the local name server repository (e.g., /etc/resolv.conf). If you would like to specify the DNS server to query, the server name can be appended to the “@” symbol and passed as an argument to dig:
$ dig @192.168.1.1 www.daemons.net A
; <<>> DiG 9.2.2 <<>> @192.168.1.1 www.daemons.net A
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35663
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2
;; QUESTION SECTION:
;www.daemons.net. IN A
;; ANSWER SECTION:
www.daemons.net. 15949 IN A 66.148.84.65
;; AUTHORITY SECTION:
daemons.net. 27887 IN NS olympus.daemons.net.
daemons.net. 27887 IN NS elysium.daemons.net.
;; ADDITIONAL SECTION:
elysium.daemons.net. 121641 IN A 206.222.17.178
olympus.daemons.net. 35241 IN A 66.148.71.8
;; Query time: 11 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Oct 20 16:16:03 2005
;; MSG SIZE rcvd: 125
As with nslookup, dig can be used to retrieve all of the standard record types (e.g., A, MX, SOA, NS, etc.). The following example show how to retrieve the MX (mail exchangers) records for the domain daemons.net:
$ dig @192.168.1.1 daemons.net MX
; <<>> DiG 9.2.2 <<>> @192.168.1.1 daemons.net MX
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 4
;; QUESTION SECTION:
;daemons.net. IN MX
;; ANSWER SECTION:
daemons.net. 84867 IN MX 20 deimos.daemons.net.
daemons.net. 84867 IN MX 10 phobos.daemons.net.
;; AUTHORITY SECTION:
daemons.net. 27791 IN NS elysium.daemons.net.
daemons.net. 27791 IN NS olympus.daemons.net.
;; ADDITIONAL SECTION:
phobos.daemons.net. 2029 IN A 206.222.17.179
deimos.daemons.net. 84867 IN A 66.148.71.29
elysium.daemons.net. 121545 IN A 206.222.17.178
olympus.daemons.net. 35145 IN A 66.148.71.8
;; Query time: 23 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Oct 20 16:17:38 2005
;; MSG SIZE rcvd: 183
dig also supports numerous options to control which pieces of the query and response are displayed. To view just the result of a query (e.g., just an IP or FQDN), dig’s “+short” option can be used to disable all extraneous output (perfect for shell scripts):
$ dig +short @192.168.1.1 www.daemons.net a
66.148.84.65
If you need to resolve IP addresses to hostname, you are in luck! dig provides the “-x” option to retrieve the PTR record for in-addr.arpa entries, and performs all the translations for you:
$ dig @192.168.1.1 -x 206.222.17.178
; <<>> DiG 9.2.2 <<>> @192.168.1.1 -x 206.222.17.178
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36325
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 2
;; QUESTION SECTION:
;178.17.222.206.in-addr.arpa. IN PTR
;; ANSWER SECTION:
178.17.222.206.in-addr.arpa. 86389 IN PTR elysium.daemons.net.
;; AUTHORITY SECTION:
17.222.206.in-addr.arpa. 86389 IN NS dns3.ee.net.
17.222.206.in-addr.arpa. 86389 IN NS dns1.ee.net.
17.222.206.in-addr.arpa. 86389 IN NS dns2.ee.net.
;; ADDITIONAL SECTION:
dns2.ee.net. 172789 IN A 206.222.1.2
dns3.ee.net. 172789 IN A 206.222.1.3
;; Query time: 20 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Thu Oct 20 20:18:46 2005
;; MSG SIZE rcvd: 170
Dig can also perform zone file transfers with the AXFR protocol:
$ dig @66.148.71.8 daemons.net AXFR
;; Connection to 66.148.71.8#53(66.148.71.8) for daemons.net failed:
connection refused.
The daemons.net DNS adminstrator is limiting zone transfers to pre-defined IP address, so unfortunately the transfer did not complete succesfully. If zone transfers were supported, the AXFR would retrieve the zone file for the domain daemons.net. If you are having problems with DNS reslution, dig provides numerous options to help troubleshoot problems. The “trace” option can be super useful for tracing a query through the entire hierarchical DNS system:
$ dig +trace @192.168.1.1 www.daemons.net a
; <<>> DiG 9.2.2 <<>> +trace @192.168.1.1 www.daemons.net a
;; global options: printcmd
. 518210 IN NS L.ROOT-SERVERS.NET.
. 518210 IN NS M.ROOT-SERVERS.NET.
. 518210 IN NS A.ROOT-SERVERS.NET.
. 518210 IN NS B.ROOT-SERVERS.NET.
. 518210 IN NS C.ROOT-SERVERS.NET.
. 518210 IN NS D.ROOT-SERVERS.NET.
. 518210 IN NS E.ROOT-SERVERS.NET.
. 518210 IN NS F.ROOT-SERVERS.NET.
. 518210 IN NS G.ROOT-SERVERS.NET.
. 518210 IN NS H.ROOT-SERVERS.NET.
. 518210 IN NS I.ROOT-SERVERS.NET.
. 518210 IN NS J.ROOT-SERVERS.NET.
. 518210 IN NS K.ROOT-SERVERS.NET.
;; Received 340 bytes from 192.168.1.1#53(192.168.1.1) in 22 ms
net. 172800 IN NS A.GTLD-SERVERS.net.
net. 172800 IN NS G.GTLD-SERVERS.net.
net. 172800 IN NS H.GTLD-SERVERS.net.
net. 172800 IN NS C.GTLD-SERVERS.net.
net. 172800 IN NS I.GTLD-SERVERS.net.
net. 172800 IN NS B.GTLD-SERVERS.net.
net. 172800 IN NS D.GTLD-SERVERS.net.
net. 172800 IN NS L.GTLD-SERVERS.net.
net. 172800 IN NS F.GTLD-SERVERS.net.
net. 172800 IN NS J.GTLD-SERVERS.net.
net. 172800 IN NS K.GTLD-SERVERS.net.
net. 172800 IN NS E.GTLD-SERVERS.net.
net. 172800 IN NS M.GTLD-SERVERS.net.
;; Received 502 bytes from 198.32.64.12#53(L.ROOT-SERVERS.NET) in 81 ms
daemons.net. 172800 IN NS elysium.daemons.net.
daemons.net. 172800 IN NS olympus.daemons.net.
;; Received 109 bytes from 192.5.6.30#53(A.GTLD-SERVERS.net) in 39 ms
www.daemons.net. 86400 IN A 66.148.84.65
daemons.net. 86400 IN NS olympus.daemons.net.
daemons.net. 86400 IN NS elysium.daemons.net.
;; Received 125 bytes from 206.222.17.178#53(elysium.daemons.net) in 46 ms
The output shows that the first query requested the TLD server responsible (L.ROOT-SERVERS.NET in this case) for the .net domain, the second query requested the name servers registered to daemons.net, and the final query requested the A record for the host www.daemons.net. Dig is a super cool and powerful utility!! I how to cover TSIG and signed DNS queries in a future BLOG post.
While debugging an application on a Linux server this week, I needed to view the library calls (specifically malloc and free) that were being called by a process. This was super easy to do with the Linux ltrace(1) utility:
$ ltrace /bin/cat
__libc_start_main(0x8048f49, 1, 0xbfbec464, 0x804ae98, 0x804aeec
setlocale(6, "") = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
textdomain("coreutils") = "coreutils"
__cxa_atexit(0x8048f1f, 0, 0, 0x804cb70, 0xbfbec3d8) = 0
getopt_long(1, 0xbfbec464, "benstuvAET", 0x804c9c0, NULL) = -1
__fxstat64(3, 1, 0xbfbec360) = 0
__fxstat64(3, 0, 0xbfbec360) = 0
malloc(1024) = 0x8c5f858
read(0,
ltrace(1) also allows you to selectively trace library calls when executed with the “-e” option and a set of calls to trace:
$ ltrace -e malloc /bin/cat
malloc(1024) = 0x8883858
If you need to view the library calls from a live process, you can use ltrace(1)‘s “-p” option:
$ ps auxw | grep [g]am_server
root 2644 0.0 0.2 2212 1064 ? S 12:51 0:00 /usr/libexec/gam_server
$ ltrace -p 2644
--- SIGSTOP (Stopped (signal)) ---
--- SIGSTOP (Stopped (signal)) ---
time(NULL) = 1130003202
__xstat64(3, "/etc/xdg/menus/server-settings-m"..., 0xbfe342bc) = -1
__errno_location() = 0xb7f266a0
memcpy(0x84a56e0, "|q221", 96) = 0x84a56e0
g_dir_open(0x84a5748, 0, 0, 0x8b59c1, 0x8499fe8) = 0
__xstat64(3, "/root/.config/menus/server-setti"..., 0xbfe342bc) = -1
__errno_location() = 0xb7f266a0
memcpy(0x84a55f8, "330B343277_i256", 96) = 0x84a55f8
g_dir_open(0x84a5660, 0, 0, 0x8b59c1, 0x8499fe8) = 0
__xstat64(3, "/etc/xdg/menus/system-settings-m"..., 0xbfe342bc) = -1
This is a super cool utility, and is invaluable tool for debugging application problems on Linux systems.
I performed a Fedora core 4 installation today, and for some reason the root password I typed in during the installation got munged (or I typed it incorrectly two times). Since Fedora Core uses grub as a boot loader, I was able to recover from this situation relatively quickly.
To get to a shell where I could use the passwd(1) utility or vi(P) to change the password, I first needed to reboot the box to get to the grub menu. Once I was greeted with the grub menu, I used the up and down arrow keys to select a kernel, and then hit the ‘e’ key to edit the boot paramaeters. Once the editor displayed the kernel boot string, I added a 1 immediately following the LABEL definition:
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/ 1 rhgb quiet
The number following the LABEL definition indicates the run level to boot into, and in this case 1 refers to single user mode. Once you finish editing the boot definition, you can hit ‘b’ to boot. This will boot to single user mode, and should dump you into a shell if everything goes well. Once your in the shell, you can use passwd(1) or vi(P) to update the root users password. Since I haven’t tinkered with grub for quite some time, this experience reminded me how important physical security and grub passwords are!
Whiel reading through the dig documentation today I came across the “nssearch” option:
$ dig +nssearch @192.168.1.1 daemons.net
SOA olympus.daemons.net. hostmaster.daemons.net. 1128483301 16384 2048 1048576 2560 from server olympus.daemons.net in 27 ms.
SOA olympus.daemons.net. hostmaster.daemons.net. 1128483259 16384 2048 1048576 2560 from server elysium.daemons.net in 41 ms.
This nifty little option can be used to view the SOA record maintained by all servers authoritative for a domain. If you choose to avoid using AXFR and manually update zone files, this option could be extremely useful.
While reviewing the running processes on my Linux desktop, I noticed a process named mDNSResponder. I have seen this process numerous times on my OS X desktops, but have never taken the time to determine what function it served. Being the curious guy I am, I read through the mDNSResponder(1) manual page, and found the following description:
“The mDNSResponder daemon publishes and browses available services on a link according to the IETF Zeronconf (aka “Rendezvous”) draft standard. Only one instance of mDNSResponder needs to run on a host. Once started, mDNSResponder runs continuously.”
This explains how iTunes is able to discover airtunes capable airport express base stations, and is most likely the foundation of peer-to-eer service discovery in Apple networks.