The Swede in the middle of Silicon Valley

Saturday, February 2, 2008

How to enable BIND with DNSSEC and Secure Dynamic Update using SIG(0)

For the last couple of days I've been struggling trying to figure out how to get DNSSEC with SDU (Secure Dynamic updates) to work using SIG(0) keys. I was almost at the edge of giving up when a colleague of mine proposed to try it out in RHEL 5.1 and file a bug report to RedHat, and so I did only to get the surprise that it worked perfectly fine.

Since I've spent so much time on this I decided to blog on how to do this. I hope someone get use of this blogpost.

First off please notice that this configuration was made using:

Red Hat Enterprise Linux Server release 5.1 (Tikanga)
Linux dl360-g5-i.mysql.com 2.6.18-53.1.6.el5 #1 SMP Wed Jan 16 03:56:43 EST 2008 i686 i686 i386 GNU/Linux
bind-chroot-9.3.3-10.el5



I can not guarantee that it will work with whatever setup you're using!

The tools used to enable DNSSEC and SDU is:

  • dnssec-keygen
  • dnssec-signzone
  • nsupdate
First off we need to configure named.conf, here's an example configuration:

options {
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";

version "secret";

querylog yes;

allow-transfer { 127.0.0.1; };

key-directory "/etc/keys";
};

logging {
channel my_security_channel {
file "/var/logs/named_log.txt" versions 20 size 40m;
print-time yes;
severity debug 2;
};

channel my_dynamic_channel {
file "/var/logs/dynamic_log.txt" versions 2 size 40m;
print-time yes;
severity debug 65535;
};

category default { my_security_channel; };

category default { my_dynamic_channel; };
category client { my_dynamic_channel; };
category config { my_dynamic_channel; };
category database { my_dynamic_channel; };
category delegation-only { my_dynamic_channel; };
category dispatch { my_dynamic_channel; };
category dnssec { my_dynamic_channel; };
category general { my_dynamic_channel; };
category lame-servers { my_dynamic_channel; };
category network { my_dynamic_channel; };
category notify { my_dynamic_channel; };
category queries { my_dynamic_channel; };
category resolver { my_dynamic_channel; };
category security { my_dynamic_channel; };
category unmatched { my_dynamic_channel; };
category update { my_dynamic_channel; };
category update-security { my_dynamic_channel; };
category xfer-in { my_dynamic_channel; };
category xfer-out { my_dynamic_channel; };

};

view "internal" {
match-clients { 127.0.0.1; };

recursion yes;
allow-recursion { localhost; };

zone "example.com" IN {
type master;
file "data/example.com.db.signed";
update-policy {
grant example.com subdomain example.com. any;
};
};
};

include "/etc/rndc.key";


This configuration is pretty straight forward and doesn't have to many elements to it but to an unknown user there might be some unknowns.

version "secret";
First off we want to make sure that a potential intruder isn't aware of which version of BIND we're using. If an intruder has knowledge about the flaws in a certain version of BIND we're taking the risk of being exploited.

key-directory "/etc/keys"
BIND needs to be aware of your private keys when doing updates, otherwise the changes you'll make will not be signed and you'll have to do a manual resign of the zone which kills the purpose of dynamic updates.

logging
When dealing with DNSSEC it's important to know what's going on, in the example configuration pretty much all logging is enabled to give us a wide picture of what kind of connections and data-transfers that's passing to and from your server. All of it isn't a necessary but logs are always more useful than one think.

view "internal"
This element isn't really necessary in this simple setup but if you have a DNS server that hosts different zones in different networks (external/internal) this is crucial to not distribute your internal zones. It also to enable the right person to get the right data.

recursion "yes"
Recursion allows clients to resolve domains and or hosts that your server isn't authoritative for. This isn't necessary in this example but can be useful.

allow-recursion { localhost };
This is yet an element which isn't necessary in this setup but it's important to know that you don't want to have recursion enabled for anyone but trusted sources. Your DNS server should only host your domains unless it's internal or intended to allow recursive traffic.

file "data/example.com.db.signed"
Usually you would probably use something like example.com.db but when signing the zone-file the name is changed to .signed there is however a flag in dnssec-signzone letting you decide the output name of the file so it's really up to you if you want to use the .signed suffix or not.

