Below are a few examples of configurations you can use during the workshop. Note that they may not be suitable for production zones.

The workshop roots trust anchor


trusted-keys {
"." 257 3 5 "AwEAAefwq///dxpJmppvNLLH/2RNST0Lcka2WHr6sd3N3nH4gzHg7qFM
             267FGNwoX8VEqgLvlszaAHUY5bRrNFF00xsHkWFHfYvm5pufZdfNgGLU
             olOHsHU6jCLQR/PIQm3tuX4NHOD9sYfjmUVAsGlqFuwO9zYnt6L1k6/n
             04eKWqa4yLspups4MYlxKMs328D3SojZCMAmea+RXZknJKVRZJ83daup
             9LBft/hgEZIG/h5VT/ZK1rwJBMe67EOR94uNgNUGjvOP2iowaU9Czoq3
             +Na6yAuCibksQvEp2bZjbutC2zTxHAXNIr3AQwLk4BqA9+PfBZWUUEnp
             8i0lZfQiVJU="
};



This trust-anchor is extracted from the KSK from the root:

. IN DNSKEY 257 3 5 AwEAAefwq///dxpJmppvNLLH/2RNST0Lcka2WHr6sd3N3nH4gzHg7qFM
                    267FGNwoX8VEqgLvlszaAHUY5bRrNFF00xsHkWFHfYvm5pufZdfNgGLU
                    olOHsHU6jCLQR/PIQm3tuX4NHOD9sYfjmUVAsGlqFuwO9zYnt6L1k6/n
                    04eKWqa4yLspups4MYlxKMs328D3SojZCMAmea+RXZknJKVRZJ83daup
                    9LBft/hgEZIG/h5VT/ZK1rwJBMe67EOR94uNgNUGjvOP2iowaU9Czoq3
                    +Na6yAuCibksQvEp2bZjbutC2zTxHAXNIr3AQwLk4BqA9+PfBZWUUEnp
                    8i0lZfQiVJU=

named.conf

See Chapter 6. BIND 9 Configuration Reference for the details of all the options and statments.
// example configuration for a recursive server

options {
        pid-file "named.pid";
	dnssec-enable yes;
        dnssec-validation yes;
	listen-on {127.0.0.1;};
	recursion yes;	
};


/// Beter uses $include and prevent reading this secret.
//  There is also a tool to generate this.
//  man 8 rndc-confgen 

key "rndc-key" {
        algorithm hmac-md5;
        secret "upDNkmX9suVSLvf32mnbCw==";
};



controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1;}  keys { "rndc-key"; };
};





zone "." {
	type hint;
	file "root.hints";
};




logging {

        channel syslog_channel {
                syslog daemon;        // end to syslog's daemon
                severity debug 6;
                print-severity yes;
                 print-category yes;
        };
        channel query_channel {
                file "/usr/local/workshop/log/querylog" size  5m ;
                print-time yes;
        };

        channel update_channel {
                file "/usr/local/workshop/log/notify+update.log" size 5m;
                print-time yes;
               severity debug 5;
        };
        
        channel notify_channel {
                file "/usr/local/workshop/log/notify+update.log" size 5m;

                severity debug 6;
                print-time yes;
        };

        channel everything_else {
                file "/usr/local/workshop/log/runlog" size 5m;
                print-time yes;
                severity debug 6;
                print-severity yes;
                print-category yes;
        };


        channel dnssec_log {                 // a DNSSEC log channel
                file "/usr/local/workshop/log/dnsseclog"  size 20m;
                print-time yes;                 // timestamp the entries
                print-category yes;             // add category name to entries
                print-severity yes;             // add severity level to entries                
                severity debug 6;               // print debug message <= 3 t

        };
        category dnssec  { dnssec_log;  };
        category security { dnssec_log;  };
        category queries { query_channel; };
        category update  { update_channel; syslog_channel; };
        category notify  { notify_channel; syslog_channel; };
        category default { everything_else; };
};


Zone file


; demonstration zone l
; 
$TTL 100
@	100	IN	SOA	 ns  (    
			 zonemaster    ; assuming zonemaster@orignin
			 2007082200
				100    ; These values 
				200    ; are to unrealistic for 
			     604800    ; production zones
				100
				)



			NS		ns
ns			A		193.0.24.<YOUR NUMBER>


demo			A		10.0.0.1

$include K<your keysigning>.key
$include K<your zonesigning>.key

root.hint

This root hint is FOR THE WORKSHOP ONLY.

; Workshop root hints
; DO NEVER USE IN PRODUCTION
. 		400	IN	NS		A.root-servers.work.
A.root-servers.work. 	400	IN	A		193.0.24.110

The Signed Zone

For examples of the zones used in the workshop setup see the unsigned zonefiles and their signed counterparts.

Testing using drill

If you store the Workshop Root Hints in a file (e.g. root.hints) and the DNSKEY RR that is used as trust anchor in another (e.g. keyfile.pub) you can use "drill".
 drill -k keyfile.pub  -r root.hints  -S www.infra.work A  
[Example to be constructed]

Example Script

This is a perl script that uses Net::DNS and Net::DNS::SEC to perform some rudimentary checks in the workshop environment.
#!/usr/bin/perl

# Demonstration script that tests the availability of self-signed
# key-sets.

#
# Not suitable for production. To little error checking

use strict;

use Net::DNS::Resolver;
my $domain_to_check= "work" ;
# The domain should allow AXFR




my $res=Net::DNS::Resolver->new(
				dnssec     => 1,
				tcp_timeout => 1,
				udp_timeout => 1,
				retry       => 1,
				);


