February 2008 Archives
Split DNS done right: 2 servers; NSD and BIND9
Open recursors are a problem. They can be used by attackers to amplify a packet stream to a victim. As such you should only be running a recursor on your internal network and an authoritative server on your interfaces facing the big, bad Internet.
You can run BIND9 with a split view (also called 'split brain'), or use my setup: a NSD serving the outside world, and using BIND9 as recursor for your internal network.
Zones
I'm the owner of multiple domains, among which miek.nl is just one. For the purpose
of this article I will pretend this is the only domain I have. The goal here is to
have this domain available both inside my network and on the outside. And to have
recursion on the inside, but not on the outside.
Internet side
The config for miek.nl looks like this. This does assume how to read these kind
of files. The zone file is relatively short and nothing fancy happens.
For completeness, I'm using puppet for my
/etc/configuration -- you should too! :)
;
; NSD data file for miek.nl for public use
; ## configured with puppet ##
;
$TTL 1D
$ORIGIN miek.nl.
@ IN SOA open.nlnetlabs.nl. miekg.atoom.net. (
2007032000 ; Serial
4H ; Refresh
1H ; Retry
7D ; Expire
1D ) ; Negative Cache TTL
IN NS open.nlnetlabs.nl.
IN NS omval.tednet.nl.
IN NS elektron.atoom.net.
IN MX 20 mail.atoom.net.
IN MX 30 sol.nlnetlabs.nl.
miek.nl. IN A 80.127.17.126
localhost IN A 127.0.0.1
a IN A 80.127.17.126
www IN CNAME a
This zonefile contains real IP addresses, which can be resolved on the Internet.
Internal side
For internal use I'm using a slightly different zone (the joy of NAT), which looks like this:
;
; BIND data file for miek.nl for internal use
;
$TTL 1H
@ IN SOA elektron.atoom.net. miekg.atoom.net. (
2005060700 ; Serial
6H ; Refresh
2H ; Retry
7D ; Expire
1H ) ; Negative Cache TTL
@ IN NS elektron.atoom.net.
@ IN MX 10 elektron.atoom.net.
@ IN A 192.168.1.2
localhost IN A 127.0.0.1
a IN A 192.168.1.2
www IN CNAME a
And you can see that only RFC1918 addresses are used here.
Setup
So how do you actually perform the setup so that you have two servers running? First install the software packages you'll need (This is on Ubuntu/Debian):
Install nsd:
apt-get install nsd
Install bind9
apt-get install bind9
Configuration
BIND
Well, BIND is pretty well known and you can find loads of howtos on how to setup this daemon.
I'm only interested in making is listening on the intranet interfaces, in my
case (i'm only showing the relevant parts of the named.conf configuration file):
// This is the primary configuration file for the BIND DNS server named.
// ## configured with puppet ##
options {
directory "/var/cache/bind";
recursion yes;
listen-on { 127.0.0.1; 192.168.1.2; ::1; 10.0.0.1; };
};
Note the recursion yes, without this I wouldn't be able to resolve names on my internal
network.
My /etc/resolv.conf ofcourse lists my own server as nameserver:
# ## configured with puppet ##
nameserver 127.0.0.1
search atoom.net. dmz.atoom.net.
So this takes care of my internal needs.
NSD
For NSD (version 2) I need to configure which zones are to be loaded. This is done in the
nsd.zones file:
; ## configured with puppet ##
; forward
zone miek.nl zones/db.miek.nl notify 213.154.224.1 213.154.224.17
Next I need to tell NSD that it should listen on my external network interfaces.
On debian/Ubuntu this is handled in the file /etc/default/nsd. On my system it looks like this
(only the relevant parts are shown):
# Flags to pass to nsd on startup
flags="-u nsd -a 80.127.17.126 -a 2001:7b8:2ff:c8::2"
This tells NSD to listen on my external IPv4 and IPv6 addresses. Setting up and requesting
a domain name goes beyond this article.
Restart the services
Basicly that was it... now BIND9 is only used on my internal network, and NSD is used for the outside. Just the way I like it; just the way it should be.
Just restart the services and you should be done:
/etc/init.d/nsd restart && /etc/init.d/bind9 restart
Check /var/log/messages/ and /var/log/daemon.log for any errors you might get.
My ZSH prompt setup
I like tweak my prompt and I use zsh, thus I have infinite possibilities :-)
I owe much the phil's prompt which gave me a lot of ideas.
My prompt is ofcourse in full color, as I'm a fan of that too. (Old UNIX users may shrudder at this point...)
Right now I have a prompt that keeps out of my face, but when needed has some usefull extras; like showing background jobs and showing the exit code of the previous command if it wasn't equal to zero.
Furher more the right side prompt show the current directory.
path
My default prompt looks something like this:
host.user% pwd
Or in a specific incarnation:
elektron.miekg% ~
If the path gets too long, only the last part is shown.
The code to fix this:
mypath="%~"
((MAXMID=$COLUMNS / 2)) # truncate to this value
RPS1="$RPSL%$MAXMID<...<$mypath$RPSR"
Line1: put the current path in a variable, as I'm also using colors this was more easy. The next line calculates the half of my terminal width, so the third line will correctly chop the path if it gets too long.
background jobs
A list of background jobs is placed at the left side, but only when there are any. One background job:
[1+] host.user% ~
Or multiple
[1+,2,3-] host.user% ~
The code for the jobs-string looks like this:
for a (${(k)jobstates})
{j=$jobstates[$a];i="${${(@s,:,)j}[2]}"
myjobs+=($a${i//[^+-]/})}
myjobs=${(j:,:)myjobs}
The first three lines are the for-loop, where from the $jobstates
a new array is created. The last line transforms this array back into
a string with ,s in between.
exit code of previous command
Sometimes its very handy to see the exit code of your command, esp. when
its not zero (0). You can use echo $? after each interesting command.
The code I have in the prompt will only show the exit code if it wasn't
equal to zero at the right side, like so:
host.user% ~ (1)
This is relative easy to do in zsh:
RPSR='%(0?..(%?%))'
I'm using a conditional here, if the exit-code is zero do nothing,
otherwise print it using ( and ).
full configuration
The full setup if ofcourse somewhat more complicated, so I will just list the files here, have fun with it.
My color definition (~/.zcolors):
###
# See if we can use colors.
autoload colors zsh/terminfo
if [[ "$terminfo[colors]" -ge 8 ]]; then
colors
fi
for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE GREY; do
eval C_$color='%{$terminfo[bold]$fg[${(L)color}]%}'
eval C_L_$color='%{$fg[${(L)color}]%}'
done
C_OFF="%{$terminfo[sgr0]%}"
My prompt definition (~/.zprompt):
# load prompt functions
setopt promptsubst
unsetopt transient_rprompt # leave the pwd
# get the colors
source ~/.zcolors
# set the prompt
set_prompt() {
mypath="$C_OFF$C_L_GREEN%~"
myjobs=()
for a (${(k)jobstates})
{j=$jobstates[$a];i="${${(@s,:,)j}[2]}"
myjobs+=($a${i//[^+-]/})}
myjobs=${(j:,:)myjobs}
((MAXMID=$COLUMNS / 2)) # truncate to this value
RPS1="$RPSL$C_L_GREEN%$MAXMID<...<$mypath$RPSR"
rehash
}
# print optional number of bg jobs (when 0 show nothing)
# when the path is too long only the last section is shown
# root is simple and all red
# reset the colors when printing the rside prompt always
if [ "$USER" = "root" ]; then
PS1=$'$C_RED%~ %#% $C_OFF '
else
PS1=$'$C_L_BLUE%(1j.[$myjobs]% $C_OFF .$C_OFF)%m.%B%n%b$C_OFF$C_L_GREEN%#$C_OFF '
fi
RPSL=$'$C_OFF'
RPSR=$'$C_OFF$C_L_RED%(0?.$C_L_GREEN. (%?%))$C_OFF'
RPS2='%^'
precmd () {
set_prompt
}
Lego Mindstorms
I am now in the possession of my LEGO mindstorms set! I'm loving it already. Too bad I'm forced to use my Mac OS X to program the damn thing, but graphical programming environment works kinda cool. I'm thinking about porting the whole app to Linux (in Perl/GTK-2). But this is going to be a lot of work.
Yesterday I've built the walking robot ('Rex') which is way cool, but now I want to make something like a spider. Trouble there is that I will probably need two (2) servo motors per leg... and I only have three of them... I have seen solution for this in other robots. Other links for making spiders:
So...guess I will be spending some of my time playing with LEGO again :)
RFC4641
Co-author of RFC 4641 a BCP (Best Current Practice) for DNSSEC operations. This was written together with Olaf Kolkman.
At the time I was employed at NLnet Labs
This RFC gives guidelines on how to setup secure zones in a world with DNSSEC. It also gives pointers for public and private key handling and deals with the key lengths and how to handle key rollovers.
Moved to Maildir
Well, after having used the go'old mbox format, I have now changed my mail
setup to maildir. What a difference. I think the load on my machine
is actual less then before the transition.
I used google (mbox convert maildir) to convert my setup to maildir,
this was all relatively easy. Both postfix and
procmail were "fixed" this way.
After restarting I indeed saw mail being deliverd to my newly created
Maildir directory in my homedir. But I couldn't read it...
/etc/skel
Small sidestep:
The directory /etc/skel holds the skeleton directory for newly created users, so
I've added a Maildir directory in here too.
Mutt
As said, actual reading of Maildir-style mail from mutt was more of a problem than I thought. My final config snippet looks like this:
1. set mbox_type=Maildir
2. set folder="~/Maildir"
3. set mbox=+.old
4. set postponed=+.drafts
5. set record=+.sent
6. set spoolfile=+
7. set mask="!^\\.[^.]"
8. mailboxes ! +.spam +.old +.sent
- Tell
muttyour mail is in the Maildir format - Location of the directory
- Where to move read mail to. I could not get it to go to a complete
other directory. So now I have my old mail stored in the same
directory as my new mail. There is a package called
archivemailthat might be of help here. - Where to put postponed mail, again in a subdir below Maildir.
- Save sent mail, previously I've done this with a
send-hook. - Where is you default mailbox located, this means: your default
folder. Before I had this line in there,
muttkept looking for new mail in/var/mail. - Don't recognize
.and..mailboxes - List all your mailboxes,
!is your default mailbox here.
rdup 0.5.5
A new version of rdup is released. This release features the GPL version 3 license and I've added an option to make hourly backups (-H for rdup-simple).
See the project page for more information.
Quicklink: rdup-0.5.5.tar.bz2
rdup 0.5.5 coming soon
Rdup version 0.5.5 will be released in the next two days; after some internal testing. The release will feature a new license: GPL3. And the protection bits will now be printed in four positions - as they should be.
I've also added the possibility to create hourly backups, the diff for doing this was very small, which in my eyes shows how powerfull rdup is.
DNSSEC: problemen en beloftes
older publication: 2001
Door
R. Gieben, miek@nlnetlabs.nl or miek@miek.nl
Voorwoord
In dit introductie artikel behandel ik DNSSEC en de beloftes en problemen die het met zich mee brengt. Daarbij wil ik uit leggen wat de bijdrage van NLnet Labs is geweest in het analyseren en oplossen van enkele van die problemen. Verder ga ik in op de plannen voor de uitrol van DNSSEC in Nederland in de nabije toekomst.
NLnet Labs is opgericht door Stichting NLnet om nieuwe protocollen en applicaties te promoten en te ontwikkelen voor het Internet. Er is een budget voor 15 jaar ontwikkeling door 6 developers.
DNSSEC
In de eerste dagen van het Internet was het een plek waar voornamelijk ontwikkelaars vanuit de wetenschap en het bedrijfsleven in een vriendschappelijke omgeven met elkaar konden communiceren. Het werd gebruikt als een medium om ideeen en informatie uit te wisselen. Beveiliging was hier geen issue. Vandaag de dag nu het Internet miljoenen gebruiker herbergt, zijn de risico's groter geworden. De risico's varieren van ongewenst tot ronduit gevaarlijk: van spam (grootschalig verspreiden van ongevraagde reclame) via virusssen en denial of service attacks, tot fraude met creditcard nummers. In al deze zaken speelt het ontbreken van een waterdichte indentificatie en authenticatie een hoofdrol.
Een van de systemen die goed werken in een vriendelijke omgeving, maar tegenwoordig kwetsbaar blijken te zijn, is het domain name system (DNS). De belangrijkste taak van het DNS is het verzorgen van een conversie tussen een domein name (bijvoorbeeld www.example.com) en een IP nummer (bijvoorbeeld 192.168.1.1). Mede dankzij de schaalbaarheid van het DNS is het Internet zo snel, zo groot geworden.
Echter, door het ontbreken van beveiliging kan men in een onvriendelijke omgeving de DNS informatie manipuleren en daarmee zowel de eigen identiteit verhullen als anderen de verkeerde kant op sturen. Dankzij het eerste kan men ongestraft SPAM en virussen verspreiden, het tweede vormt een directe bedreiging voor ieder vorm van e-commerce.
Als snel na de invoering van DNS realiseerde men zich deze kwetsbaarheid van het DNS (1990: Steven M. Belovin [2]). Het rapport daarover is vervolgens 5 jaar geheim gehouden uit angst voor grootschalige verlammingen van het toenmalige Internet. Ook was de groei van het Internet dusdanig dat niemand tijd had om na te denken over beveiliging. Alle prioriteit werd gegeven aan het draaiende houden van het systeem en aan het werk om de groei op te vangen (met groei percentages van 20 to 30% per maand geen sinecure). Pas in 1995 is er, om iets aan de problemen te doen, een extensie voor DNS voorgesteld: het secure domain name system (DNSSEC). DNSSEC gebruikt digitale handtekeningen (signatures) om antwoorden te authenticeren en misbruik te detecteren. Als een signature niet klopt, wordt de informatie die hierbij hoort weggegooid. Zodoende zorgt DNSSEC ervoor dat bovengenoemde security issues worden opgelost, maar het introduceert tegelijkertijd weer nieuwe problemen, DNSSEC
- is CPU intensie
- zorgt voor toename in de grootte van zonefiles (met een factor 3-5)
- zorgt voor toename van de communicatie tussen registries en registrars (zogenaamde "key management")
CPU intensief
NLnet Labs heeft onderzoek gedaan naar de deployment van DNSSEC. Hoewel DNSSEC een veel CPU intensiever is dan DNS zal dit waarschijnlijk niet veel problemen op gaan leveren. Computers worden immers steeds sneller en de thuisgebruiker hoeft alleen digitale handtekeningen te valideren (iets dat minder moeite kost dan het creeren van digitale handtekeningen). De zonefiles worden van te voren voorzien van hun signatures. Zoals bijvoorbeeld de .nl zone, bestaande uit 600.000 domeinen. Als heel .nl DNSSEC zou gebruiken zouden er 600.000 publieke sleutels (public keys) moeten worden gemaakt, alsmede de 600.000 bijbehorende signatures. Dit proces is vrij intensief, maar NLnet Labs heeft aangetoond dat dit voor de meeste zones op het Internet haalbaar is. Zelf .com (met 30 miljoen domeinen veruit de grootste zones van het Internet) heeft laten zien dat het signen van hun zone haalbaar is.
Zeer grote zonefiles
Ten gevolge van DNSSEC worden zonefiles groter, een factor 3 tot 5. Hele grote zonefiles zouden hierdoor tot onhandelbare proporties kunnen groeien. Bijkomend probleem is dat een DNSSEC zonefile gesorteerd moet worden, wat ook weer tot onoplosbare computercapaciteits problemen zou kunnen leiden. Maar, ook hier is vastgesteld dat dit zelfs voor de allergrootste zones met de hedendaagse (64-bit) systemen opgelost kan worden. DNSSEC zones zullen bovendien regelmatig van hernieuwde signatures moeten worden voorzien, aangezien deze signatures een gelimiteerde levensduur hebben. Dit zogenaamde resignen blijkt te kunnen in 5% van de originele signtijd en zal naar verwachting dus veel minder problemen opleveren. Het is met de standaard tools, op een desktop PC al mogelijk om de .nl zone twee keer per dag te resignen.
Key management
Een derde en minder eenvoudig oplosbaar probleem van DNSSEC is het key management. Hieronder vallen private key procedures en de procedures die beschrijven hoe public keys met de registry uitgewisseld dienen te worden. Zoals met alle public/private key crypto systemen is het van het uiterste belang, dat een private key geheim blijft. Aan de andere kant moet een private key ook beschikbaar zijn om signatures te creeeren. Deze situatie zorgt voor een spanningsveld waarvoor nog geen adequate oplossing is gevonden.
Verder bestaat key management ook uit procedures die vastleggen hoe een public key gesignd moet worden door de registry. Om duidelijk te maken waarom dat een moeilijk probleem is zal ik eerst wat dieper ingaan op de structuur van DNSSEC.
In DNS (en dus ook in DNSSEC) bestaat er een parent/child relatie tussen
domeinen (zie Figuur 1); simpel gezegd is .nl de parent van ieder .nl domain
(bijvoorbeeld miek.nl). En miek.nl is dan een child van .nl. Ook .nl is zelf
weer een child en wel van '.' (root). In DNSSEC creeert elke zone een eigen
public key, de zogenaamde zone signing key. Met deze zone signing key worden de
signatures gemaakt over alle informatie van die zone. Dus wordt alle informatie
in die zone beschermd door deze zone key (zie ook Figuur 2).
Natuurlijk moet ook die zone signing key zelf weer beveiligd zijn. Dit wordt normaliter in DNSSEC gedaan door de parent deze key te laten signeren. (er zijn ook andere methoden, zoals bv het in de Staats Courant publiceren en vervolgens hard configureren van de public key bij de resolver).
De zone key van miek.nl wordt dus gesignd door de zone key van .nl. Om alle DNSSEC zones van .nl te verifieren is slecht de zone key van .nl nodig. Wanneer deze zone key nu buiten het DNS om en op een veilige manier bij de thuisgebruiker kan worden afgeleverd, zal men instaat zijn een secure view te hebben op .nl.
In het ideale geval zal men de public key van de "root" zone thuis hebben en is er een secure view op het gehele Internet mogelijk. Na de invoer van DNSSEC signt "root" de zone key van .nl en .nl signt op haar beurt de public key van miek.nl. Dit process heet de "chain of trust" en kan gezien worden het grote voordeel van DNSSEC: 1 zone key is genoeg om alle signatures te kunnen verfivieren.
In de originele DNSSEC specificatie (RFC 2535 [4]) waren er 4 stappen nodig om de public key van een child bij de parent te krijgen (Figuur 3). Dit leverde te veel interactie op tussen de parent en child. De hoeveelheid administratie die nodig is om dit op een veilige manier te doen is ongekend en zal voor vrijwel alle TLDs (Top Level Domain, hieronder vallen .com, .org, .net, .etc.) tot onoverkomenlijke problemen leiden. NLnet Labs heeft heeft een voorstel gedaan om de key interactie efficienter te laten verlopen. Alleen bleek dit vast te lopen op bepaalde details in het DNS. Een van die details was dat er signatures ontstonden die er weliswaar identiek uitzagen, maar verschillende semantische betekenissen hadden. Later is dit voorstel in een andere vorm opnieuw ter stemming gebracht. Dit zogenaamde Delegation Signer (DS) model van Olufar Gudmanson heeft de goede punten van het NLnet Labs proposal in zich, maar omzeilt de problemen (Zie figuur 4). Deze DS draft is nu in last call bij de IETF en zal heel waarschijnlijk binnenkort geaccepteerd worden als een RFC. Dankzij DS zal het administratief mogelijk worden om DNSSEC uit te rollen in grote zones.
DNSSEC in .nl (.nl.nl experiment)
Uiteindelijk heeft het tot 2000 geduurd voordat de tools die DNSSEC protocol implementeren beschikbaar kwamen. En ook nu moet er weer gewacht worden voordat de tools die DS aankunnen klaar zijn. Ondertussen is NLnet Labs bezig met het opzetten van een schaduw registry voor DNSSEC in .nl [5]. In deze registry kunnen .nl domein houders hun domein laten registeren om deze secure te laten maken. De opzet is van dien aard dat er straks naast de DNS-view op .nl er ook een (secure) DNSSEC-view bestaat. Het is de bedoeling dat deze registry eind juni geheel operationeel zal zijn. (Mits de DNSSEC+DS software tijdig beschikbaar komt (1)). Het eerdere .nl.nl experiment waar al secure .nl.nl domeinen konden worden geregistreerd wordt dan afgesloten. Dankzij dit .nl.nl experiment is overigens duidelijk geworden dat DNSSEC RFC2535-style nooit gerealiseerd zou kunnen worden op TLD niveau: de communicatie overhead was gewoon te groot.
In de loop van 2002 zal duidelijk worden of dit schaduw experiment een succes wordt. Mocht dit zo zijn dan is de verwachting dat het SIDN (de officiƫle .nl registry) niet al te lange tijd daarna DNSSEC gaat aanbieden in .nl. Nederland zou met deze registry het eerste land ter wereld zijn die DNSSEC aan het invoeren is. Wanneer DNSSEC wordt uitgerold, zal het een infrastructuur bieden waarin allerlei cryptografisch materiaal kan worden gepubliceerd. Dit biedt ongekende mogelijkheden voor IPsec, PGP en elke andere service die cryptografie gebruikt en zal hopelijk het begin zijn van een veiliger Internet.
Voetnoten
- Dit hangt af van (administratieve) procedures in het Department of Justice en/of het Pentagon. De software is af, er moet alleen nog maar een handtekening gezet worden om de betaling goed te keuren.
DNSSEC in the .nl zone mini HOWTO. The .nl.nl-experiment.
published in 2003
DNSSEC mini HOWTO
By Paul Wouters (paul@xtdnet.nl)
Introduction
This article is a translation of the article "Secure DNS, Het beveiligingen van DNS in de praktijk that appeared in C'T magazine on March 14 2003.
DNSSEC in the .nl zone
The Dutch NIC (SIDN [http://www.domain-registry.nl/]>), The European Regional Internet Registry (RIPE), and NLnetLabs have created the first toplevel secure DNS. The experiment is running its own set of nameservers to guarantee that the experiment will not interfere with the production nameservers. The project started in November of 2002 with the goal of gaining experience in running DNSSEC for a TLD Registry.
For years, the IETF has been (re)designing the successor of the current DNS system. The new protocols have been changed so often, people began to wonder if it would ever happen at all. One would think that the DNS would have been one of the first protocols to be thoroughly secured. After all, practically all communication on the internet relies on the DNS. A malicious user only needs to manipulate the DNS to get control of the communication.

The standard DNS zonefile of the domain "ct.nl", with the standard "start of authority" (SOA), nameserver (NS), mail (MX), address (A) and alias (CNAME) resource records (RR's).
Digital Signature
Standard DNS queries and answers are easily faked. If third parties can observe the DNS traffic of any machine between the enduser and the DNS server that person is using, data can be easily manipulated. DNSSEC solves this problem by using digital signatures for all records. A key-pair is generated, of which the public key is put in the DNS itself, in the form of a KEY record. The private key is then used to digitally sign all records, including the public key record. These signatures are placed in the SIG records. A malicious user can still modify the DNS data, but without the private key, the the corresponding SIG records cannot be recreated to validate the changed records. The tampering will be noticed, and the spoofed DNS answers not believed. The beauty of this setup is that the entire zone can be signed on a very secure machine and then copied onto the nameserver. Even if one has full control of the nameserver, one cannot change any DNS record without breaking the SIG record. An attacker can ofcourse still destroy the nameserver, but at least no one will be tricked to connect to an attacker's malicious network, even after a nameserver compromise.

The ct.nl zonefile, secured with DNSSEC records. (KEY material shortened for readability).
DNSSEC has another new record type, the NXT record. This record gives us the opportunity to deny the existence of a certain RR. It is not enough to just not have a certain record to make it clear the requested RR doesn't exist. We have to proof this somehow.
The NXT record for ct.nl shows the existence of the NS, SOA, MX, SIG, KEY and NXT record types. It also tells us that the next RR, in alphabetical order, is going to be www.ct.nl. The NXT record of www.ct.nl shows that there is only a CNAME, SIG and NXT record. And since its NXT record points back to ct.nl, we know it is the last name in the chain. There is no zzz.ct.nl. And all this information was digitally signed. This is the essence of DNSSEC.
But we have a few wrinkles to iron out. The DNS is a hierarchical system. The zone above our zone, the parent zone, has some information about our zone. The nameserver of the parent zone contains nameserver (NS) records to point to the responsible nameservers of its child zones. And if the nameservers of the child zone themselves have names within their own zone (for example when ns.ct.nl is an NS record for ct.nl), then it also needs to pass that information to pass along as well ; the so-called glue records. If someone manages to manipulate those records in our parent zone, then it doesn't matter how secure our own server is. They will never reach our super-secure nameserver. So this information needs to be signed as well. But our parent doesn't have our private key, so it cannot sign those records on our behalf. Somehow, we will need to give our parent some information about our key, without turning it over.
The Hint
Of course this problem isn't new to DNS. The .nl nameserver (ns.nic.nl) already has NS records for our ct.nl zone. In our case these point to ns.xtdnet.nl. However, this answer is given without setting the so-called "authoritative answer" flag. The information is provided "as is". If we would ask the same question to ns.xtdnet.nl, it would yield the same answer, but this time the "authoritative answer" flag will be set. If ns.xtdnet.nl would give different answer, we would call this a "lame server". But for DNSSEC, this hint is not enough. After all, anyone can just claim to be an authoritative server. That is why DNSSEC gives a cryptographic hint, the Delegation Signer(DS) record.
The DS record contains the id and the hash of the KEY record of the child-zone. The DS record itself is signed by the parent-zone with a SIG record. To find the ct.nl zone we ask the .nl nameserver for both the NS and DS records. We receive a hint (NS) to use ns.xtdnet.nl as nameserver and a hash of the key (DS) that as far as .nl knows, should have signed the entire ct.nl zone. Then we go to ns.xtdnet.nl and ask for the KEY record of ct.nl. We receive the KEY record, and the signature that belongs to it. We hash the KEY and compare it with the hash in the DS record we received from the .nl nameserver. If they match, we have securely landed at the authoritative nameserver for ct.nl. and we can proceed to ask it about the ct.nl domain. All the answers of ns.xtdnet.nl will be digitally signed, and cannot be tampered with.

Securely resolving www.ct.nl, using the resolv tool made by Miek Gieben.
KEY roll-overs
However, with enough time and cpu-power, all crypto can be broken eventually. That is why it is very important to change your KEY's regularly. But we cannot just change the key, because then our parent's DS record will be wrong. So how do we renew our KEY's without constantly bugging the parent to update the DS record?
The trick is to use two KEY records in our zone, a zone-signing key (ZSK) and a key-signing key (KSK). We sign all KEY records with the KSK, then sign the entire zone with the ZSK. The KSK is the key for which our parent publishes the DS record. The zone-signing key (ZSK) can be relatively small (for instance 768 bits) if we recycle it every month. We can keep the KSK for a year if we make it a bit stronger, for example 2048 bit.
So we get the following path of trust: We trust the KEY of .nl, and thus we trust the NS and DS that ns.nic.nl serves us which, when used, ends us at ns.xtdnet.nl. We verify its KSK with the DS we got, so we trust the KSK which has signed the ZSK, which has signed all the data (RR's) of which we wanted to know the signed A record www.ct.nl. And we can now recycle the ZSK without notifying the parent. Though of course we just postponed our problem. We still need to recycle the KSK after a year, and we need to securely inform our parent about the new KSK.
To start a roll-over of the KSK we first create another KSK (let's call it KSK2) and add this third KEY to the zone. Then we can inform the parent (even insecurely!) that there is a new KSK. The parent checks whether its existing KSK (for which it has a DS to verify) has signed the new KSK2. If so, it will update its DS record to point to KSK2. Once we are sure that no cached copies of KSK are scattered around the world, we can remove KSK from our zone. For .nl, NLnetlabs has created such a procedure, SECREG (Secure registration).
From DNS to DNSSEC
Our last problem is that the world will not switch in a single moment from DNS to DNSSEC. So while some subtrees, such as .nl, might have switched, others, most notable the root zone (".") itself, might still be insecure. The resolve this issue, it is possible to define "secure islands" within a insecure tree. You can define a 'trusted key' for a particular tree. This is exactly what SIDN has done for .nl
We will now describe how to secure a .nl domain using DNSSEC and SECREG. Obviously, the SECREG part only applies to .nl domains, but you can still read the procedures involved in making any zone secure.
DNSSEC is still a fast moving target. The only software that can be used to create signed zones at this time is the latest snapshot of bind9.
In that snapshot, threading is broken, so you will need to disable that with --disable-threads. Zones signed with the snapshot can however be served by any recent nameserver software package, such as the stable versions of bind8 and bind9 or nsd. The only caveat is when using bind8. If you setup a secure zone, with signatures that are valid for a month, and you forget about your expeirment and let those signatures expire, bind8 will remove the record from the zone. Bind9 will keep serving the expired record, and leave it up to the resolvers querying it to determine whether or not to pass the expired record on to the application.
To not jeopardize the regular operations of the .nl zone, two separate DNSSEC aware CC:TLD nameservers, "bakbeest.sidnl.nl" and "alpha.nlnetlabs.nl" are used. If you want to test secure resolving, be sure to use those two servers instead of the official .nl nameservers. Of course you can also use tools such as dig or resolv.pl manually. If you wish to create your own secure recursing nameserver, you need to run the latest bind9 snapshot and add a trusted-key statement for the .nl key in named.conf:
trusted-keys {
"nl." 256 3 1
"AQOtBQXOH5L/wmOt01PuxXAfSk1bw/dneWPoCyl4yi8tLCjz+DkAs0mzAAvd9XUNpYDaf5KT
ciSs9254oeiE0s0FuYbxS4nm7veZSPCgWoHULFNJtKPNeb4EEblNkAsEGagwQJoIrjlAYKx4C
En3hPwElUlVko23I5tSSPPssxrVnQ==";
};
(The above should be on a single line)
Be aware that using bind9 snapshots will often kill some of the functionality of your nameserver. Do not run this on production servers, unless you know what you're doing and have extensive monitoring enabled. Even though the development is focused on dnssec, some snapshots also broke normal resolving, so be careful. The next step is to install Net::DNS::SEC from CPAN. Some of the perl scripts we use later on depend on it. Olaf Kolkman of RIPE NCC has written a management-tool that uses it extensively. Such a tool is vital once you start securing many zones. So after we have installed all our software, we're ready to secure our domain, fnl.nl. Ideally, this would be the time to remove the signing machine from the network, and only connect it to upload the signed zones to the primary nameserver. Other methods would be even better, such as transferring the zones with a USB pen-drive. The security setup of the signer machine is left as exercise for the reader.
We will start by creating the KSK and ZSK:
$ dnssec-keygen -a RSASHA1 -b 2048 -n ZONE fnl.nl
Kfnl.nl.+005+16217
$ nssec-keygen -a RSASHA1 -b 768 -n ZONE fnl.nl
Kfnl.nl.+005+25541
The private keys are in the files with extension .private. The public keys are in the files with extension .key. If you are creating a large amount of keys, you might need to use "-r /dev/urandom". This random source is slightly less secure, but will not block while you're waiting for new randomness to appear. It seems that, with Linux at least, the quickest way of getting more random is to move the mouse. Once we're done with the key-pair creation, we add the KEY records to the zonefile:
$ cat *key >> /var/named/fnl.nl
And after we've increased the zone's serial number, we're ready to sign the zone:
$ dnssec-signzone -o fnl.nl -k Kfnl.nl.+005+16217.key /var/named/fnl.nl Kfnl.nl.+005+25541.key
We can then copy the zonefile to our primary nameserver and reload the zone:
# rndc reload fnl.nl
(If you use RedHat, you can also use 'service named restart')
After a few minutes, your secondary nameservers should also have loaded the new zone. We will use the dig command to verify this. We recommend that people who are used to using the nslookup or the host command really break that habit by now. If you preferred the output of host or nslookup over the output of dig, you can now use the +multiline option to dig (which you can even put in a .digrc file) to get output that is very similar to nslookup or host. To verify if our secondary server received the new zone, we query a key record:
$ dig +dnssec +multiline -t key fnl.nl @ns.xtdnet.nl
We should receive an answer that contains both a KEY and a SIG record. Also take a close look at the "flags" section of the dig output. The Authoritative Answer (aa) flag will say whether or not the nameserver itself was responsible for the zone (authoritative). The Authenticated Data (ad) flag tells us whether our answer was verifiably secure using the dnssec extensions. The above query, contrary to what you might except, did not set the "ad" flag. The reason for this is that the verification of data is done by a resolver, and not by the authoritative server itself. It wouldn't make much sense to verify the zone on your own disk.
Creating the DS record
When we have our secure zones loaded on our nameservers, we can ask SECREG to vouch for our domainname and request it adds a signed DS record to the .nl zone. We can request this through email (for bulk registrations) or use the web-interface:

Selecting the correct KEY for SECREG.
At this point there is no way that SECREG can determine which key is your ZSK and which is your KSK, though a draft to make a distinction is on its way. If you used a different key-size when generating the keys, you can tell the keys apart by their size. If you used an equal size, you'll have to check your key id, which is apparent from the filename it uses. Once you've told SECREG which key is the KSK, the zone will appear as "processing".

Registrant and Registrar have two days to cancel the SECREG request.
SECREG decided to add a two day waiting period so that any involved party (Registrant or Registrar) has a chance to decline the request. This is an experimental policy, that might develope into a Best Current Practice ("BCP"). If no one declines the request, your zone will be added to SECREG. The .nl zone is refreshed every weekday between 7am and 11am. This 40 MByte file is then signed by the signing machine, currently a Pentium-III 1Ghz. This process takes about two hours, and when it is done, the file size has grown to 300 Mbyte. SECREG will send emails to the parties involved if it has successfully added a zone, which means adding and signing the DS record for your zone.

The "ad" flag is set. Dig has successfully found the address of our website using DNSSEC.
KSK roll-over
The KSK and ZSK do not have an expire date - only SIG records expire. The ZSK roll-over can be done whenever you want, since the KSK will just sign whatever ZSK you have. So this rollover just consists of deleting the old key, generating a new one, and updating the KEY record in the zone.
The KSK rollover needs to happen in a co-ordinated fashion with the parent, so that the DS record can be updated. First, one needs to create a new KSK:
$ dnssec-keygen -a RSASHA1 -b 2048 -n ZONE fnl.nl
Kfnl.nl.+005+16310
The public KEY record needs to be added to the zone. Assuming the zonefile lives in /var/named/fnl.nl, issue:
$ cat Kfnl.nl.+005+16310.key >> /var/named/fnl.nl
And after we increased the serial, both KSK's need to sign the KEY records and the ZSK needs to sign the entire zone:
$ dnssec-signzone -o fnl.nl -k Kfnl.nl.+005+16217 -k Kfnl.nl.+005+16310
/var/named/fnl.nl Kfnl.nl.+005+25541
Then we need to propagate the new zone to the primary and secondary nameservers. Then we go back to the SECREG website and choose "rollover". It will present us with a TXT record containing a random challenge string. This needs to be signed using the sign.pl tool linked on that page, using the OLD KSK.
$ sign.pl
What is the full path to your private key? []
Kfnl.nl.+005+16217.private
What is your domain? []
fnl.nl
Record to sign: []
3600 IN TXT "random txt m80fN0LtmpXz2aQ"
Key path : Kfnl.nl.+005+35861.private
Domain name : fnl.nl
Record to sign : 3600 IN TXT "random txt m80fN0LtmpXz2aQ"
Is this correct (y/n)? y
fnl.nl. 3600 IN SIG TXT 5 2 3600 20030315125047 (
20030213125047 35861 fnl.nl
KHR718ehTtidLkTUbnf+NPPJymSo2jwrWTkPOvjKySFTe
v6tRoCPkvQ2pZxnn7aR3hOCrMAWmwa7WCUJ4GzdPJD2fx
M0zYkH722ewhVmayyZTTgGQ81cpVmbag/95/OR )

Using the sign.pl tool and our old KSK, we have signed the random TXT record as proof that are allowed to do a KSK roll-over.
If the signature is correct, SECREG knows we are the holder of the old KSK key, and that we are authorized to perform a key roll-over. SECREG will update the DS record, which will be published when the .nl zone gets reloaded. Our roll-over is complete.
The old KSK might still be in various caches on the net, so you should at least keep it for as long as its TTL was. Only when that time has past, can the old KSK be removed from the zone. Olaf Kolkman's maintenance tool does an excellent job of managing these roll-overs.
Conclusion
The Netherlands is the first TLD with a functional DNSSEC registry. One cannot expect to find many programs that already use the extra functionality that DNSSEC offers. Because of the many changes, even very recently, of the DNSSEC protocol, this hasn't really been possible so far. DNSSEC extensions are also missing from the POSIX libraries, such as the C-library, which means that every program which wants to support DNSSEC needs to write their own dns functions. The first applications to adopt DNSSEC will likely be FreeS/WAN, the most widely deployed Linux IPsec implementation, and OpenSSH. Both tools use public key cryptography, and need to fetch and verify their own application keys. These keys can be put into the DNS, but one can only rely on it if the DNS itself is secure. And the entire situation can become quite complex, as soon as DNSSEC finds it way into DHCP client updates, dynamic dns updates or IPsec opportunistic encryption. And hopefully browsers will also soon understand DNSSEC, so that online banking can implement real DNS security, instead of advising the user "to only continue when the name of our bank appears in the address bar". We have been waiting for DNSSEC for years. Let's hope the Dutch SECREG experiment gives everyone a push in the right direction.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
DNSSEC in NL or the .nl.nl experiment
This is an older publication (from 2004).
This report gives an outline of the current status of SECREG, the Dutch experiment for introducing DNSSEC in NL.
It is written for SIDN (the people who take care of .nl) and it tries to explain what DNSSEC will mean for a registry.
Downloads are here:
Apache2 configureren/opzetten (in Dutch)
Ik beheer mijn eigen DNS en mijn eigen mail/web server op de computer die ik thuis heb staan; gewoon om te blijven leren hoe zulke zaken in elkaar steken. Ik zal hier vertellen hoe ik een site op heb gezet.
Tis wel ontzettend lang geleden sinds ik dit allemaal opgezet heb, dus ik hoop dat ik het nog juist vertel.
voorbereiding
Dit verhaal gaat er vanuit dat je een domein hebt geregistreerd en dat
er een A (address) record met de naam 'www' bestaan. Dit address
record heeft het IP adres van jouw host. Ik zal het hier over het
domein miek.nl hebben. Ik ga verder niet in op de details die je
moet regelen omdat voor elkaar te krijgen.
Als het allemaal goed werkt kun je een ping www.miek.nl geven en zien
dat je antwoord krijgt.
webserver installeren
Dit gaat gewoon via het mechanisme van de desbetreffende distributie.
Bij mij dus: apt-get install apache2
configureren
Nu moet er eea aan instellingen goed gezet worden; onder Debian/Ubuntu
heb je nu ongeveer de volgende layout in /etc/apache2:
apache2.conf
httpd.conf
ports.conf
mods-enabled/
sites-available/
sites-enabled/
conf.d/
mods-available/
ssl/
Onder debian beheer je de apache modules met de commandos a2enmod en
a2dismod. Ik zal hier niet verder ingaan op de apache modules. Dat is
een verhaal op zich.
Het aan- of uitzetten van een website gaat met a2ensite en a2dissite
respectievelijk.
/etc/apache2/apache2.conf
De laatste 2 regels van deze file luiden als volgt:
NameVirtualHost *:80
Include /etc/apache2/sites-enabled
Met het eerste statement geef ik aan dat ik websites heb draaien op port 80 op alle interfaces van mijn machine.
Het laatste statement verteld apache waar de website definities gevonden kunnen worden.
Maar goed - nu moet er dus nog eerst een site worden geconfigureerd. Dit doe je
door de configuratie dus in sites-available te zetten.
/etc/apache2/sites-available/
In deze directory heb ik een file genaamd 'miek.nl' staan, hierin wordt aan apache vertelt hoe die website geconfigureerd is:
1 <VirtualHost *:80>
2 ServerAdmin hostmaster@miek.nl
3 ServerName www.miek.nl
4 ServerAlias miek.nl
5 ServerAlias a.miek.nl
6 ServerAlias gieben.com
7 ServerAlias a.gieben.com
8 ServerAlias 80.127.17.126
9 ServerAlias 192.168.1.2
10 ServerSignature Off
11 DocumentRoot /home/miekg/miek.nl
12 LogLevel warn
13 ErrorLog /var/log/apache2/miek.nl-error.log
14 CustomLog /var/log/apache2/miek.nl-access.log combined
15 </VirtualHost>
- Start een nieuwe
virtualhostop port 80 (de http poort) - Wie is de admin?
- Wat is de officiele hostnaam voor deze server:
www.miek.nl - Een alias
- Nog een
- Idem
- Idem
- Idem, maar dan een IP nummer (weet niet of dit per se nodig is).
- Idem
- Geef geen extra informatie over de apache server (versie nummers enzo)
- Waar kun je de site op het filesystem vinden? Hier dus
/home/miekg/miek.nl. - Hoeveel logging wil je hebben
- En waar moet die logging heen
- Idem
- Einde virtual host block
a2ensite
Nu kun je met a2ensite miek.nl voor deze file een symlink creeeren
vanuit /etc/apache2/site-enabled naar /etc/apache2/site-available.
Daar moet je apache restarten en zou eea moeten gaan werken:
/etc/init.d/apache2 restart
Permissies
De apache server op Debian/Ubuntu draait als user www-data, deze user
moet wel recht hebben om de files in /home/miekg/miek.nl te kunnen
lezen!
Ik kan nu dus een /home/miekg/miek.nl/index2.html file aanmaken met de
juiste permissies:
touch /home/miekg/miek.nl/index2.html
chmod 644 /home/miekg/miek.nl/index2.html
NB: ook alle tussenliggende directories moeten bewandelbaar zijn voor de 'www-data' user, anders krijg je een 'permission denied'.
Nu moet je dus je browser naar miek.nl/index2.html kunnen wijzen
en moet je een mooi, wit scherm krijgen. Heb je dit dan kun je daarna
verder gaan met het ontwikkelen van een website.
Heb je dit niet dan kun je in /var/log/apache2/miek.nl-error.log zien
of er fout-meldingen zijn verschijnen. Eventueel kun je ook
/var/log/apache2/error.log bekijken.
puppet with git
I've worked with cfengine in the past and really like it. It really cuts down on management for the systems that used it. For my home network I thought I try something else, that something turned out to be puppet.
I must say that I already like it more than cfengine as you can write much smaller manifests.
goals
I want to centralize the management of the files in /etc and I want to keep track of changes of the file. For the management I'm going with puppet and for the versioning I choose git.
My main puppet server is called elektron.atoom.net. The first client is also elektron.atoom.net so this server is both server and client.
initial setup
First install puppet, I'm not going into much detail here. Next install git. Then:
# cd /etc/puppet
# git-init-db
So you we have created a git-repository in /etc/puppet. The default puppet install on Debian/Ubuntu places some of the following files in /etc/puppet:
files/
fileserver.conf
manifests/
puppetd.conf
puppetmasterd.conf
In files/ you place whole files you want to manage with puppet - I will come to that later. Important now are fileserver.conf, puppetd.conf and puppetmasterd.conf.
Setting up the master
The master daemon is called puppetmasterd and is controlled with the following files:
fileserver.conf:
[files]
path /etc/puppet/files
allow 192.168.1.2
allow 127.0.0.1
The path statement tells puppetmasterd that it can find the files in the /etc/puppet/files directory.
I haven't touch the file puppetmasterd.conf, and gone with my distribution's default.
The client
The client is called puppetd and uses the puppetd.conf for its configuration. The only important
change I've made is that I've added server=elektron.atoom.net to it.
Writing manifests
puppet works by reading manifests which then get 'executed' on the target system. I'm not
following the preferred set of directories as I consider those a bit overkill for my small setup.
In /etc/puppet/manifests I do have the following:
etc.pp
site.pp
site.pp is the default file that gets read by puppetmasterd, in there you specify which hosts
(called nodes in puppet) get which configuration. As I only configure 1 machine at the moment
I only have:
import "etc.pp"
node 'elektron.atoom.net' {
include etc
}
The file etc.pp defines one class: etc which I include in the configuration for elektron.atoom.net.
For my other (soon to be added) machine called "foton" I will need another node-statement. I needed
to put the name elektron.atoom.net in single quotes to make this work, double quotes didn't cut it
for me.
etc.pp
The file etc.pp looks like this: (I've added line numbers)
1 class etc {
2 file { "/etc":
3 source => "puppet://elektron.atoom.net/files/elektron/etc",
4 recurse => true
5 }
6
7 file { "/etc/inetd.conf": owner => root, group => root, mode => 644,
7.5 source => "puppet://elektron.atoom.net/files/elektron/etc/inetd.conf"}
8 file { "/etc/motd.tail": owner => root, group => root, mode => 644,
8.5 source => "puppet://elektron.atoom.net/files/elektron/etc/inetd.conf"}
9
10 service { inetd:
11 ensure => true,
12 pattern => "/usr/sbin/inetd",
13 subscribe => FILE["/etc/inetd.conf"]
14 }
15
16 exec { "Create /etc/motd":
17 subscribe => FILE["/etc/motd.tail"],
18 logoutput => true,
19 refreshonly => true,
20 command => "/bin/uname -snrvm > /var/run/motd; /bin/cat /etc/motd.tail >> /var/run/motd"
21 }
22 }
I will go by this line-by-line.
- 1: define a new class called
etc. - 2: The concerns the file "/etc" - which ofcourse is a directory.
- 3: This defines what to put in this directory: namely files from
/etc/puppet/files/elektron/etc. now all files in that directory will get copied to/etc. Note the source syntax uses/etc/puppetas a basedir, alltough we've specified/etc/puppet/filesinfileserver.conf. - 4:
recurseis used to say that all files in files/elektron/etc should be monited. - 7: The files are named here so that they can be references by other puppet manifests.
- 7.5: Because I redefine the file
/etc/inetd.confI must tell puppet where to find it. - 8.5: And the same here for
/etc/motd.tail. - 10: I use this to tell
puppetthat if the file/etc/inetd.confchanges the service (daeamon)inetdshould be restarted. - 13:
subscribe, watch the file/etc/inetd.conf. My personal preference is to write this with all capitals. For puppet only the first character needs to be uppercased. - 16: Now I subscribe to
/etc/motd. - 20: when the file changes puppet needs to perform the following command.
Now I only need to put my files in /etc/puppet/files/elektron/etc and
puppet will miror them in the real `/etc'. Note that ownership and permissions are also exactly copied.
versioning
As said I will be using git to version my files. This is relatively easy. First add the files
to your repository.
# cd /etc/puppet
# git-add files manifests
And then commit them:
# git-commit -a -m "committing my changes to /etc"
As git doesn't support the $Id$ tags that you might know from CVS and subversion I just
change my files to include the text string ## configured with puppet ##.
Debugging and testing
Just use:
# puppetmasterd -v
on the commandline and watch the output and correct any errors you might see.
The easiest way to debug and test puppetd was also on the commandline, with:
# puppetd -v -o
You will get a lot of output telling you what happens. You can also debug a specific puppet manifest with:
# puppetd -v -o etc.pp