update-policy
To enable us to do dynamic updates we need to have permission to do it. The grant statements tells the BIND server what which key is allowed to change. There's multiple options for this but for now we want this key to be able to change anything.

Now that we've a configured named.conf we want to create a couple of directories for the files to be placed in. In this example we're using the chrooted package from RedHat, notice that you're setup might be different.

First of we want to create directories for the keys and log files
mkdir /var/named/chroot/var/logs
mkdir /var/named/chroot/etc/keys
Followed by that is a couple of symlinks to make our life easier when accessing files.
ln -s /var/named/chroot/etc/named.conf /etc/named.conf
ln -s /var/named/chroot/etc/keys /etc/keys
We also need to make sure that BIND has full permission of the folders, unless it has it wont be able to pick up the keys necessary.
chown -R named:named /var/named/chroot/var/logs
chown -R named:named /var/named/chroot/etc/keys
Now that we've all of the directories available we need to create a zone-file. Go to /var/named/chroot/var/named/data and open up your favorite editor. When you're in the editor you want to post the following conf:
$ORIGIN .
$TTL 3600 ; 1 hour
example.com IN SOA ns1.example.com. hostmaster.example.com (
2008020201 ; serial
7200 ; refresh
3600 ; retry
604800 ; expire
3600 ; minimum
)
NS ns1.example.com.
$ORIGIN example.com.
ns1 A 127.0.0.1
Remember that your settings may vary.

As we're finished with the zone file we need to create a couple of keys, one for DNSSEC and one for SDU. The reason why we've two different keys is because DNSSEC leverage DNSKEY while SDU uses KEY. This also adds an additional set of security by separating signing from updating.

To create the keys go to your key folder /etc/keys and execute the following commands:
dnssec-keygen -a rsasha1 -b 1024 -n zone example.com
dnssec-keygen -k -a rsasha1 -b 1024 -n zone example.com
The first command generates the keys you need to sign your zone, meanwhile the second generates the keys for the updates. When finished you'll have 4 keys named Kexample.com.+005+12345.private and .key.

What we need to do now is to add our DNSKEY and KEY to our zone file, you can either copy and paste the content in the .key files or execute the following command:
cat /etc/keys/Kexample.com.*.key >> /var/named/chroot/var/named/data/example.com.db
You'll now have two entries at the bottom of the zone file looking similar to this:
example.com. IN KEY 256 3 5 AwEAAcldVDO9D1NM7zVCOt2hrXoKJw8Vd2O37N5ykJcK2ODgDlCnXo6R lt/HjzIPZq4A04a0X/9AJVpDk8sZQP4kkbcv4WkXpmKSFJyhIW3B7b+k ouWnyPkym0EEFrSmIaKKQw4asMaH2Ei\
WBpOEWPeFWRtD2lX8YZRVm1tE Si8GH/oT
example.com. IN DNSKEY 256 3 5 AwEAActFWDC3bvmy6U5URVjz+EzmP/vbkUu8c0SUPpce3mv11DptfEo9 +BiY3A0NUPNfLXgIH1h75A6ZUPDBGApU54NsYJNo9bBPlcvWj7MA0VX6 wdPODqUNhuRfVrA8a3nuUC0PzSN1\
wC+sl396P91sWq9lYbYLjujm/nEg tREih0EB
We're now ready to sign our zone.

Go to your data directory /var/named/chroot/var/named/data/. It's now important that you sign with the correct key, compare the content in both .key keys and remember the name of the one containing the DNSKEY statement, this is the key we're going to use to sign our zone.
To sign the zone execute the following command:
dnssec-signzone -t -g -o example.com example.com.db /etc/keys/Kexample.com.+005+12345.private
This should give you an output that's similar to this:
example.com.db.signed
Signatures generated: 21
Signatures retained: 0
Signatures dropped: 0
Signatures successfully verified: 0
Signatures unsuccessfully verified: 0
Runtime in seconds: 0.114
Signatures per second: 182.734
If you get the errormessage dnssec-signzone: cannot load dnskey /etc/keys/Kexample.com.+005+26385.private: bad key type
you tried to use an incorrect key.

After running the script you'll have 3 new files in the data-directory:
  • example.com.db.signed
  • dsset-example.com
  • keyset-example.com

