Check DNS Validation with delv
A forged or stripped DNS answer looks exactly like a real one until you check it with delv. It is BIND 9's DNSSEC-aware lookup tool: point it at a server and it tells you whether the answer is fully validated, unsigned or invalid. This guide covers a normal query, a reverse lookup and the trace options for when an answer needs investigating. Allow about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Confirm the installed version
This guide uses the bind9-dnsutils package, version 9.18.39-0ubuntu0.24.04.7-Ubuntu. Options and output differ between releases, so check your own binary before copying a command into a script:
$ command -v delv
/usr/bin/delv
$ delv -v
delv 9.18.39-0ubuntu0.24.04.7-Ubuntu
Tip
No command in this guide needs elevated privileges, because queries are ordinary network operations. Do not reach for sudo to fix a timeout or a DNSSEC failure: root access will not make an unreachable resolver reachable, or an invalid signature valid.
2. Query a name and read the validation marker
Give delv a server with the @server prefix, followed by the name and record type. This example asks Cloudflare's resolver for the IPv4 address records for example.com:
$ delv @1.1.1.1 example.com A
; fully validated
example.com. 138 IN A 104.20.23.154
example.com. 138 IN A 172.66.147.243
The addresses and TTL will change every time you run it. What matters is the status comment. ; fully validated means delv built and checked a DNSSEC chain from its trust anchor. A signed response is not automatically a valid one, so do not treat the presence of an RRSIG alone as proof.
For a compact answer, add +short:
$ delv @1.1.1.1 example.com A +short
93.184.216.34
Short output is handy for a quick value check, but it drops the explanation that tells you whether validation actually succeeded. Use the default verbose form when that is the question.
3. Know which resolver you are actually querying
Omit @server and delv falls back to whatever is listed in /etc/resolv.conf, then to local IPv4 and IPv6 addresses if it finds nothing usable there. Check that file before diagnosing a surprising result:
$ sed -n '1,40p' /etc/resolv.conf
nameserver 127.0.0.53
A local stub such as 127.0.0.53 can forward to an upstream service you have never inspected. Supplying @1.1.1.1, @8.8.8.8 or your organisation's known resolver makes the comparison explicit. A hostname form such as @resolver.example.net needs a preliminary lookup that delv does not validate, so an IP address is the clearer choice while troubleshooting DNSSEC.
The default query type is A. Add the type when you need something else:
$ delv @1.1.1.1 example.com MX +short
0 .
Do not read an empty or terse result as a validation failure. Check the verbose response, the exit status and the record type you actually asked for.
4. Trace the resolver and the validator
When the status surprises you, add +rtrace to show the fetches made while resolving and +vtrace to show the DNSSEC decisions behind them:
$ delv @1.1.1.1 example.com A +rtrace +vtrace
;; fetch: example.com/A
;; validating example.com/A: starting
;; fetch: example.com/DNSKEY
;; fetch: example.com/DS
;; fetch: com/DNSKEY
;; fetch: ./DNSKEY
;; validating example.com/A: marking as secure (DS)
; fully validated
The exact fetch order and key identifiers vary. Look for the original query, the DNSKEY and DS lookups, then the final validation state. +mtrace adds a full dump of received messages and can be noisy, so start with the two narrower traces so the event you care about is not buried in packet data.
5. Pull DNSSEC data without hiding the evidence
delv requests and validates DNSSEC records by default. +dnssec and +nodnssec only control whether RRSIG records are displayed; they do not switch DNSSEC requests or validation on and off, the way they do in some dig workflows. Use +noall carefully, since it clears comment, per-record comment and trust-display options together.
If the resolver you are querying is itself validating and is blocking an invalid answer, ask it to disable checking for this one query with +cdflag:
$ delv @1.1.1.1 name.example A +cdflag +vtrace
$ printf 'exit status: %s\n' "$?"
exit status: 0
Replace name.example with a domain you are authorised to test. This is a diagnostic path, not a way to make bad DNS safe: the upstream resolver may ignore the request, and delv can still report a validation error locally. The manpage notes that -i disables delv's own internal validation without setting the CD bit, so avoid -i when the question is whether an answer can be trusted.
6. Run a reverse lookup
Use -x for an address-to-name query. delv builds the corresponding reverse DNS name for you and switches the type to PTR:
$ delv @1.1.1.1 -x 1.1.1.1 +short
one.one.one.one.
IPv6 addresses are converted to the nibble form under ip6.arpa. A reverse result is an assertion made by the address owner, not proof that the named host owns the address in the forward direction. If that relationship matters, query the returned name for an A or AAAA record and compare it yourself.
7. Handle failures without touching the system
For a timeout, try the same name against a known-reachable resolver first, and force a transport family if that helps:
$ delv -4 @1.1.1.1 example.com A
$ delv -6 @2606:4700:4700::1111 example.com A
$ printf 'last status: %s\n' "$?"
last status: 0
Use only the command that matches a working interface. -4 and -6 restrict transport; they do not change the queried record. If both fail, check routing, firewall policy and the resolver service rather than editing /etc/resolv.conf, which another service commonly manages and can overwrite behind your back.
For a validation failure, keep the full verbose output, repeat with +rtrace +vtrace, and compare a second resolver.
Warning
Do not replace /etc/bind/bind.keys casually. It holds the default trust anchors delv uses, and the manpage warns it does not read the managed-keys database maintained by named. Changing trust anchors changes what the tool trusts, so follow your distribution's BIND update process instead.
Done means
- Confirmed the version and queried an explicit server instead of trusting the default.
- Told validated from merely returned, using the status comment rather than the presence of records.
- Traced the DNSSEC path with
+rtraceand+vtracewhen the result needed evidence. - Know the diagnostic flags:
-idisables local validation, and+cdflagis a request to the upstream resolver, not a fix. - Checked reverse results properly, without treating a PTR answer as forward ownership proof.
- Left resolver configuration and trust anchors unchanged.