DNSSEC and E-Mail Security workshop @ SWITCH
1 Agenda and Slides
1.1 PDF versions of the slides
1.2 Slides
1.2.1 DNSSEC
1.2.2 SPF, DKIM and DMARC
1.3 DNSSEC workshop agenda
- 12:30 Welcome
- 12:45 DNSSEC in a nutshell
- 14:30 Operating a DNSSEC resolver
- 15:30 Break
- 15:45 DNSSEC signing best practices
- 16:30 DNSSEC Risk mitigation
- 17:30 End of the workshop
2 General Information
- This instructions and the slides can be found online at https://switch.dane.onl
- Please replace the placeholder characters
NNin the instructions with your participant number. You can find your participant number in the table on this page - We have prepared two Linux virtual machines in the Internet (one primary authoritative DNS server and one DNS resolver). These machines have a Debian 11 OS installed. You can reach these machines via secure shell (SSH) or via Web-Browser (Cockpit Terminal).
3 Mail and DNS-Server VMs
- Your authoritative DNS-Server:
dns.zNN.dane.onl - Text editors evailanble preinstalled on the server:
emacs,vim,nano,mg(MicroEmacs). Feel free to install other editors or software that can help you with the workshop - Preinstalled tools
tmux,dvtm - The Bash-Shell can be started with the command
bash
4 DNSSEC
4.1 Hands-On: Install DNS resolver
- Install the DNS query tools (
nslookup,dig)% apt install dnsutils
- Install the Unbound DNS resolver. DNSSEC validation is enabled by
default, there is no need to adjust the configuration
% apt install unbound
- Test the DNSSEC validation (the AD-Flag must be shown)
% dig switch.ch a @localhost ; <<>> DiG 9.16.22-Debian <<>> @localhost switch.ch a ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50512 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;switch.ch. IN A ;; ANSWER SECTION: switch.ch. 300 IN A 130.59.31.80 ;; Query time: 20 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Mar 09 09:57:10 UTC 2022 ;; MSG SIZE rcvd: 52
4.2 Hands-On: DNSSEC signatures
- Work on the DNS resolver VM
- Request the DNSSEC signature for
dnssec.works NS:$ dig @localhost dnssec.works NS +dnssec +multi
- Try to answert the following questions
- Which DNSSEC algorithm has been used to sign this zone? Find the DNSSEC algorithms in the IANA documentation IANA Domain Name System Security (DNSSEC) Algorithm Numbers
- When will the signature expire?
- When did the signature become valid?
4.3 Hands-On: Negative Trust Anchor (Unbound)
- The domain
fail01.dnssec.workshas DNSSEC validation issues
% dig fail01.dnssec.works @localhost ; <<>> DiG 9.16.27-Debian <<>> fail01.dnssec.works @localhost ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 32784 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;fail01.dnssec.works. IN A ;; Query time: 172 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Aug 29 05:35:52 UTC 2022 ;; MSG SIZE rcvd: 48
- Create a new text file in
/etc/unbound/unbound.conf.d/NTA-fail01-dnssec-works.confwith this content:
server: domain-insecure: fail01.dnssec.works
- Check the Unbound configuration for syntax errors
% unbound-checkconf unbound-checkconf: no errors in /etc/unbound/unbound.conf
- Reload the Unbound configuration
% unbound-control reload OK
- Test the Name resolution of the failing domain again, it should now resolve (but without DNSSEC validation - no AD-Flag!)
# dig fail01.dnssec.works @localhost
; <<>> DiG 9.16.27-Debian <<>> fail01.dnssec.works @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31681
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;fail01.dnssec.works. IN A
;; ANSWER SECTION:
fail01.dnssec.works. 3600 IN A 5.45.109.212
;; Query time: 364 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Aug 29 05:35:17 UTC 2022
;; MSG SIZE rcvd: 64
- Negative Trust Anchors in Unbound are not automatically removed
- In production environments, implement a system that will remove the NTA automatically after some time or once the DNSSEC issue is solved on the domain owners side
4.4 Hands-On: Configuring a BIND 9 authoritative DNS server and DNS zone
- Use the virtual lab machine (authoritative DNS Server
dns.zNN.dane.onl) - Work as user root
$ sudo -s
- Verify that the BIND 9 DNS server process is started
% systemctl status bind9
- Edit the BIND 9 configuration file
/etc/bind/named.confwith a text editor of your choice. There is a primary authoritative zone for the domainzNN.dane.onlpreconfigured% chmod +w /etc/bind/named.conf % nano /etc/bind/named.conf
- Make the zonefile
/etc/bind/zonefile.dbwriteable (chmod +w /etc/bind/zonefile.db) and open the zone file in an editor. Add the IPv6 Address record (AAAA-Record) of the server at the APEX of the zone (at the base domain name), You can get the IPv6 address of the server with the commandhostname -I. Increment the SOA serial number and save the changes.- Example AAAA-Record:
zNN.dane.onl. IN AAAA 2001:db8::1
- Example AAAA-Record:
- Check both the BIND 9 configuration file and the zone file for
syntax errors
% named-checkconf -z
- If no errors are reported, load the configuration and the new zone
file into the BIND 9 server (using
rndc)% rndc reload zNN.dane.onl
- Verify that the DNS server responds to DNS queries and contains
the new SOA serial number
$ dig @::1 zNN.dane.onl SOA
- Use an external DNS-Resolver (in this example we use Quad9) or
your own recursive resolver at
dnsr.zNN.dane.onlto resolve the IPv6 address of the server:$ dig @9.9.9.9 zNN.dane.onl AAAA
4.5 Hands-On: DNSSEC with BIND 9 inline-signing
- Use the virtual lab sever
dns.zNN.dane.onl(authoritative primary DNS) - Configure a directory for the DNSSEC keys in the BIND 9
configuration file
/etc/bind/named.conf. Make sure that the directory configured in thekey-directorystatement exists.options { directory "/etc/bind"; key-directory "keys"; }; - Create a DNSSEC key pair (ZSK and KSK) for the zone
- The parameter
-Kdefines the directory where the new key(s) will be stored
% dnssec-keygen -a RSASHA256 -b 1536 -K /etc/bind/keys -n ZONE zNN.dane.onl % dnssec-keygen -a RSASHA256 -b 2048 -K /etc/bind/keys -f KSK -n ZONE zNN.dane.onl
- The parameter
- Make sure that the BIND 9 process
bindcan read the key files, the zonefiles and the configuration files% chown -R bind:bind /etc/bind
- Activate the
inline-signingfunction for the domainzNN.dane.onl, includingauto-dnssecfor automatic DNSSEC key management:zone "zNN.dane.onl" IN { type master; file "zonefile.db"; inline-signing yes; auto-dnssec maintain; }; - Text the new configuration, reload the new configuration into the
server and have the zone DNSSEC signed:
% named-checkconf -z % rndc reconfig % rndc sign zNN.dane.onl
- Check the log files for error messages during the signing (the
command
rndc signwill never report a signing error!)% tail /var/log/daemon.log Sep 20 19:51:08 auth05 named[12822]: received control channel command 'sign zNN.dane.onl' Sep 20 19:51:08 auth05 named[12822]: zone zNN.dane.onl/IN (signed): reconfiguring zone keys Sep 20 19:51:08 auth05 named[12822]: zone zNN.dane.onl/IN (signed): next key event: 20-Sep-2021 20:51:08.845
- The new zonefile containing the DNSSEC signed zone will be
written in binary
RAWformat.- The new file will have the file extension
.signed - In addition to the new signed zone file, BIND 9 will also
create a journal file with the extension
.jnl. This file will contain the journal of all changes over time (required for incremental zone transfers of the zone). There will also be a backup of the journal file with the extension.jbk
- The new file will have the file extension
- The original zone file will not be changed!
- All changes to the zone file created through the inline-signing
process will be written to storage after approx. 15 minutes
- This can be forced with the command
rndc sync
- This can be forced with the command
- All changes to the zone file will be done in the usual way inside
the original zone file
- The SOA-Serial-number must be incremented after each change
- The SOA-Serial-number does not need to be higher than the number seen on the live server, it must just be higher than the last loaded SOA serial number.
- Add a new TXT-Record to the zone file and increment the SOA
serial number:
erhöhen
% nano zonefile.db
- Example of a TXT-Record
zNN.dane.onl. IN TXT "Hello, this is a TXT record"
- Reload the zone and inspect the log-files. Query the SOA record
of the zone and inspect the new SOA serial number value. It
should be higher than the number written in the zone file (Why?)
% rndc reload zNN.dane.onl $ dig @::1 zNN.dane.onl SOA +multi +dnssec $ dig @::1 zNN.dane.onl TXT +multi +dnssec
4.6 Hands-On: DNSSEC Chain of Trust
- To close the chain of trust, the hash of the Key-Signing-Keys
(KSK) of our zone
zNN.dane.onlmust be published as the DS-Record in the parent zonedane.onl - Create the DS-Record from the KSK file (Caution: be sure to use
the correct key file from the KSK, not the ZSK!!)
% dnssec-dsfromkey -2 /etc/bind/keys/KzNN.dane.onl.+008+NNNNN.key
- Copy the output of the command into a file and copy the file to
the trainers machine, so that the trainer can copy the data and
publish the DS record in the parent zone (use the password
dnssec-2022for the destination machine)% dnssec-dsfromkey -2 /etc/bind/keys/KzNN.dane.onl.+008+NNNNN.key > ds-NN % scp ds-NN user@dnsr.z01.dane.onl:.
- Once the DS record is published, test the zone from your DNS
resolver machine (or using a public DNS resolver) and verify that
the AD-Flag (Authentic Data) is signaling successful DNSSEC validation
resolver% dig @::1 zNN.dane.onl soa +dnssec +multi resolver% dig @1.1.1.1 zNN.dane.onl soa +dnssec +multi
5 SPF
5.1 Basic SPF config
- We work on the authoritative machine
dns.zNN.dane.onl - Query the IPv4 address of the DNS resolver/Mailserver machine
$ dig mail.zNN.dane.onl A
- Open the file
/etc/bind/zonefile.dband enter an SPF TXT record for the IPv4 address of the lab mail serverzNN.dane.onl. 60 IN TXT "v=spf1 ip4:<ip-of-mail-server> ~all"
- Increment the SOA serial number (required for BIND 9 to pick up the new zone data for inline signing)
- Check the configuration and reload the zone, test the TXT record
% named-checkconf -z % rndc reload % dig @1.1.1.1 txt zNN.dane.onl
- Login to the mail-server (which is also our DNS resolver)
- Send an e-mail using the
swakstool from the mail server (mail.zNN.dane.onl)$ swaks -t switch-training@sys4.de -s 127.0.0.1 -f user@zNN.dane.onl
5.2 Border Filter
- Add the following IP-Adresses to your SPF policy:
2001:db8::/128and192.0.2.1/32zNN.dane.onl. 60 IN TXT "v=spf1 ip4:<ip-of-mail-server> ip4:192.0.2.1 ip6:2001:db8:: ~all"
5.3 Email Service Provider / Subdomain
- Include the SPF-Policy from
_spf.sys4.deto your border filter policyzNN.dane.onl. 60 IN TXT ( "v=spf1 ip4:<ip-of-mail-server> ip4:192.0.2.1" "ip6:2001:db8:: include:_spf.sys4.de ~all" )
5.4 Delegation
- Example of a SPF policy delegation
zNN.dane.onl. 60 IN TXT "v=spf1 redirect:_spf.sys4.de ~all"
6 DKIM
- Work on the mail server (
mail.zNN.dane.onl) - Generate DKIM keys with the RSA-SHA256 algorithm
rspamadm dkim_keygen -s '223012-rsa' -b 2048 \ -d zNN.dane.onl \ -k /etc/rspamd/dkim/zNN.dane.onl-rsa.private \ > zNN.dane.onl-rsa.txt - Generate DKIM keys with the ed25519 algorithm
rspamadm dkim_keygen -s '223012-ed25519' -t ed25519 \ -d zNN.dane.onl \ -k /etc/rspamd/dkim/zNN.dane.onl-ed25519.private \ > zNN.dane.onl-ed25519.txt - Make sure that the
rspamdprocess is able to read the generated private keys - Adjust the Domain-Names used in the file
/etc/rspamd/local.d/dkim_signing.confto use your domain name.domain { zNN.dane.onl { selectors [ { path: "/etc/rspamd/dkim/zNN.dane.onl-rsa.private"; selector: "223012-rsa"; }, { path: "/etc/rspamd/dkim/zNN.dane.onl-ed25519.private"; selector: "223012-ed25519"; }, ] } } - Verify the RSpamd configuration file and restart the RSpamd service
% rspamadm configtest syntax OK % systemctl restart rspamd
- The DNS DKIM public key records can now be found in the files
zNN.dane.onl-rsa.txtandzNN.dane.onl-ed25519.txt - Copy the DKIM TXT records info the
zonefile.dbfile on the authoritative DNS server (dns.zNN.dane.onl) - Increment the SOA serial number of the zonefile, save the file,
check the configuration and the zonefile with
name-checkconf -zand reload the zone. Query the new TXT records from a public DNS resolver to make sure the DKIM public keys are visible from the Internet DNSdig @9.9.9.9 223012-rsa._domainkey.zNN.dane.onl. TXT +dnssec +multi
- Send an e-mail using the
swakstool from the mail server (mail.zNN.dane.onl)$ swaks -t switch-training@sys4.de -s 127.0.0.1 -f user@zNN.dane.onl \ --header 'From: Tessi Testinger <user@z29.dane.onl>' - The trainer will check the DKIM signature authentication results on the sys4 mail server
7 DMARC
- Work on the authoritative DNS server (
dns.zNN.dane.onl) - Add a
noneDMARC policy to your domain, reports should be senddmarc@zNN.dane.onl_dmarc.zNN.dane.onl. 60 IN TXT "v=DMARC1\; p=none\; rua=mailto:dmarc@zNN.dane.onl\;"
- Send an e-mail using the
swakstool from the mail server (mail.zNN.dane.onl)$ swaks -t switch-training@sys4.de -s 127.0.0.1 -f user@zNN.dane.onl \ --header 'From: Tessi Testinger <user@z29.dane.onl>' - The trainer will check the DMARC results on the sys4 mail server