The one that's of interest for us is the example.com.db.signed file which should look similar to this:
$ORIGIN .
$TTL 3600 ; 1 hour
example.com IN SOA ns1.example.com. hostmaster.example.com. (
2008020202 ; serial
7200 ; refresh (2 hours)
3600 ; retry (1 hour)
604800 ; expire (1 week)
3600 ; minimum (1 hour)
)
RRSIG SOA 5 2 3600 20080304065047 (
20080203055047 51525 example.com.
TZNrgK8y35vEcDrB4pMVvf0+nV5HRcL+9gQvfxrlPV6F
rt9+8WjSQTug63G3YdpEWIPXB1hZvgovpWRrK6MsImex
Vvx8US59jJLjjQowG7DiD2XYcfg23ufgHfpNv71X0QuM
ZkyntzvGOL7wn+SgbJDglersJkbKJzFv5FJrBks= )
NS ns1.example.com.
RRSIG NS 5 2 3600 20080304054131 (
20080203054131 51525 example.com.
hTQF3MyTnlvfkvSCtUAvQltzyIo5vvo3K33cDzD+Ahc2
z9hBelkGLZu6XO0B3bvWLbzKzCFkUVjjMDtWPMnd3Srx
RGqspo1HGqvU0gT6W6OTXeevgKbcHZ0Ctt6gDF03EgEI
qmAlWlpRhWMCdgJ7XhM41fvsSE7LdiKsiX3XrE8= )
KEY 256 3 5 (
AwEAAcldVDO9D1NM7zVCOt2hrXoKJw8Vd2O37N5ykJcK
2ODgDlCnXo6Rlt/HjzIPZq4A04a0X/9AJVpDk8sZQP4k
kbcv4WkXpmKSFJyhIW3B7b+kouWnyPkym0EEFrSmIaKK
Qw4asMaH2EiWBpOEWPeFWRtD2lX8YZRVm1tESi8GH/oT
) ; key id = 17781
RRSIG KEY 5 2 3600 20080304054131 (
20080203054131 51525 example.com.
YpfIG5nM45Ty3HSpD0sGbeM84WhNCtVP9wayQPt9F6zd
6Tdu+NanfoAdiQ0oIDTd5nLToTk81sihcNClvAHPwpff
VtkQ2g+vEjJuPEL53vN6WL81Fh//a+6P8O410wxNGajC
rrYt5WI2bId8SJ+Sw0kzBgzxRoH+7F1+/O3zL2o= )
NSEC ns1.example.com. NS SOA KEY RRSIG NSEC DNSKEY
RRSIG NSEC 5 2 3600 20080304054131 (
20080203054131 51525 example.com.
rcQlAb+bS62KuNA4EpFFKpbmy+bFxw3sSZO+unB4CmM1
5PycFPbFm4m2+OQLoy20IM85ugszUsReOfCtEe/JEe6Q
eEQGm/JmFnQJ2mf5yYn4cN+DId8+FVwG6kvIcjCjmNbC
pz7NWYdM1lbeBFASIXF+es9rSg4kjSmJmS2f5Pg= )
DNSKEY 256 3 5 (
AwEAActFWDC3bvmy6U5URVjz+EzmP/vbkUu8c0SUPpce
3mv11DptfEo9+BiY3A0NUPNfLXgIH1h75A6ZUPDBGApU
54NsYJNo9bBPlcvWj7MA0VX6wdPODqUNhuRfVrA8a3nu
UC0PzSN1wC+sl396P91sWq9lYbYLjujm/nEgtREih0EB
) ; key id = 51525
RRSIG DNSKEY 5 2 3600 20080304054131 (
20080203054131 51525 example.com.
mkegJTmyMG6uEC9DkG7KUExvHOj3q2iDgaEmw7o9RB1s
ETUvwd8uteCH13TvBZ3EXMxdpEFaE4EhccYIArUlqarA
z1kzeCyslyIGS4TwsZTR94/cQY8F6Yv8cv8u+ISxSoO+
hZCLXOrQ9wyMhx82smT/NycwvLzHxtgikvWLWw4= )
$ORIGIN example.com.
ns1 A 127.0.0.1
RRSIG A 5 3 3600 20080304054131 (
20080203054131 51525 example.com.
BzvAbDGuu4rEE6kDjXehVIULkGajBJXF/B6D27k9DWIH
9MJ/vi9frE/E4jLz/frY3rHdDgtolGX05SphuEsFdmMo
G1a1yQIvfJVHY5L0Xc03qMquhsXVd5yJS5DwyxEZuxqZ
DMgeLjp0bm9M1FabOhpIcm4gQqu5JTxHo/5CEtw= )
NSEC testing A RRSIG NSEC
RRSIG NSEC 5 3 3600 20080304065047 (
20080203055047 51525 example.com.
tNNunF81mxfWJaUYtwtAkirNaV7J9cUKni7pZTL2FAMi
kmQDnTKQUP5a4nogDT9zB0gRxr0pL1lpVC3vSV7tJAl7
t7/R9DE6wO7I3VA08wTyKc2k9rS0xA06C4SPwWJGHZXl
nxxck4gAunaum+FXlqnY9YILnCbapWlCQGTkCa8= )
testing CNAME example.com.
RRSIG CNAME 5 3 3600 20080304065047 (
20080203055047 51525 example.com.
RknsWLMnxfD1ixiNezyHNLRSK/GKf19N9EXvQopa7pji
ziyqf3uYWKrJtnGQoe8vdpy8GbTrWw5ZzdxlYVe66cGC
q+saQEc9KdTOo6kDCH7WrXnY9Tko6+tPTZqM61XvyLQa
BqZKKi6bkktJv6orhbyx4KuyFdVTL/wW4h3HpUs= )
NSEC example.com. CNAME RRSIG NSEC
RRSIG NSEC 5 3 3600 20080304065047 (
20080203055047 51525 example.com.
GtV/5WFPMph2EVoPNe/fbhOxZG8sANoAw4GayI1esMqV
qTshx4yWlJt02TTtNc4AsAjk6NBi7ctQWXgtHitDeAzJ
pRhImA9RRY082WkG2GCCVCf4a/ldcf4SQt6E3C6wj+5P
iI+Uz4BjAAEHxfT7mB19m1YLo7MVhxlKe6QFW1c= )

