[dns-operations] DNSSEC signatures expired for getdnsapi.org and getdnsapi.net

Viktor Dukhovni ietf-dane at dukhovni.org
Mon Sep 18 08:19:01 UTC 2017


> On Sep 18, 2017, at 3:56 AM, Daniel Karrenberg <dfk at ripe.net> wrote:
> 
>> I'd like to suggest monitoring.  For my own domains, the alarms start
>> going off 3 days before the signatures are due to expire.  When automatic
>> re-signing is working correctly no records ever get that close to
>> expiration.
>> 
> Care to share code?

It is BIND-specific, looks directly at the slave copies of zone
files and is not documented and likely not portable.  It assumes
all monitored zones should have MX and NSEC3PARAM records. So if
that matches your needs, sure, but you'll probably need to change
it to suit your needs.  It just parses every RRSet looking for a
matching RRSIG that is not expiring shortly.  Won't scale to very
large zones where holding the zone in memory is not practical.

I have a local slave copy of the root and arpa zones.  The script
produces no output when all is well, and otherwise cron emails me
the produced warnings.  It is a mixture of bash and Perl.

XX YY * * * cd $HOME; ./bin/checkdns . arpa dukhovni.org xn--b1adqpd3ao5c.name xn--b1adqpd3ao5c.org ...etc...

-- 
	Viktor.

#! /usr/local/bin/bash

# FreeBSD paths and /etc/namedb data location below
export PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin

maxdays=3.14159

usage() {
    echo "Usage: $0 [-d maxdays] domain ..." >&2
    exit 1
}

while getopts d: o
do
   case $o in
   d) maxdays="$OPTARG";;
   *) usage;;
   esac
done
shift $(( OPTIND - 1 ))

export TZ=UTC
for d in "$@"
do
    case $d in
    .) db=root.slave;;
    arpa) db=$d.slave;;
    *) db=$d;;
    esac
    named-compilezone -i local -jD -f raw -o - $d /usr/local/etc/namedb/slave/$db 2>/dev/null |
    perl -MPOSIX -lane '
	BEGIN {
	    ($domain, $maxdays) = splice(@ARGV, 0, 2);
	    $now = time();
	    for (qw(DNSKEY NS)) { $want->{"IN"}->{$_}->{$domain} = 1; }
	    if ($domain ne "." && $domain ne "arpa") {
		for (qw(MX NSEC3PARAM)) { $want->{"IN"}->{$_}->{$domain} = 1; }
	    }
	}
	($owner, $ttl, $class, $rrtype, @rdata) = @F;
	next if $rrtype ne "RRSIG";
	($sigtype, $alg, $labels, $maxtll, $expiration, $inception) = @rdata;
	$expiration =~ m{^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$}
	    or die "Malformed expiration $owner $sigtype: $expiration\n";
	$s = POSIX::mktime($6, $5, $4, $3, $2 - 1, $1 - 1900);
	$d = ($s - $now) / 86400;
	if ($d < $maxdays) {
	    warn sprintf("Signature of $owner $class $sigtype expires in %.2f days\n", $d);
	}
	$owner =~ s/.\K\.$//;
	delete $want->{$class}->{$sigtype}->{lc($owner)};
	END {
	    while (($class, $vc) = each %$want) {
		while (($rrtype, $vr) = each %$vc) {
		    while (($domain, $dummy) = each %$vr) {
			warn "No signature found for $domain $class $rrtype\n"
		    }
		}
	    }
	}
    ' "$d" "$maxdays"

    if [ "$d" = "." -o "$d" = "arpa"]; then continue; fi

    # Check delegation consistency
    #
    p=${d#*.}
    pns=( $(dig +short -t ns "$p." | sort) )
    gluens=( $(dig +noall +auth +nocl +nottl -t ns "${d%.}." "@${pns[0]}" | awk '{print $NF}' | sort) )
    if [ ${#gluens[@]} -eq 0 ]; then
	printf "Warning no glue NS RRs found for %s via %s\n" "$d" "${pns[0]}" >&2
	continue
    fi
    for gns in "${gluens[@]}"
    do
	zonens=( $(dig +short -t ns "${d%.}." "@${gns[0]}" | sort) )
	if [ ${#zonens[@]} -ne ${#gluens[@]} ]; then
	    echo "$d glue NS count != zone NS count @$gns" >&2
	    continue
	fi
	for i in "${!gluens[@]}"
	do
	    if [ "${gluens[$i]}" != "${zonens[$i]}" ]; then
		printf "$d glue NS[%d] %s != zone NS[%d] %s @$gns" \
		    $i "${gluens[$i]}" $i "${zonens[$i]}" >&2
	    fi
	done
    done
done




More information about the dns-operations mailing list