troubleshooting dnssec

If you’re looking for DNSSEC troubleshooting tools, Carsten Strotmann’s article Delve deep into DNSSEC presents a new cli tool that will be available in BIND 9.10 called delv.

delv works very much like the already know dig. It is like dig with special DNSSEC validation powers. delv checks the DNSSEC validation chain using the same code that is used by the BIND 9 DNS server itself.

But keep in mind that delv, as any standard unix tool, will use the resolvers in /etc/resolv.conf to perform all lookups. If all your resolvers listed  are DNSSEC validating, delv will not be able to lookup a non-dnssec validating RR, and will not help you debug the problem.

[stsimb@jumbo ~]$ delv +multi +rtrace
 ;; fetch:
 ;; resolution failed: failure

You need to have access to some non-DNSSEC validating resolver, to kick start the trace..

[stsimb@jumbo ~]$ delv @ +multi +rtrace
 ;; fetch:
 ;; fetch: eu/DS
 ;; fetch: ./DNSKEY
 ;; fetch:
 ;; fetch: eu/DNSKEY
 ;; fetch: eu/DS
 ;; fetch: ./DNSKEY
 ;; fetch:
 ;; fetch: eu/DS
 ;; fetch: ./DNSKEY
 ;; fetch:
 ;; fetch: eu/DNSKEY
 ;; fetch: eu/DS
 ;; fetch: ./DNSKEY
 ;; no valid RRSIG resolving '':
 ;; no valid DS resolving '':
 ;; resolution failed: no valid DS

Personally I don’t consider this a bug. It’s expected behaviour, a unix tool to use the resolvers in /etc/resolv.conf for resolution.

delv cannot determine for sure if it’s your resolver’s fault, and then try another one (and if it did, which one should it choose?). It’s your job to have this in mind, and ask some other non-dncsec validating resolver that you have access to.

Nevertheless, this situation may come up many times. Troubleshooting broken trust chains is one of the reasons someone will use delv, and gives you a reason to keep a non dnssec-validating resolver available somewhere.

Update: Thanks to Peter van Dijk‘s tweet I discovered that +cdflag works in delv (although it’s not listed in delv -h).

soacheck – report changes in domain serial numbers


I wanted to check how often a domain gets updated, so I quickly put together soacheck.

I assume that everybody increments the SOA serial number when they make a change or generate the zone file. But strictly speaking, they don’t have to do it (they can use some other way to sync changes to all their NSs and make them available).


List the zones you’re interested in file «zones-to-check». Execute soacheckd in your crontab (no need to run as root), as often as you like. e.g.

* * * * * /path/to/soacheckd > /dev/null

Check the results in soacheckd.log.

[stsimb@pipitsa soacheck]$ grep " gr. " soacheckd.log | tail
Fri Feb 1 04:51:01 EET 2013 soacheckd[22093] gr. serial changed from 1301312194 to 1302010099
Fri Feb 1 07:51:02 EET 2013 soacheckd[19481] gr. serial changed from 1302010099 to 1302010401
Fri Feb 1 10:52:01 EET 2013 soacheckd[18500] gr. serial changed from 1302010401 to 1302010695
Fri Feb 1 13:52:01 EET 2013 soacheckd[19079] gr. serial changed from 1302010695 to 1302011000


  • Record answers from authoritative servers (answers now are from system resolver’s cache)
  • Record answers from multiple servers
    • use a set of public dns servers
    • use some dns-lg instances around the world
  • Make multiple checks in parallel
  • Record changes of other RR types, e.g. A, AAAA, CNAME, PTR etc
  • Trigger some event on change

IPv6 reverse DNS in 60″

Your allocation: 2001:db8/32
You LAN: 2001:db8:2:2001/64
Your device: 2001:db8:2:2001::11 (mydevice.local)

Let «host» do the dirty work for you!

sotiris@jumbo:~$ host 2001:db8:2:2001::11
Host not found: 3(NXDOMAIN)

The zone for your /32 is

$TTL 1d
@    IN    SOA ( 42 1h 15m 30d 10m )
     IN    NS    localhost.
;    IN    NS    localhost. ; delegate 2001:db8:2:2001/64

The zone for your /64 is

$TTL 1d
@    IN    SOA ( 42 1h 15m 30d 10m )
     IN    NS    localhost.
; IN PTR mydevice.local.

Reconfig and run host again

sotiris@jumbo:~$ host 2001:db8:2:2001::11 domain name pointer mydevice.local.

Resolvers Vs. Authoritative DNS, part 2

Με τον καινούριο Κανονισμό Διαχείρισης και Εκχώρησης Ονομάτων Χώρου (Domain Names) με κατάληξη .GR (pdf link), που δημοσιεύτηκε από την ΕΕΤΤ στις 14/04/2011, γίνεται υποχρεωτικό πλέον αυτό που είχα γράψει πριν δύο χρόνια στο Resolvers Vs. Authoritative DNS

Αρθρο 17, παράγραφος 28:
Στην περίπτωση που ένας Καταχωρητής Ονομάτων Χώρου λειτουργεί και ως Πάροχος υπηρεσιών πρόσβασης στο Διαδίκτυο (ISP), οι Λύτες (Resolvers) στο δίκτυο πρόσβασης δεν πρέπει να είναι Αρμόδιοι Εξυπηρετητές Ονομάτων (Authoritative Domain Name Server) για άλλα αρχεία ζώνης Ονομάτων Χώρου, με εξαίρεση τα Ονόματα Χώρου στα οποία ο ίδιος ο Πάροχος υπηρεσιών πρόσβασης στο Διαδίκτυο (ISP) είναι Φορέας/δικαιούχος.

Nice work EETT!

Re: Why DNS blacklists don’t work for IPv6 networks

Today @hakmem tweeted a blog post by John Levine entitled «Why DNS blacklists don’t work for IPv6 networks«.

I find the last paragraph very interesting:

For the most part mail systems simply won’t use IPv6 addresses, since all the mail that anyone wants will continue to be sent using IPv4.

How do you define «All the mail that anyone wants» ?
What I want in my email, is not always what another person wants.

Why will it continue to be sent using IPv4, when every dual-stack server that runs an MTA these days *prefers* IPv6 transport when it is available?

Automagically generate reverse from forward zones

Given a (forward) zone file, here is a quick way to automagically generate all the reverse zone files you need:

# does not generate PTR records for $GENERATE lines
# does not generate PTR records for CNAME and AAAA RRs
# generates PTR records for A RRs
%revzones = ();
$domain = $ARGV[0] || "";
$filter = $ARGV[1] || '\S+';

open (F, "<$domain");
while (<F>) {
	next if ($_ =~ /^[;\#\$]/);
	if ($_ =~ /(\S+)[\s]+(\d+[\s]+)?IN[\s]+A[\s]($filter)/) {
		$host = $1;
		$ip = $3;
		($a, $b, $c, $d) = split (/\./, $ip);
		$revzone = "$c.$b.$";
		$ptr = "$d\tIN\tPTR\t$host.$domain.\n";
		$revzones{$revzone} .= $ptr;
close (F);

open (NC, ">named.conf.rev");
foreach $revzone ( sort keys %revzones ) {
	open (R, ">$revzone");
	print R "\$INCLUDE \"\"\n";
	print R "$revzones{$revzone}";
	close (R);
	print NC "zone \"$revzone\" { type master; file \"rev/$revzone\"; };\n";
close (NC);

Careful as it will overwrite any existing reverse zone files you have in your current working directory.

PS. I do have one zone that generates 263 reverse zone files!