Our zone is now signed and we can start bind.
/etc/init.d/named start
If the startup script complains about anything have a look at the permission and the config file.

As we're up and running we're now ready to run a Secure Dynamic update. For this we'll be using nsupdate.

To add a new A record execute the following:
nsupdate -d -v -k /etc/keys/Kexample.com.+005+12345.private
server 127.0.0.1
zone example.com
update add testing.example.com. 3600 A 127.0.0.1
show
send
show
Provided that you've all the permission and configuration right you should see something like this:
Creating key...
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: testing2.example.com. 3600 IN CNAME example.com. Sending update to 127.0.0.1#53 Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 61419 ;; flags: ; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 1 ;; ZONE SECTION: ;example.com. IN SOA ;; UPDATE SECTION: testing2.example.com. 3600 IN CNAME example.com. ;; SIG0 PSEUDOSECTION: . 0 ANY SIG 0 5 0 0 20080203081438 20080203080438 17781 example.com. aa+FdvAx/qpSSHEO2SHFeG+dSWgJ3L81UfLOeyxA2QkxEJV6pHrCL34k eBs2W/Ay7KPL7UMd/OAyVo1tjotbeNFkbO8O/+/sBltNttHOOYg6W4Cf gvOX3z/OwGqVQiu2OluRGsu7tN3LEl4IlgJMChIg1yJ+xl7bSaoa8QQI OmU= Reply from update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 61419 ;; flags: qr ra ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0

You've now added an A record dynamically to your zone!

If you've a look in the log-file /var/named/chroot/var/logs/dynamic_log.txt you should see something similar to this:

03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: TCP request
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: using view 'internal'
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: request is not signed
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: recursion available
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: query
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: AXFR request
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: transfer of 'example.com/IN': AXFR question section OK
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: transfer of 'example.com/IN': AXFR authority section OK
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: zone transfer 'example.com/AXFR/IN' approved
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: ns_client_attach: ref = 1
03-Feb-2008 09:13:39.364 client 127.0.0.1#48060: view internal: transfer of 'example.com/IN': AXFR started
03-Feb-2008 09:13:39.364 example.com. 3600 IN SOA ns1.example.com. hostmaster.example.com. 2008020206 7200 3600 604800 3600
03-Feb-2008 09:13:39.364 example.com. 3600 IN RRSIG SOA 5 2 3600 20080304081335 20080203071335 51525 example.com. ars67v4wWyWVuf/HPPfScgSUvGi7lX+qq0+nzMq\
8+uoeSUBkg4d8OHn6 FZ39YVVie4CQ/aV8J4aanwnrPnbuHeDEODuYr4btXpZRsF4WtsCfesyH ZhzqzKw04GS90/NNlAIedT+r0ZsCkkLR8kon4LecEyo8qPqbO3aUuX2I FgY=
03-Feb-2008 09:13:39.364 example.com. 3600 IN NS ns1.example.com.
03-Feb-2008 09:13:39.364 example.com. 3600 IN RRSIG NS 5 2 3600 20080304054131 20080203054131 51525 example.com. hTQF3MyTnlvfkvSCtUAvQltzyIo5vvo3K33cDzD+\
Ahc2z9hBelkGLZu6 XO0B3bvWLbzKzCFkUVjjMDtWPMnd3SrxRGqspo1HGqvU0gT6W6OTXeev gKbcHZ0Ctt6gDF03EgEIqmAlWlpRhWMCdgJ7XhM41fvsSE7LdiKsiX3X rE8=
03-Feb-2008 09:13:39.365 example.com. 3600 IN KEY 256 3 5 AwEAAcldVDO9D1NM7zVCOt2hrXoKJw8Vd2O37N5ykJcK2ODgDlCnXo6R lt/HjzIPZq4A04a0X/9AJVpDk8sZQP4kkbcv\
4WkXpmKSFJyhIW3B7b+k ouWnyPkym0EEFrSmIaKKQw4asMaH2EiWBpOEWPeFWRtD2lX8YZRVm1tE Si8GH/oT
03-Feb-2008 09:13:39.365 example.com. 3600 IN RRSIG KEY 5 2 3600 20080304054131 20080203054131 51525 example.com. YpfIG5nM45Ty3HSpD0sGbeM84WhNCtVP9wayQPt\
9F6zd6Tdu+NanfoAd iQ0oIDTd5nLToTk81sihcNClvAHPwpffVtkQ2g+vEjJuPEL53vN6WL81 Fh//a+6P8O410wxNGajCrrYt5WI2bId8SJ+Sw0kzBgzxRoH+7F1+/O3z L2o=
03-Feb-2008 09:13:39.365 example.com. 3600 IN NSEC ns1.example.com. NS SOA KEY RRSIG NSEC DNSKEY
03-Feb-2008 09:13:39.365 example.com. 3600 IN RRSIG NSEC 5 2 3600 20080304054131 20080203054131 51525 example.com. rcQlAb+bS62KuNA4EpFFKpbmy+bFxw3sSZO+un\
B4CmM15PycFPbFm4m2 +OQLoy20IM85ugszUsReOfCtEe/JEe6QeEQGm/JmFnQJ2mf5yYn4cN+D Id8+FVwG6kvIcjCjmNbCpz7NWYdM1lbeBFASIXF+es9rSg4kjSmJmS2f 5Pg=
03-Feb-2008 09:13:39.365 example.com. 3600 IN DNSKEY 256 3 5 AwEAActFWDC3bvmy6U5URVjz+EzmP/vbkUu8c0SUPpce3mv11DptfEo9 +BiY3A0NUPNfLXgIH1h75A6ZUPDBGApU54Ns\
YJNo9bBPlcvWj7MA0VX6 wdPODqUNhuRfVrA8a3nuUC0PzSN1wC+sl396P91sWq9lYbYLjujm/nEg tREih0EB
03-Feb-2008 09:13:39.365 example.com. 3600 IN RRSIG DNSKEY 5 2 3600 20080304054131 20080203054131 51525 example.com. mkegJTmyMG6uEC9DkG7KUExvHOj3q2iDgaEm\
w7o9RB1sETUvwd8uteCH 13TvBZ3EXMxdpEFaE4EhccYIArUlqarAz1kzeCyslyIGS4TwsZTR94/c QY8F6Yv8cv8u+ISxSoO+hZCLXOrQ9wyMhx82smT/NycwvLzHxtgikvWL Ww4=
03-Feb-2008 09:13:39.365 ns1.example.com. 3600 IN A 127.0.0.1
03-Feb-2008 09:13:39.365 ns1.example.com. 3600 IN RRSIG A 5 3 3600 20080304054131 20080203054131 51525 example.com. BzvAbDGuu4rEE6kDjXehVIULkGajBJXF/B6D27k9D\
WIH9MJ/vi9frE/E 4jLz/frY3rHdDgtolGX05SphuEsFdmMoG1a1yQIvfJVHY5L0Xc03qMqu hsXVd5yJS5DwyxEZuxqZDMgeLjp0bm9M1FabOhpIcm4gQqu5JTxHo/5C Etw=
03-Feb-2008 09:13:39.365 ns1.example.com. 3600 IN NSEC testing.example.com. A RRSIG NSEC
03-Feb-2008 09:13:39.365 ns1.example.com. 3600 IN RRSIG NSEC 5 3 3600 20080304081335 20080203071335 51525 example.com. q4HaSLSsYfO2SMw/MVnfiZsgxQ1PHCzHIaWmZG\
sZ4MkRwEYYPZN3ID1c kisMR2DUU+/5tzrJnflipOfyXTU0ecHGbIpiI8buuM/zqgHgEAxSFDJG TkA06pkqsXCfllDwh7ClLMaK/SeBdudvB2wXHNtUFfXNmmve+SHGsTE6 G+Q=
03-Feb-2008 09:13:39.365 testing.example.com. 3600 IN RRSIG NSEC 5 3 3600 20080304081335 20080203071335 51525 example.com. hVCltJNA9X2/dD77uwLzWrpmVYYvNEAkdTU4qV\
QL2+8ZHxt553DA3eFk DF5qd74L+rs2piDgVZ7L0qYzzPGO8pZAyw9HyGKF0adi40NdhVhPegy3 Tax1ThTcayuNTPE/t7nSwgfWKEDdSQVBjIZ4GFQKYIigAIGyKnmWKe2v 0JM=
03-Feb-2008 09:13:39.365 testing.example.com. 3600 IN NSEC example.com. A RRSIG NSEC
03-Feb-2008 09:13:39.365 testing.example.com. 3600 IN RRSIG A 5 3 3600 20080304081335 20080203071335 51525 example.com. FZi8W+FsfUjSur8HfMVjrn6hJEOL0ewZoKuwBJ9QA\
lsqLwYs0TRA3HGU nSN6pXypaw0d0udBo+0IQq/lW4C3FScDpNwCZqWlSmjMEpR/C7d7uPNh jUARGcq9pXdSaJ439QtSARLXNL/8tVZjCUglwYAX8/4bbPvjNOIPrOi1 NHs=
03-Feb-2008 09:13:39.365 testing.example.com. 3600 IN A 127.0.0.1
03-Feb-2008 09:13:39.365 example.com. 3600 IN SOA ns1.example.com. hostmaster.example.com. 2008020206 7200 3600 604800 3600
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: view internal: transfer of 'example.com/IN': sending TCP message of 2109 bytes
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: view internal: transfer of 'example.com/IN': AXFR ended
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: view internal: next
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: view internal: ns_client_detach: ref = 0
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: view internal: endrequest
03-Feb-2008 09:13:39.365 client 127.0.0.1#48060: read