$domain_to_check . "." unless $domain_to_check =~ /\.$/;


my @auth_address=get_authaddress($domain_to_check);

die "Could not find authoritative servers for $domain_to_check" unless @auth_address;

print "Found the following authoritative servers for $domain_to_check:\n";

foreach my $address ( @auth_address ) {
    print "\t $address\n";
}


my @zone;

foreach my $address (  @auth_address ) {
    print "Trying zonetransfer at $address\n";
    my $res=Net::DNS::Resolver->new();
    $res->nameserver($address);
				
    @zone=$res->axfr($domain_to_check);
    
    next unless @zone;
    
}

die "Could not zonetransfer from any of the authoritative servers" unless @zone;

my %domains;

foreach my $rr ( @zone ){

    # Those RRs which do not have the same owner name as the domain we
    # are looking at but are of type NS must be delegations
    next if ($rr->name eq $domain_to_check);
    next if ($rr->type ne "NS");
    #
    # Also not deal with things we touched before
    next if exists $domains{$rr->name};
    

    # use the local resolvers to collect all authoritative servers for
    # this domain and store the address array that is returned in the
    # hash-structure.

    $domains{$rr->name}= [ get_authaddress($rr->name) ];

}	



# The %domains hash is filled with anonymous arrays containg IP addresses
# of the domain that equals the hash key.
# 
# Let us just print that information
foreach my $domain (keys %domains){
    print "Nameservers for $domain are at: " . 
	join (" ", @{$domains{$domain}}) 
	."\n";
}


#
#
# Using the above infromation you could check if the SOA is the same
# for each server for a particular domain. We skipp that now.
#
sleep(10);

while(1){
    print "-----------------------------------\n";

    my $res=Net::DNS::Resolver->new(
				      retry => 1,
				      tcp_timeout => 1,
				      udp_timeout => 1,
				      dnssec => 1,
				      );

    foreach my $domain (keys %domains){
	
	my @ns= @{$domains{$domain}};
	
	if (! defined @ns) {
	    print "I do not have IP addresses of the nameservers for ". 
		$domains{$domain} ."\n";
	    next;
	}
	
	
	$res-> nameserver ( @ns );
	my $packet=$res->send($domain,"DNSKEY");
	
	if (! defined $packet ){
	    print "Nameserver with address(es) ". join(" ", @ns).
		"do not return answer for  $domain DNSKEY \n";
	    next;
	}
	
	if (! $packet->answer ){
	    print "DOMAIN \"$domain\" does not have DNSKEYS\n";
	}else{
	#    print "DOMAIN $domain is cool \n";
	}
	
	
	my @sigrr;
	my @keyrr;
	foreach my $rr ( $packet->answer ){
	    if ($rr->type eq "DNSKEY"){
		 push @keyrr, $rr;
	    }
	    
	    if ($rr->type eq "RRSIG"){
		 push @sigrr, $rr;
		
	    }
	    
	}
	

	print "DOMAIN \"$domain\" has has not been signed !\n" unless @sigrr;
	next unless @sigrr;

	# Check the self signatures over the keyset.
	foreach my $key (@keyrr){
	    my $matching_sig;
	    # search the RRSIG with the KEY ID of this key
	    foreach my $sig (@sigrr){
		next unless ($key->keytag == $sig->keytag );
		$matching_sig=$sig;
	    }
	    if (! defined $matching_sig ){
		print "$domain Could not find a self sig for ".$key->keytag ."\n";
		next; # next KEY
	    }
	    if (! $matching_sig->verify( \@keyrr , $key )){
		print "Validation with ". $key->keytag ." failed\n".
		    "\t". $matching_sig->vrfyerrstr ."\n";
		next;
	    }else{
		print "$domain Validation with ". $key->keytag .": OK\n";
	    }
	}

    }
    sleep 5;
    
    
}






# get_authaddress()
# Takes a domain as argument and returns an array with IPv4 addresses of
# nameservers that are authoritative.

sub get_authaddress 
{
    my $domain=shift;
    my $res=Net::DNS::Resolver->new(
				    retry => 1,
				    tcp_timeout => 2,
				    udp_timeout => 2,

				    );
    my @addresses;
    
    my $packet=$res->send($domain,"NS");
    
    
    if (! defined $packet ){
	print stderr  "Resolver does not return answer for  $domain \n";
	return;   # returns undefined vallue.
    }

    foreach my $rr ( $packet->answer ){

	next if ( $rr->type ne "NS" );
	my $packet2=$res->send($rr->nsdname,"A");
	
	foreach my $rr2 ( $packet2->answer ){
	    next if ($rr2->type ne "A");
	    next if ($rr2->name ne $rr->nsdname);
	    push @addresses , ($rr2->address);
	}



	my $packet3=$res->send($rr->nsdname,"AAAA");
	
	foreach my $rr3 ( $packet3->answer ){
	    next if ($rr3->type ne "AAAA");
	    next if ($rr3->name ne $rr->nsdname);
	    push @addresses , ($rr3->address);
	}
	
    }

    return @addresses;
}






# Copyright (c) 2007 NLnetLabs
# All rights reserved.
# 

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#     * Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#
#     * Redistributions in binary form must reproduce the above
#     copyright notice, this list of conditions and the following
#     disclaimer in the documentation and/or other materials provided
#     with the distribution.
#
#     * Neither the name of NLnetLabs nor the names of its
#     contributors may be used to endorse or promote products derived
#     from this software without specific prior written permission.  
#
#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
#   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
#   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
#   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
#   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
#   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
#   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
#   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#   SUCH DAMAGE.


Dec 12-15, 2006 © NLnet Labs
Click here for copyright notice