Rob Gallagher
DNS
First steps towards DNSSEC
Apr 3rd
I recently began deploying DNSSEC within HEAnet. Things are at an early stage, but I’m hoping to have some signed zones up and running in the next few months.
For testing, I wanted to find a practical application of DNSSEC, rather than simply stating “now our zones are secure against attack A, B and C”.
RFC4255 provides exactly this, with automatic verification and trusting of SSH host keys through a combination of the SSHFP record type and DNSSEC validation. This removes the need to maintain a known_hosts file on each client, key fingerprints can simply be distributed through DNS.
I started by generating our zone signing key (ZSK) and key signing key (KSK) for the secure zone, login.heanet.ie. These are 1024bit RSASHA1 keypairs.
mkdir /etc/bind/keys cd !$ dnssec-keygen -r /dev/random -a RSASHA1 \ -b 1024 -n ZONE login.heanet.ie dnssec-keygen -r /dev/random -f KSK \ -a RSASHA1 -b 1024 -n ZONE login.heanet.ie
Then, I imported the trust anchor (KSK public part) for the zone into the DNS resolver. We are using Unbound but BIND etc. configuration is somewhat similar.
cp Klogin.heanet.ie.+005+61342.key /etc/unbound/anchors/login.heanet.ie.anchor ... vi /etc/unbound/unbound.conf ... # # login.heanet.ie test signed zone - robertg@heanet.ie 20090309 # trust-anchor-file: "/etc/unbound/anchors/login.heanet.ie.anchor" ...
To prepare the zone for signing, I published the ZSK and KSK public keys at the apex of the zone, ie: after NS records but before any other records are defined.
@ IN NS ns.heanet.ie. ; DNSSEC public keys $INCLUDE /etc/bind/keys/Klogin.heanet.ie.+005+01530.key ;ZSK $INCLUDE /etc/bind/keys/Klogin.heanet.ie.+005+61342.key ;KSK ; hosts charlene IN A 193.1.219.75 charlene IN AAAA 2001:770:18:2::193.1.219.75 charlene IN SSHFP 1 1 d343493a92fdd26281dddc26e90440e5504c3b1a charlene IN SSHFP 2 1 4fad90afa04a6b62371091662f88685822b07ebb
Now, to actually sign the zone! I signed the RRsets in the zone with dnssec-signzone and the ZSK and KSK keypairs we generated earlier. This produces a signed version of the zonefile, of the form zonefile.signed. The KSK (61342) is used to sign the keys we entered at the apex of the zone earlier, and the ZSK (01530) is used to sign all the other records in the zone.
dnssec-signzone -r /dev/random -o login.heanet.ie \ -k /etc/bind/keys/Klogin.heanet.ie.+005+61342.key \ login.heanet.ie /etc/bind/keys/Klogin.heanet.ie.+005+01530.key
Then, I loaded the .signed file into the authoritative nameserver.
zone "login.heanet.ie" {
type master;
file "pz/forward/login.heanet.ie.signed";
};
After doing this, it’s a good idea to check for any errors in name server log.
As a first test, I made a DNSSEC query to the resolvers. It should follow the chain of trust and securely resolve the query. The “ad” – authenticated data – flag in the flags: section of the dig output confirms that the zone data is signed and has been verified as authentic. The +dnssec option sets the DO (DNSSEC OK) bit on the query and the +multiline option is simply used for readability purposes.
dig @resolver0.heanet.ie charlene.login.heanet.ie +dnssec +multiline ; <<>> DiG 9.5.0-P2 <<>> @resolver0.heanet.ie charlene.login.heanet.ie +dnssec +multiline ; (2 servers found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42200 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 4096 ;; QUESTION SECTION: ;charlene.login.heanet.ie. IN A ;; ANSWER SECTION: charlene.login.heanet.ie. 3600 IN A 193.1.219.75 charlene.login.heanet.ie. 3600 IN RRSIG A 5 4 3600 20090429144034 ( 20090330144034 1530 login.heanet.ie. dw8qCGcHEBA8kSfv3CTr7sTM7FEJvoGyY8tz9bEgIsNK adSgG3eUfHIQ5nMFVYvg7/MEXLfhUyXmByNjPuuMhfi0 mvX4GV0z+MqIRfVBb6bH8kPBlAjdXisny4e8rhrheRwu P8FyONy88cyy5OqTattjzz8bBtMevZo4wN/KfQs= ) ;; AUTHORITY SECTION: login.heanet.ie. 3600 IN NS ns.heanet.ie. login.heanet.ie. 3600 IN RRSIG NS 5 3 3600 20090429144034 ( 20090330144034 1530 login.heanet.ie. C7C54YAIMVqp9UJfrrM56dRd2U8OB+zkxHV2G2YN0QsR 7XFZHVcBEjw/9l8r1E6yiRIyAx2P3XGWT/tAvYvssAG8 p143UAn29Gqnibf5mGzhRQFGN/huCdmFSIL7yK2jinhA rw/ZgOrVkBnWiGYNRe4BWtIhkHbcVYZ6roWXlo8= ) ;; Query time: 2 msec ;; SERVER: 2001:770:f8::c101:ba02#53(2001:770:f8::c101:ba02) ;; WHEN: Wed Apr 1 17:07:12 2009 ;; MSG SIZE rcvd: 436
Now to test the signed SSHFP records. On the client, I added the following to resolv.conf.
options edns0
Also, I edited ~/.ssh/config and added this line in the Host section
VerifyHostKeyDNS yes
When ssh'ing to a the machine with signed SSHFP records, the user should not be prompted to accept the host key, even if it is "unknown".
ssh -v heanet@charlene.login.heanet.ie OpenSSH_5.1, OpenSSL 0.9.7j 04 May 2006 ... debug1: found 2 secure fingerprints in DNS debug1: matching host key fingerprint found in DNS debug1: ssh_rsa_verify: signature correct ...
Presto! No known_hosts file. Profit! etc.. No need to maintain host keys across multiple clients, simply distribute your SSH fingerprints through DNS.
$ ls -al /home/rob/.ssh/ total 16 drwx------ 2 rob users 512 Mar 31 14:35 . drwxr-xr-x 3 rob users 512 Mar 31 14:15 .. -rw------- 1 rob users 613 Mar 31 17:23 authorized_keys -rw-r--r-- 1 rob users 120 Mar 31 14:35 config
Of course there are a number of issues. I haven't gone through the required key rollover and resigning processes, however these are reasonably straightforward and can be automated with freely available tools.
TLD monitoring
Nov 26th
Now this is a good idea, TLD monitoring with nagios.
It highlights some interesting information, such as the large amount of open resolvers.
The Law, protecting you from those scary zone transfers
Jan 17th
So in North Dakota, you can apparently be prosecuted for conducting a DNS zone transfer:
“Ritz’s behavior in conducting a zone transfer was unauthorized within the meaning of the North Dakota Computer Crime Law.â€
Interpreting that, it seems to say that you should not do a zone transfer without the expressed permission of the transferee (??) – whoever that may be. Many nameservers don’t restrict who can carry out a zone transfer, for legitimate reasons, but there’s no mechanism for explicitly getting the permission of someone in authority before doing so. Any such system would be unworkable.
But wait, there’s more, publishing the results of freely available whois data is also illegal:
“Ritz has engaged in a variety of activities without authorization on the Internet. Those activities include port scanning, hijacking computers, and the compilation and publication of Whois lookups without authorization from Network Solutions.â€
The braindead statements above came from a court course filed by a spammer against the anti-spam activist David Ritz.
Everyone needs a little Iodine..
Oct 31st
Iodine is a nifty little program to tunnel IPv4 packets over DNS (53 is the atomic number of Iodine..*arf*). It can be handy in those situations where DNS queries are allowed out from a network, but not much else.
The setup: One local FreeBSD box (the client), one Ubuntu Feisty box (the server) and control over your own domain.
We start off by installing iodine on our FreeBSD machine, there is a port available for it:
[root@akagi ~]# portinstall iodine
Unfortunately iodine isn’t available in the Ubuntu package repositories, but we can just nick the Debian package and use that instead. The server is an amd64 machine, so you’d need to fetch the right package for your architecture. Install using
wget http://ftp.ie.debian.org/debian/pool/main/i/iodine/iodine_0.4.0-3_amd64.deb dpkg -i iodine_0.4.0-3_amd64.deb
apt spat out some post-install errors due to version string mismatches – these are safe to ignore.
The next step is to delegate control of a domain to our server. This will cause all queries for the domain iotunneldom.spoofedpacket.net to go to our server iotunnel.spoofedpacket.net, where our iodine daemon lies in wait.
iotunnel 300 IN A 88.198.67.243 ... iotunneldom 300 IN NS iotunnel.spoofedpacket.net.
Now, we start the server. The iodine daemon accepts udp/53 requests and creates a tunnel interface (dns0) for the IPv4-in-DNS packets. Make sure you have the tun device available, lsmod should confirm this.
root@longcat:~# iodined -P iminurdns 192.168.0.1 iotunneldom.spoofedpacket.net Opened dns0 Setting IP of dns0 to 192.168.0.1 Setting MTU of dns0 to 1024 Opened UDP socket Listening to dns for domain iotunneldom.spoofedpacket.net Detaching from terminal...
-P specifies the password to use. The first argument is the tunnel endpoint address, choose an addressing scheme that doesn’t overlap with anything you already have – private space is a good choice. The second argument is the domain we setup earlier.
You should end up with an interface like this:
root@longcat:~# ifconfig dns0
dns0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:192.168.0.1 P-t-P:192.168.0.1 Mask:255.255.255.0
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1024 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:168 (168.0 b) TX bytes:168 (168.0 b)
Start up the client and point it at our tunnel server. Again, you’ll need some kind of tunnel device available – the generic FreeBSD kernel has one by default:
[root@akagi ~]# iodine iotunnel.spoofedpacket.net iotunneldom.spoofedpacket.net Enter password on stdin: iminurdns Opened /dev/tun0 Opened UDP socket Retrying version check... Version ok, both running 0x00000400. You are user #1 Setting IP of tun0 to 192.168.0.3 Adding route 192.168.0.3/24 to 192.168.0.3 add net 192.168.0.3: gateway 192.168.0.3 Setting MTU of tun0 to 1024 Sending queries for iotunneldom.spoofedpacket.net to iotunnel.spoofedpacket.net Detaching from terminal...
The client will then have the following interface (tun0) available:
[root@akagi ~]# ifconfig tun0 tun0: flags=8051mtu 1024 inet 192.168.0.3 --> 192.168.0.3 netmask 0xffffff00 Opened by PID 61357
Now lets pass some traffic through it, test out the tunnel by pinging the remote end:
[root@akagi ~]# ping 192.168.0.1 PING 192.168.0.1 (192.168.0.1): 56 data bytes 64 bytes from 192.168.0.1: icmp_seq=0 ttl=64 time=57.382 ms
So, iodine is relatively straightforward to setup. Once you’ve got your tunnel, there are many uses you can put it to – Run a web proxy on the server, do some port forwarding or simply route all your traffic down it. There is also the potential to obfuscate your traffic, as all anyone would see is udp/53 queries.