To completely verify that you're record has been added do a zone-transfer and grep for your entry:

host -t axfr example.com localhost | grep testing

testing.example.com. 3600 IN RRSIG NSEC 5 3 3600 20080304081335 20080203071335 51525 example.com. hVCltJNA9X2/dD77uwLzWrpmVYYvNEAkdTU4qVQL2+8ZHxt553DA3eFk DF5qd74L+rs2piDgVZ7L0qYzzPGO8pZAyw9HyGKF0adi40NdhVhPegy3 Tax1ThTcayuNTPE/t7nSwgfWKEDdSQVBjIZ4GFQKYIigAIGyKnmWKe2v 0JM=
testing.example.com. 3600 IN NSEC example.com. A RRSIG NSEC
testing.example.com. 3600 IN RRSIG A 5 3 3600 20080304081335 20080203071335 51525 example.com. FZi8W+FsfUjSur8HfMVjrn6hJEOL0ewZoKuwBJ9QAlsqLwYs0TRA3HGU nSN6pXypaw0d0udBo+0IQq/lW4C3FScDpNwCZqWlSmjMEpR/C7d7uPNh jUARGcq9pXdSaJ439QtSARLXNL/8tVZjCUglwYAX8/4bbPvjNOIPrOi1 NHs=
testing.example.com. 3600 IN A 127.0.0.1
You now have a functioning DNSSEC and SDU setup.