# nslookup and drill: DNS resolution in terminal

LLMS index: [llms.txt](/en/llms.txt)

---

The server won't resolve a domain, but pings fly through. No familiar dig at hand — the BIOS is already loading a minimal busybox. Or on a host without bind-tools. nslookup and drill fill this gap: the first one is built into almost everything, the second gives more context when debugging.

## nslookup: interactive and one-liner modes

nslookup ships with bind-utils and isc-dhcp-client. It works in two modes.

One-liner query:

```
nslookup example.com
nslookup example.com 8.8.8.8
```

Interactive mode starts with no arguments. Typical session:

```
$ nslookup
> server 1.1.1.1
Default server: 1.1.1.1
Address: 1.1.1.1#53
> set type=MX
> example.com
Server:         1.1.1.1
Address:        1.1.1.1#53

example.com     mail exchanger = 10 mx1.example.com.
> exit
```

Switching servers inside a session only changes the resolver for that query. If you need a permanent resolver — edit `/etc/resolv.conf`.

## DNS record types in queries

By default nslookup queries A records. For other types use `set type=`:

| Record type | Purpose | Example output |
|-------------|---------|----------------|
| A | IPv4 address | `93.184.216.34` |
| AAAA | IPv6 address | `2606:2800:220:1::` |
| MX | Mail exchanger | `10 mail.example.com` |
| TXT | Text records, SPF | `v=spf1 include:_spf.example.com ~all` |
| NS | Authoritative servers | `a.iana-servers.net` |
| SOA | Start of Authority | serial 2005080901 |
| CNAME | Canonical name | `example.com canonical name = www.example.com` |
| PTR | Reverse resolution | `34.216.184.93.in-addr.arpa name = example.com` |

One-liner equivalent — `-type=` flag:

```
nslookup -type=ANY example.com
nslookup -type=MX github.com
```

> [!WARNING]
> `ANY` queries are often blocked at the resolver level. The recursor returns SERVFAIL or an empty response. Do not rely on ANY when troubleshooting.

## drill: output with Resource Record type

drill is part of ldns. It returns results in classic DNS format with ANSWER, AUTHORITY, ADDITIONAL sections:

```
drill A example.com
drill MX github.com @1.1.1.1
```

drill output is more readable when tracing a CNAME chain:

```
$ drill CNAME www.cloudflare.com
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDRIBUTE: 0

;; QUESTION SECTION:
;www.cloudflare.com.   IN   CNAME

;; ANSWER SECTION:
www.cloudflare.com.  300  IN  CNAME  cloudflare.com.

;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
```

Without the `@server` flag, drill reads the resolver from `/etc/resolv.conf`.

## DNSSEC validation

drill checks the DNSSEC trust chain:

```
drill -S _dmarc.example.com TXT @1.1.1.1
```

The `-S` flag requests the DS record higher in the chain and validates the signature. On an invalid chain:

```
drill: RRSIG validation failed: Signature has expired
```

nslookup does not validate DNSSEC — it only sends queries with the DO flag (include RRSIG in the response). For full validation you need drill or `delv`.

## NXDOMAIN and SERVFAIL: reading response codes

First step on any error — look at the response code.

**NXDOMAIN** (code 3) — the domain does not exist. Source: authoritative server for the zone. If `dig +short` returns nothing, and nslookup says `** server can't find example.invalid`, that's NXDOMAIN. Causes: typo in the domain, stale CNAME, deleted zone.

**SERVFAIL** (code 2) — the resolver couldn't answer. Causes: broken DNSSEC validation, exceeded timeout, circular reference in NS records, overloaded authoritative server. nslookup shows `** server can't find example.com: Server failed`.

**REFUSED** (code 5) — the recursor refused to answer. Usually ACL on the DNS server or rate limiting.

```
nslookup example.com 10.0.0.1
# Server:  10.0.0.1
# Address: 10.0.0.1#53
# ** server can't find example.com: Server failed
```

## Key flags for nslookup and drill

### nslookup

| Flag | Effect |
|------|--------|
| `-type=RR` | Record type (A, MX, TXT, ANY) |
| `host` | Redirect to specified server |
| `-port=53` | Non-standard port (e.g. 5353 for mDNS) |
| `-timeout=5` | Timeout in seconds |
| `-retry=3` | Number of retries |
| `-vc` | TCP instead of UDP |

```
nslookup -type=TXT -port=5353 _http._tcp.local 224.0.0.251
```

### drill

| Flag | Effect |
|------|--------|
| `@server` | Server to query |
| `-Q` | Quiet mode, answer only |
| `-T` | Show response time |
| `-S` | DNSSEC validation |
| `-D` | Force DNSSEC (query with DO flag) |
| `-p port` | Non-standard port |
| `-t timeout` | Timeout in seconds |

```
drill -TD -S TXT dkim._domainkey.example.com @8.8.8.8
```

`-T` is useful for comparing latency between resolvers:

```
drill A google.com @1.1.1.1
# Query timeout: 2
# Answer received in 45ms
```

## Installation

```
# Debian / Ubuntu
apt install dnsutils ldnsutils

# RHEL / CentOS / Fedora
dnf install bind-utils ldns

# Alpine
apk add bind-tools ldns
```

In minimal busybox images you already have a simplified nslookup. The full feature set is available after installing dnsutils.
