PowerDNS Training May 2026
1 Introduction
- what is your interest in DNS/PowerDNS?
- what is your prior knowledge of DNS/PowerDNS?
- what do you want to learn about DNS/PowerDNS?
2 New terminology used in DNS
- The terms
masterandslavehave been used to describe primary and secondary authoritative DNS servers in the past.- However this terminology is wrong and misleading, for reasons discussed in the Internet Draft Terminology, Power, and Inclusive Language in Internet-Drafts and RFCs: https://tools.ietf.org/html/draft-knodel-terminology
- In this document, and in configuration examples, we are using the
new terms
primary(instead ofmaster) andsecondary(instead ofslave) whenever possible. - PowerDNS made this switch in version 4.5.0
- The old terminology will also be found in older books and standards documents (RFCs and Internet Drafts)
- DNS terminology can be confusing and is sometimes overloaded. RFC 8499 DNS terminology ( https://tools.ietf.org/html/rfc8499 ) tries to collect and document the current usage of DNS terminology.
3 Intro - DNS 1x1
4 Operating a PowerDNS authoritative Server
4.1 Authoritative DNS server deployment strategies (hidden primary, DNSSEC signer, anycast)
4.1.1 Authoritative DNS Server location
- Authoritative DNS server, such as the PowerDNS server, can be deployed in various different setups
- Classic DNS
- In a classic case, one DNS server hosts the primary (master) zones
and one or more other server host the secondary zones (slave zones)
- The zone content is maintained on the machine hosting the primary zone
- The secondary zones are synchronized via full zone transfer (AXFR) or incremental zone transfer (IXFR)
- The server should be placed in different data-center and in different autonomous systems (AS)
- There should be authoritative server near each customer population to make use of the DNS resolver round-trip-time measurement
- In classic DNS deployments, each authoritative server has one or more dedicated IP-addresses and a single domain name for the DNS service
- In a classic case, one DNS server hosts the primary (master) zones
and one or more other server host the secondary zones (slave zones)
- Anycast deployments
- To enhance resilience against certain attacks (like distributed denial of service attacks), authoritative server can be deployed with anycast addresses and routing
- In an anycast deployment, all authoritative server have the same IP address (IPv6 or IPv4) and the same domain name and are located in different routing domains / autonomous systems (AS)
- The routing protocol (BGP for Internet routing or OSPF for
internal routing) is being used to direct the DNS query to an
authoritative DNS server with optimal network distance to the
client
- Database zone storage
- Some DNS server products (such as PowerDNS, BIND 9, Microsoft DNS) support zone storage in database systems (SQL or other, like NoSQL, LDAP/Active directory)
- In such an setup, all authoritative DNS server are primaries (multi-master)
- One option is to have all DNS server to connect to the same
database (shared database setup)
- Alternatively, multiple databases can be used. The DNS data is then
either synchronized with database replication or with traditional
DNS functions such as AXFR/IXFR zone-transfer
4.1.2 Hidden Primaries
- For security reasons, it sometimes not desirable to have the zone
data write-able on a server that is exposed to the Internet
- In such situations, a hidden primary setup can be useful
- In an hidden primary setup, the server hosting the primary zone is located inside a protected network (often behind a firewall)
- The public secondaries are exposed to the Internet, but as secondaries the zone data is read-only.
- In a hidden primary setup, the delegation and in-zone NS-records
do only list the publicly reachable secondaries
- As an option, the domain name of the hidden primary can be
listed in the SOA record
MNAMEfield to support synamic updates to the zone
- As an option, the domain name of the hidden primary can be
listed in the SOA record
- For DNSSEC signed zones, the hidden master could also act as a
DNSSEC signer, adding DNSSEC data to the zones
- The precious DNSSEC keys are not exposed to the Internet
- Non-DNSSEC aware DNS management software can be augmented with DNSSEC capabilities using such a hidden signer (also known as a bump-in-the-wire signer.
4.2 Downloading, Compiling and Installing PowerDNS authoritative Server
- There are several options to install a PowerDNS authoritative DNS
server on a Linux/Unix operating system
- Using pre-compiled packages from the operating system repositories
- Using pre-compiled packages from PowerDNS B.V. The packages provided by PowerDNS B.V. might be more recent or have special features enabled that are not available in the Linux/Unix repository packages (https://repo.powerdns.com)
- Using a package manager that compiles the software from source, such as pkgsrc (http://www.pkgsrc.org) or nix (https://nixos.org/download.html)
- Compiling directly from source (https://github.com/PowerDNS)
4.2.1 Installing PowerDNS authoritative Server on Debian 11
- In the hands-on lab sessions for this training, we will be installing the PowerDNS server from the Debain 13 repositories
apt-get install pdns-server
- PowerDNS supports a range of different backend (SQL Database, BIND 9, LDAP, Lua, Pipe etc). To list the available PowerDNS backends (on Debian 13):
# apt search pdns-backend Sorting... Done Full Text Search... Done pdns-backend-bind/stable,now 4.4.1-1 amd64 [installed,automatic] BIND backend for PowerDNS pdns-backend-geoip/stable 4.4.1-1 amd64 GeoIP backend for PowerDNS pdns-backend-ldap/stable 4.4.1-1 amd64 LDAP backend for PowerDNS pdns-backend-lmdb/stable 4.4.1-1 amd64 LMDB backend for PowerDNS pdns-backend-lua2/stable 4.4.1-1 amd64 Lua2 backend for PowerDNS pdns-backend-mysql/stable 4.4.1-1 amd64 MySQL backend for PowerDNS pdns-backend-odbc/stable 4.4.1-1 amd64 UnixODBC backend for PowerDNS pdns-backend-pgsql/stable 4.4.1-1 amd64 PostgreSQL backend for PowerDNS pdns-backend-pipe/stable 4.4.1-1 amd64 pipe/coprocess backend for PowerDNS pdns-backend-remote/stable 4.4.1-1 amd64 remote backend for PowerDNS pdns-backend-sqlite3/stable 4.4.1-1 amd64 sqlite 3 backend for PowerDNS pdns-backend-tinydns/stable 4.4.1-1 amd64 tinydns compatibility backend for PowerDNS
- Select and install once or more of the available backends. In this example we're installing the MySQL/MariaDB backend:
% apt install pdns-backend-mysql
- After installation, the PowerDNS server should be up and running
with a default configuration. To check the status of the PowerDNS
service, we use
systemctl status pdns:
# systemctl status pdns.service
● pdns.service - PowerDNS Authoritative Server
Loaded: loaded (/lib/systemd/system/pdns.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-10-29 06:38:25 UTC; 14s ago
Docs: man:pdns_server(1)
man:pdns_control(1)
https://doc.powerdns.com
Main PID: 22789 (pdns_server)
Tasks: 8 (limit: 1132)
Memory: 43.6M
CPU: 139ms
CGroup: /system.slice/pdns.service
└─22789 /usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
Oct 29 06:38:25 pdns01 pdns_server[22789]: TCP server bound to [::]:53
Oct 29 06:38:25 pdns01 pdns_server[22789]: PowerDNS Authoritative Server 4.4.1 (C) 2001-2020 PowerDNS.COM BV
Oct 29 06:38:25 pdns01 pdns_server[22789]: Using 64-bits mode. Built using gcc 10.2.1 20210110.
Oct 29 06:38:25 pdns01 pdns_server[22789]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms >
Oct 29 06:38:25 pdns01 pdns_server[22789]: Creating backend connection for TCP
Oct 29 06:38:25 pdns01 pdns_server[22789]: [bindbackend] Parsing 0 domain(s), will report when done
Oct 29 06:38:25 pdns01 pdns_server[22789]: [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed
Oct 29 06:38:25 pdns01 systemd[1]: Started PowerDNS Authoritative Server.
Oct 29 06:38:25 pdns01 pdns_server[22789]: About to create 3 backend threads for UDP
Oct 29 06:38:25 pdns01 pdns_server[22789]: Done launching threads, ready to distribute questions
- The default security settings of the PowerDNS service is already
quite good, as can be seen with
systemd-analyze:
% systemd-analyze security pdns
- However some additional hardening steps are possible (optional):
MemoryDenyWriteExecute- enables a function in the memory management unit (and modern CPUs) that makes memory pages either write-able (data) or executable (program code), but never both. This prevents certain attacks, such as buffer overflow attacksumask- Files created by the PowerDNS processes can only be read or written by the PowerDNS user orroot, but not by any other userMemoryMax- Restrict the memory consumption of the PowerDNS process to 2 GB. This is usually more than enough for an authoritative server even with large zone files and prevents system instability in case of a memory leakTasksMax- restricts the number of threads (tasks) of the PowerDNS service to 20. This prevents DoS attacks through a security vulnerability that would allow and external attacker to start new threads. This setting should be monitored and adjusted to the real world scenario where PowerDNS is deloyed (number of CPU cores, network interfaces etc).
# Additional hardening for the PowerDNS systemd unit MemoryDenyWriteExecute=true UMask=077 MemoryMax=2G TasksMax=20
4.2.2 Exercise
- Login to your hands-on lab machine
pdnsNNNa.dnslab.org- Account
user - Password
PowerDNS - use
sshorhttpsfrom a web browser
- Account
- Become
root - Install the PowerDNS authoritative server from the Debian 13 package repository
- Use
systemctl edit --full pdnsto add the additional hardening configuration shown above. Add the additional lines inside the[service]section - Restart the PowerDNS service, and check with
systemctl statusthat the Task and Memory restrictions are in place
4.3 SQL Database-Backend (MySQL/MariaDB)
- MySQL (or MariaDB) is a popular backend for PowerDNS server. To install MariaDB/MySQL on Debian 13, execute:
% apt install mariadb-server
- Use
systemctl statusto verify that the database process is started
% systemctl status mysql
● mariadb.service - MariaDB 10.5.12 database server
Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-10-29 06:46:53 UTC; 23s ago
Docs: man:mariadbd(8)
https://mariadb.com/kb/en/library/systemd/
Process: 23536 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
Process: 23537 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
Process: 23539 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= || VAR=`cd /usr/bin/..; /usr/bin/galera_recovery`; [ $? -eq 0 ] && systemctl set-en>
Process: 23598 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
Process: 23600 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
Main PID: 23586 (mariadbd)
Status: "Taking your SQL requests now..."
Tasks: 12 (limit: 1132)
Memory: 81.1M
CPU: 1.092s
CGroup: /system.slice/mariadb.service
└─23586 /usr/sbin/mariadbd
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: mysql
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: performance_schema
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: Phase 6/7: Checking and upgrading tables
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: Processing databases
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: information_schema
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: performance_schema
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: Phase 7/7: Running 'FLUSH PRIVILEGES'
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23605]: OK
Oct 29 06:46:54 pdns01 /etc/mysql/debian-start[23811]: Checking for insecure root accounts.
Oct 29 06:46:55 pdns01 /etc/mysql/debian-start[23819]: Triggering myisam-recover for all MyISAM tables and aria-recover for all Aria tables
- Login to the database command line tool to create the database for
PowerDNS zones. Database-User is
root, password is empty by default
% mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 44 Server version: 10.5.12-MariaDB-0+deb11u1 Debian 13 Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]>
- Create the database
MariaDB [(none)]> CREATE DATABASE powerdns;
- Create a database user for PowerDNS and set the password (don't use the insecure password shown here, use your own secure password):
MariaDB [(none)]> GRANT ALL ON powerdns.* TO 'pdnsuser'@'localhost' IDENTIFIED BY 'securepw'; MariaDB [(none)]> FLUSH PRIVILEGES; MariaDB [(none)]> \q
- Save the SQL schema below into the file
pdns47.sql(taken from https://doc.powerdns.com/authoritative/backends/generic-mysql.html)
CREATE TABLE domains ( id INT AUTO_INCREMENT, name VARCHAR(255) NOT NULL, master VARCHAR(128) DEFAULT NULL, last_check INT DEFAULT NULL, type VARCHAR(8) NOT NULL, notified_serial INT UNSIGNED DEFAULT NULL, account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL, options VARCHAR(64000) DEFAULT NULL, catalog VARCHAR(255) DEFAULT NULL, PRIMARY KEY (id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE UNIQUE INDEX name_index ON domains(name); CREATE INDEX catalog_idx ON domains(catalog); CREATE TABLE records ( id BIGINT AUTO_INCREMENT, domain_id INT DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, type VARCHAR(10) DEFAULT NULL, content VARCHAR(64000) DEFAULT NULL, ttl INT DEFAULT NULL, prio INT DEFAULT NULL, disabled TINYINT(1) DEFAULT 0, ordername VARCHAR(255) BINARY DEFAULT NULL, auth TINYINT(1) DEFAULT 1, PRIMARY KEY (id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE INDEX nametype_index ON records(name,type); CREATE INDEX domain_id ON records(domain_id); CREATE INDEX ordername ON records (ordername); CREATE TABLE supermasters ( ip VARCHAR(64) NOT NULL, nameserver VARCHAR(255) NOT NULL, account VARCHAR(40) CHARACTER SET 'utf8' NOT NULL, PRIMARY KEY (ip, nameserver) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE TABLE comments ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(10) NOT NULL, modified_at INT NOT NULL, account VARCHAR(40) CHARACTER SET 'utf8' DEFAULT NULL, comment TEXT CHARACTER SET 'utf8' NOT NULL, PRIMARY KEY (id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE INDEX comments_name_type_idx ON comments (name, type); CREATE INDEX comments_order_idx ON comments (domain_id, modified_at); CREATE TABLE domainmetadata ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, kind VARCHAR(32), content TEXT, PRIMARY KEY (id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind); CREATE TABLE cryptokeys ( id INT AUTO_INCREMENT, domain_id INT NOT NULL, flags INT NOT NULL, active BOOL, published BOOL DEFAULT 1, content TEXT, PRIMARY KEY(id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE INDEX domainidindex ON cryptokeys(domain_id); CREATE TABLE tsigkeys ( id INT AUTO_INCREMENT, name VARCHAR(255), algorithm VARCHAR(50), secret VARCHAR(255), PRIMARY KEY (id) ) Engine=InnoDB CHARACTER SET 'latin1'; CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
- Apply the schema to the
powerdnsdatabase to initialize the database
% mysql -u root -p powerdns < pdns47.sql
4.3.1 Exercise
- Work to your hands-on lab machine
pdnsNNNa.dnslab.org - Install the MariaDB database server from the Debian 13 package repository
- Create and initialize a database for PowerDNS as shown above
4.4 PowerDNS Configuration Files
- The PowerDNS configuration file is in
/etc/powerdns/pdns.conf. The default configuration file can be overwhelming in the beginning, so we start with a clean file and build our configuration from there. We backup the original configuration files.
% mv /etc/powerdns/pdns.conf /etc/powerdns/pdns.conf.debian13 % mkdir /etc/powerdns/pdns.d.disabled % mv /etc/powerdns/pdns.d/bind.conf /etc/powerdns/pdns.d.disabled/ % touch /etc/powerdns/pdns.conf
- PowerDNS configuration can be stored either in a monolithic
(all-on-one-file) or a split configuration file (smaller
configuration files included into the main file). For a split
configuration, the configuration snippets are stored in
/etc/powerdns/pdns.d. Which configuration scheme to use is a matter of taste or sometimes demanded by a configuration management tool. This training lab sessions will use a monolithic configuration file. - Example on how to include configuration snippets from the main
configuration file
/etc/powerdns/pdns.conf:
################################# # include-dir Include *.conf files from this directory # # include-dir= include-dir=/etc/powerdns/pdns.d
- First we add the Database configuration for our MySQL/MariaDB
instance in
/etc/powerdns/pdns.conf
# MySQL / MariaDB Database access configuration launch=gmysql gmysql-socket=/run/mysqld/mysqld.sock gmysql-dbname=powerdns gmysql-user=pdnsuser gmysql-password=securepw
- Restart the PowerDNS server so that the new configuration becomes active
% systemctl restart pdns
- Install DNS look-up utilities (Debian packet
dnsutils) and test that the PowerDNS server listens on UDP port 53 and responds to DNS queries
% dig @localhost ns . ; <<>> DiG 9.16.22-Debian <<>> @localhost ns . ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 48594 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;. IN NS ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Oct 29 07:36:59 UTC 2021 ;; MSG SIZE rcvd: 28
- Here we get a DNS answer (good), it is of Return-Code
REFUSED, as PowerDNS is not authoritative for the root zone
4.4.1 Exercise
- Add the configuration for the MariaDB database to PowerDNS configuration
- Check the configuration with
pdns_server --config=check - If there are no syntax errors in the configuration file, restart the PowerDNS server
- Test with
digthat the PowerDNS server responds to DNS requests
4.5 Hosting a primary zone
- There are multiple options on how to create a new primary zone on a
PowerDNS server
- One is converting a RFC standard zone file into SQL statements that are used to provisioning the zone data into the SQL database
- Others are using a BIND 9 configuration file
named.conf(for the BIND backend),pdnsutil, dynamic updates or graphical user interfaces
- DNS zones are often stored in RFC 1035 "MASTER FILE FORMAT". This format is supported my almost all DNS server products
- We need a zone-file for our new zone. The zone-name will be
zoneNNN.dnslab.org. Our authoritative name-server is namedpdnsNNNa.dnslab.org. - Use the zone template below (replace the
NNNwith your attendee number) to create a new zone-file with the filenamezoneNNN.dnslab.orgsomewhere on the file system (proposal:/etc/powerdns/zones). Having a low TTL of 60 seconds is important in our lab environment. For production environments, the recommendation is 3600 seconds (1 hour) as a default TTL. - the period
.at the end of domain names is very important in zone files. Don't omit it. - Change the IPv4 and IPv6 Address records to match the IP-addresses of your lab server. To display the IPv4 and IPv6 addresses of a Linux-Server
% hostname -I
- The Zone Template:
$TTL 60 zoneNNN.dnslab.org. IN SOA pdnsNNNa.dnslab.org. ( hostmaster 1001 1h 30m 41d 60s ) zoneNNN.dnslab.org. IN NS pdnsNNNa.dnslab.org. zoneNNN.dnslab.org. IN A <ipv4-address-of-the-lab-server> zoneNNN.dnslab.org. IN AAAA <ipv6-address-of-the-lab-server>
- We use the PowerDNS tool
zone2sqlto convert the DNS zone from RFC1035 format into SQL statements for MariaDB/MySQL
% zone2sql --gmysql --transactions --zone-name=zoneNNN.dnslab.org --zone=zoneNNN.dnslab.org
BEGIN;
insert into domains (name,type) values ('zoneNNN.dnslab.org','NATIVE');
insert into records (domain_id, name, type,content,ttl,prio,disabled) select id ,'zoneNNN.dnslab.org', 'SOA', 'pdnsNNNa.dnslab.org hostmaster.zoneNNN.dnslab.org 1NNN 3600 1800 3542400 60', 60, 0, 0 from domains where name='zoneNNN.dnslab.org';
insert into records (domain_id, name, type,content,ttl,prio,disabled) select id ,'zoneNNN.dnslab.org', 'NS', 'pdnsNNNa.dnslab.org', 60, 0, 0 from domains where name='zoneNNN.dnslab.org';
insert into records (domain_id, name, type,content,ttl,prio,disabled) select id ,'zoneNNN.dnslab.org', 'A', '192.0.2.53', 60, 0, 0 from domains where name='zoneNNN.dnslab.org';
insert into records (domain_id, name, type,content,ttl,prio,disabled) select id ,'zoneNNN.dnslab.org', 'AAAA', '2001:db8:100::133d:1', 60, 0, 0 from domains where name='zoneNNN.dnslab.org';
1 domains were fully parsed, containing 4 records
COMMIT WORK;
- We can pipe the output of
zone2sqlinto the MySQL/MariaDB command line tool to create the zone content
% zone2sql --gmysql --transactions --zone-name=zoneNNN.dnslab.org --zone=zoneNNN.dnslab.org | mysql -u root -p powerdns
- Our PowerDNS server will now answer to queries for this zone
# dig @localhost zoneNNN.dnslab.org soa +norec ; <<>> DiG 9.16.22-Debian <<>> @localhost zoneNNN.dnslab.org soa ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50489 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;zoneNNN.dnslab.org. IN SOA ;; ANSWER SECTION: zoneNNN.dnslab.org. 60 IN SOA pdnsNNNa.dnslab.org. hostmaster.zoneNNN.dnslab.org. 1001 3600 1800 3542400 60 ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Oct 29 07:59:28 UTC 2021 ;; MSG SIZE rcvd: 101
4.6 Querying the DNS with "dig"
digis the standard tool to send DNS queries.- It replaces the older (and obsolete
nslookup) - the output of
digresembles the structure of DNS packets on the wire
- The
digoutput explained
- the DNS data is separated in sections
4.6.1 DNS Packet Header
- opcode:
query,notify,update,DSO… see IANA registry for DNS OpCodes - status/rcode:
NOERROR- the operation was successfulNXDOMAIN- the domain name requested does not exist (or is not delegated)SERVFAIL- some remote DNS server failure or DNSSEC validation failureFORMERR- the query was not correct DNSREFUSED- this server has an access control list that forbids the answer to this clientNOTIMPL- a feature used/requested that this server does not implementBADCOOKIE- Bad/missing Server Cookie
- queryid: 16bit value to sort DNS answers to DNS queries
- flags: information on the query and the answer
(see
IANA registry for DNS Header Flags)
AAauthoritative answer - answer is coming directly from an authoritative serverTCtruncated - answer does not fit into the advertised UDP packet size, please re-query over TCPRDrecursion desired - this is a query from a client machine, please provide a full complete answer (no referral please)RArecursion available - this answer comes from a DNS resolver that is willing to accept queries withRDflag set
- DNSSEC flags: AD- and CD-Flag
ADauthentic data - the DNS resolver sending this answer has performed a successful DNSSEC validation on the data. If we trust the resolver, we can trust the dataCDchecking disabled - a client asking a DNSSEC validating DNS resolver to not perform DNSSEC validation but to pass all DNSSEC data unaltered (even if the data is invalid). Used for troubleshooting DNSSEC issues.
- QUERY: number of query resource records (usually one)
- ANSWER: count of DNS resource records in the answer. Can be more than one. Can be zero if no data is available for the query.
- AUTHORITY: number of authority records in the answer. Can be a SOA-Record (for negative answers) or NS-Records for referrals or positive answers. Many modern DNS server only fill the authority section if required by the protocol to keep answer packets small
- ADDITIONAL: additional resource records that not have been requested but might help with the name resolution, and the EDNS (Extended DNS) OPT-Record (see RFC 6891 Extension Mechanisms for DNS (EDNS(0))
4.6.2 Extended DNS OPT Section
- EDNS Version 0 is the current version
- new Versions are being discussed in the IETF
- additional EDNS flags.
DO- DNSSEC OK, this DNS client supports DNSSEC records - maximum UDP answer packet size in byte as negotiated between
digand the DNS server/resolver. Current default is 4096, must be between 512 and 4096. The default changed to 1232 on DNS flag day 2020
4.6.3 Answer Section
- The answer section contains zero (if there is no data available), one or more DNS resource records that match the query
4.6.4 Authority Section
- if present, the authority section contains the authoritative name server that hosts the content delivered in the answer. For negative (NXDOMAIN/NOERROR-NODATA) answers, the authority section contains the SOA record of the zone that is authoritative for the negative answer.
4.6.5 Additional Section
- if present, the additional section contains additional DNS records that have not been explicitly requested, but might help in the name resolution process. Because the additional section can be misused in attacks, modern DNS server software minimizes the additional section data.
- If EDNS data is available, it is also in the
additional section, but
digdisplays this data in the OPT pseudo-section
4.6.6 Footer
- the footer contains the size (in bytes) of the answer packet, the DNS server that has send the answer, the time it took to receive the answer and the time and date of the DNS communication
4.6.7 sending the query to a specific DNS server/resolver
- usually
digsends the query to the DNS resolver configured in the operating system (file/etc/resolv.confon Unix/Linux) - with the
@syntax the query can be sent to other DNS servers (resolver or authoritative server)
4.6.8 sending non-recursive queries
- command line switches can alter the query sent by
dig.+multiformats the output in human readable form (wrapped for 80 column terminal)+norecsends a query withoutRDflag (non-recursive or iterative query)
4.6.9 asking for DNSSEC data
- the switch
+dnssecrequests DNSSEC data from the upstream server - the switch
+cdsends theCD(checking disabled) flag to disable upstream DNSSEC validation (if the target of the query is a DNS resolver)
4.6.10 Zone-Transfer
digcan initiate a zone transfer from an authoritative server that contains the zone database (primary or secondary server)- the data is printed in the Master Zone Format and can be used to start a new zone database file
- Example: list top level domains with DNSSEC delegation:
$ dig @f.root-servers.net AXFR . +noidnout | \ grep DS | \ grep -v RRSIG | \ cut -d "." -f 1 | \ uniq
4.7 PowerDNS Management Tools
- The PowerDNS Server comes with a couple of command line tools that help operating and maintaining the PowerDNS service
- The tools
pdns_controlandpdnsutiloverlap sometimes in their functionality.pdnsutilwas originally a tool to manage DNSSEC data in PowerDNS installations, and later morphed into a general management tool.
4.7.1 pdns_server
pdns_serveris the actual PowerDNS server binary. Besides starting the PowerDNS service, this command can be used to check the configuration file
% pdns_server --config=check Apr 28 08:31:46 Loading '/usr/lib/x86_64-linux-gnu/pdns/libgmysqlbackend.so'
- The parameter
--versionshows some help information, but also the compile time configuration of the PowerDNS server binary. This is helpful to recompile a newer PowerDNS version with the same configuration, or to check for the existence of a compile-time feature
% pdns_server --version
Apr 28 08:32:29 PowerDNS Authoritative Server 4.9.7 (C) PowerDNS.COM BV
Apr 28 08:32:29 Using 64-bits mode. Built using gcc 14.2.0.
Apr 28 08:32:29 PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
Apr 28 08:32:29 Features: libcrypto-ecdsa libcrypto-ed25519 libcrypto-ed448 libcrypto-eddsa libgeoip libmaxminddb lua lua-records PKCS#11 protobuf sodium curl scrypt
Apr 28 08:32:29 Built-in modules:
Apr 28 08:32:29 Loading '/usr/lib/x86_64-linux-gnu/pdns/libbindbackend.so'
Apr 28 08:32:29 Loading '/usr/lib/x86_64-linux-gnu/pdns/libgmysqlbackend.so'
Apr 28 08:32:29 Loaded modules: bind gmysql
Apr 28 08:32:29 Configured with: " '--build=x86_64-linux-gnu'
'--prefix=/usr'
'--includedir=${prefix}/include'
'--mandir=${prefix}/share/man'
'--infodir=${prefix}/share/info'
'--sysconfdir=/etc'
'--localstatedir=/var'
'--disable-option-checking'
'--libdir=${prefix}/lib/x86_64-linux-gnu'
'--runstatedir=/run'
'--disable-maintainer-mode'
'--disable-dependency-tracking'
'--sysconfdir=/etc/powerdns'
'--enable-systemd'
'--with-systemd=/usr/lib/systemd/system'
'--with-dynmodules=bind ldap lmdb lua2 pipe gmysql godbc gpgsql gsqlite3 geoip remote tinydns'
'--with-modules='
'--enable-ixfrdist'
'--enable-tools'
'--with-protobuf'
'--enable-unit-tests'
'--enable-lua-records'
'--enable-experimental-pkcs11'
'--enable-reproducible'
'--disable-silent-rules'
'--with-libcrypto=/usr'
'build_alias=x86_64-linux-gnu'
'CFLAGS=-g -O2 -Werror=implicit-function-declaration -ffile-prefix-map=/build/reproducible-path/pdns-4.9.7=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection' 'LDFLAGS=-Wl,-z,relro -Wl,-z,now' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2' 'CXXFLAGS=-g -O2 -ffile-prefix-map=/build/reproducible-path/pdns-4.9.7=. -fstack-protector-strong -fstack-clash-protection -Wformat -Werror=format-security -fcf-protection -DPACKAGEVERSION='\''"4.9.7-1.Debian"'\'''"
4.7.2 Tool: pdns_control
pdns_controlis the older of the two PowerDNS command line utilities. It contains many functions to maintain the running PowerDNS server
- Basic operation
- Is the server alive and listening?
% pdns_control rping PONG
- Show the uptime of the PowerDNS process
% pdns_control uptime 47 minutes
- Show the version of the running PowerDNS server
% pdns_control version 4.9.7
- Statistics
- Dump out all available statistics to the standard output
% pdns_control list backend-queries=8,corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup=0,deferred-packetcache-inserts=0,deferred-packetcache-lookup=0,dnsupdate-answers=0,dnsupdate-changes=0,dnsupdate-queries=0,dnsupdate-refused=0,incoming-notifications=0,noerror-packets=0,nxdomain-packets=0,overload-drops=0,packetcache-hit=0,packetcache-miss=6,packetcache-size=3,query-cache-hit=0,query-cache-miss=8,query-cache-size=4,rd-queries=7,recursing-answers=0,recursing-questions=0,recursion-unanswered=0,security-status=0,servfail-packets=0,signatures=0,tcp-answers=0,tcp-answers-bytes=0,tcp-queries=0,tcp4-answers=0,tcp4-answers-bytes=0,tcp4-queries=0,tcp6-answers=0,tcp6-answers-bytes=0,tcp6-queries=0,timedout-packets=0,udp-answers=7,udp-answers-bytes=338,udp-do-queries=2,udp-queries=7,udp4-answers=7,udp4-answers-bytes=338,udp4-queries=7,udp6-answers=0,udp6-answers-bytes=0,udp6-queries=0,unauth-packets=3,cpu-iowait=1296,cpu-steal=56,fd-usage=21,key-cache-size=0,latency=15,meta-cache-size=1,open-tcp-connections=0,qsize-q=0,real-memory-usage=104902656,ring-logmessages-capacity=10000,ring-logmessages-size=0,ring-noerror-queries-capacity=10000,ring-noerror-queries-size=0,ring-nxdomain-queries-capacity=10000,ring-nxdomain-queries-size=0,ring-queries-capacity=10000,ring-queries-size=0,ring-remotes-capacity=10000,ring-remotes-corrupt-capacity=10000,ring-remotes-corrupt-size=0,ring-remotes-size=0,ring-remotes-unauth-capacity=10000,ring-remotes-unauth-size=0,ring-servfail-queries-capacity=10000,ring-servfail-queries-size=0,ring-unauth-queries-capacity=10000,ring-unauth-queries-size=0,signature-cache-size=0,sys-msec=253,udp-in-errors=0,udp-noport-errors=494,udp-recvbuf-errors=0,udp-sndbuf-errors=0,uptime=1819,user-msec=119,xfr-queue=0,
- The statistics output can be piped into a monitoring tool, or it
can be processed on a shell pipe
- Here we're changing the formatting to display the statistics one line per metric
% pdns_control list | sed s/,/\\n/g
- Show a single statistics value (name of metric is taken from the
pdns_control listoutput)
% pdns_control show backend-queries
- Show the statistics on DNS query types (QTYPES)
% pdns_control qtypes NS 1 SOA 1 TXT 3 ANY 2
- Display histogram of response sizes. For optimal performance, the majority (> 99%) if responses should be below 1232 bytes. If larger responses are generated, the zone content should be optimized (large resource record reviewed etc) to prevent TCP traffic
# pdns_control respsizes 20 5 40 0 60 1 80 0 100 1 150 0 200 0 400 0 600 0 800 0 [...]
4.7.3 Tool "pdnsutil"
pdnsutilis the newer command line management tools. It contains functions to work with DNSSEC and TSIG security protocols (which will be covered on day 3 of this training).- It also contains functions to manage zones and zone content
- Zone management
- List all available zones
% pdnsutil list-all-zones zone001.dnslab.org
- Dump the zone content in RFC1035 format
# pdnsutil list-zone zone001.dnslab.org $ORIGIN . test.zone001.dnslab.org 60 IN TXT "Hello PowerDNS" zone001.dnslab.org 60 IN A 138.68.87.93 zone001.dnslab.org 60 IN AAAA 2a03:b0c0:3:d0::133d:1 zone001.dnslab.org 60 IN NS ns001a.dnslab.org. zone001.dnslab.org 60 IN SOA ns001a.dnslab.org hostmaster.zone001.dnslab.org 1001 3600 1800 3542400 60
- Show the status of a zone (including DNSSEC status)
% pdnsutil show-zone zone001.dnslab.org This is a Native zone Zone is not actively secured Metadata items: None No keys for zone 'zone001.dnslab.org'.
- Increment the SOA serial of a zone, triggering a zone transfer to all secondaries
% pdnsutil increase-serial zone001.dnslab.org SOA serial for zone zone001.dnslab.org set to 1002
- Create a new, empty zone. The new zone will have a bogus SOA records that needs to be changed
% pdnsutil create-zone pdns001.dnslab.org Creating empty zone 'pdns001.dnslab.org' % pdnsutil list-zone pdns001.dnslab.org $ORIGIN . pdns001.dnslab.org 3600 IN SOA a.misconfigured.dns.server.invalid hostmaster.pdns001.dnslab.org 0 10800 3600 604800 3600
- The command
clear-zonewill remove all DNS resource records from the zone (including NS and SOA), but will keep the zone in the configuration (and database)
% pdnsutil clear-zone pdns001.dnslab.org % pdnsutil list-zone pdns001.dnslab.org $ORIGIN .
- The command
delete-zonewill remove a zone from the configuration and the database
% pdnsutil delete-zone pdns001.dnslab.org % pdnsutil list-zone pdns001.dnslab.org Domain 'pdns001.dnslab.org' not found!
- Adding / Removing zone content
- The tool
pdnsutilcan be used to add DNS resource records to existing DNS zones. The RDATA (Data part of the record) must be in double quotes. As the shell normally removes the double quote after parsing, the double quotes"need to be escaped, for example with single quotes'. The domain name of the new record cannot be fully qualified, it should not contain the name of the zone! Here we create a TXT record with the labeltestin the zonezoneNNN.dnslab.org:
% pdnsutil add-record zone001.dnslab.org test TXT 60 '"Hello PowerDNS"' New rrset: test.zone001.dnslab.org. 60 IN TXT "Hello PowerDNS"
- The new record should be public immediately
% dig @localhost test.zone001.dnslab.org txt ; <<>> DiG 9.16.22-Debian <<>> @localhost test.zone001.dnslab.org txt ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35999 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;test.zone001.dnslab.org. IN TXT ;; ANSWER SECTION: test.zone001.dnslab.org. 60 IN TXT "Hello PowerDNS" ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Fri Oct 29 08:32:24 UTC 2021 ;; MSG SIZE rcvd: 79
- Deleting a resource record set. This will remove all records for the given domain name and record type:
% pdnsutil delete-rrset zone001.dnslab.org test txt
- Changing a resource record set
# pdnsutil replace-rrset zone001.dnslab.org test TXT 60 '"Hello PowerDNS, how are you?"' Current records for test.zone001.dnslab.org IN TXT will be replaced New rrset: test.zone001.dnslab.org. 60 IN TXT "Hello PowerDNS, how are you?"
- Editing a zone with the text editor stored in the
EDITORenvironment variable, or the defaul editor of the system. After editing, the tool displays a diff of all the changes and checks if the SOA serial has been incremented. If the SOA serial is still the same, it offers to increment it.
% export EDITOR=emacs % pdnsutil edit-zone zone001.dnslab.org Checked 5 records of 'zone001.dnslab.org', 0 errors, 0 warnings. Detected the following changes: -test.zone001.dnslab.org 60 IN TXT "Hello PowerDNS" +test.zone001.dnslab.org 60 IN TXT "Hello PowerDNS, how are you?" You have not updated the SOA record! Would you like to increase-serial? (y)es - increase serial, (n)o - leave SOA record as is, (e)dit your changes, (q)uit: y (a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit: a Adding empty non-terminals for non-DNSSEC zone
- The tool
- Checking Zones
- Check all zones for errors
% pdnsutil check-all-zones Checked 4 records of 'zone001.dnslab.org', 0 errors, 0 warnings. Checked 1 zones, 0 had errors.
- Check a single zone
% pdnsutil check-zone zone001.dnslab.org Checked 4 records of 'zone001.dnslab.org', 0 errors, 0 warnings.
4.8 Generating and Reading PowerDNS Log Files
4.8.1 Systemd Journal
- In the default configuration PowerDNS will write log information to standard-out (stdout), which will be read by systemd and send to the systemd journal. This is the command that is executed by systemd to start the PowerDNS process:
/usr/sbin/pdns_server --guardian=no --daemon=no --disable-syslog --log-timestamp=no --write-pid=no
- The PowerDNS unit name is
pdns. The command tooljournalctlcan be used to show and filter the PowerDNS log content. Here the log is shown infollowmode wherejournalctlwill block and display new log messages as they arrive:
# journalctl -fu pdns -- Journal begins at Fri 2021-10-29 06:10:29 UTC. -- Oct 29 07:34:23 pdns01 pdns_server[26503]: TCP server bound to 0.0.0.0:53 Oct 29 07:34:23 pdns01 pdns_server[26503]: TCP server bound to [::]:53 Oct 29 07:34:23 pdns01 pdns_server[26503]: PowerDNS Authoritative Server 4.4.1 (C) 2001-2020 PowerDNS.COM BV Oct 29 07:34:23 pdns01 pdns_server[26503]: Using 64-bits mode. Built using gcc 10.2.1 20210110. Oct 29 07:34:23 pdns01 pdns_server[26503]: PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2. Oct 29 07:34:23 pdns01 pdns_server[26503]: Not validating response for security status update, this is a non-release version Oct 29 07:34:23 pdns01 pdns_server[26503]: Creating backend connection for TCP Oct 29 07:34:23 pdns01 systemd[1]: Started PowerDNS Authoritative Server. Oct 29 07:34:23 pdns01 pdns_server[26503]: About to create 3 backend threads for UDP Oct 29 07:34:24 pdns01 pdns_server[26503]: Done launching threads, ready to distribute questions Oct 29 08:04:23 pdns01 pdns_server[26503]: Not validating response for security status update, this is a non-release version Oct 29 08:11:28 pdns01 pdns_server[26503]: Cache clear request for 'zone001.dnslab.org' received from operator Oct 29 08:11:37 pdns01 pdns_server[26503]: Cache clear request received from operator Oct 29 08:13:11 pdns01 pdns_server[26503]: Rediscovery was requested Oct 29 08:29:42 pdns01 pdns_server[26503]: Cache clear request received from operator Oct 29 08:30:05 pdns01 pdns_server[26503]: AXFR-out zone 'zone001.dnslab.org', client '127.0.0.1:48973', transfer initiated Oct 29 08:34:23 pdns01 pdns_server[26503]: Not validating response for security status update, this is a non-release version
- You might see the message below in the log and might be
worried. The release versions of PowerDNS as distributed by
PowerDNS B.V. will phone home to check for new security
vulnerabilities. This does not work on non-release version, such as
the version distributed in Debian 13.
Not validating response for security status update, this is a non-release version
- This function can be disabled by setting the
security-poll-suffixto an empty string in the PowerDNS configuration:
Zone name from which to query security update notifications. Setting this to an empty string disables secpoll.
4.8.2 DNS/SQL Query-Logging
- PowerDNS can log every incoming DNS query. This DNS query-logging
is CPU intensive and can slow down the DNS server operation. It is
recommended to only enable query-logging in a debugging situation
for a limited time and under direct control of the
administrator. Configuration in
pdns.conf
# Query Logging log-dns-queries=yes loglevel=6
- Example DNS query-log output
Oct 30 02:01:24 pdns01 pdns_server[28629]: Remote 127.0.0.1 wants 'zone001.dnslab.org|SOA', do = 0, bufsize = 1232 (4096): packetcache MISS Oct 30 02:04:44 pdns01 pdns_server[28629]: Remote 127.0.0.1 wants 'zone001.dnslab.org|SOA', do = 0, bufsize = 1232 (4096): packetcache MISS Oct 30 02:04:55 pdns01 pdns_server[28629]: Remote 127.0.0.1 wants 'zone001.dnslab.org|A', do = 0, bufsize = 1232 (4096): packetcache MISS Oct 30 02:05:08 pdns01 pdns_server[28629]: Remote 127.0.0.1 wants 'zone001.dnslab.org|A', do = 0, bufsize = 1232 (4096): packetcache HIT Oct 30 02:05:37 pdns01 pdns_server[28629]: Remote 127.0.0.1 wants 'zone001.dnslab.org|AAAA', do = 1, bufsize = 1232 (4096): packetcache MISS
- Log more DNS details. In the PowerDNS configuration file
log-dns-details=yes
4.8.3 Backend query logging
- In addition to DNS queries, PowerDNS can also log the database or backend queries. In the PowerDNS configuration file add
query-logging=yes
- As SQL query-logging is also CPU intensive and can hurt the DNS
servers performance, the SQL query-logging function can be
controlled at run-time from
pdns_control
% pdns_control set query-logging yes done
- Example of SQL query-logging output
Oct 30 02:29:50 pdns01 pdns_server[28849]: Remote 127.0.0.1 wants 'zone001.dnslab.org|AAAA', do = 1, bufsize = 1232 (4096): packetcache MISS Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614378640: SELECT content,ttl,prio,type,domain_id,disabled,name,auth FROM records WHERE disabled=0 and type=? and name=? Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614378640: 709 usec to execute Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614378640: 780 total usec to last row Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614420096: select kind,content from domains, domainmetadata where domainmetadata.domain_id=domains.id and name=? Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614420096: 1108 usec to execute Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614420096: 1141 total usec to last row Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614379408: SELECT content,ttl,prio,type,domain_id,disabled,name,auth FROM records WHERE disabled=0 and name=? and domain_id=? Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614379408: 1108 usec to execute Oct 30 02:29:50 pdns01 pdns_server[28849]: Query 140584614379408: 1181 total usec to last row
- Exercise
- Work on the VM machine
pdnsNNNa.dnslab.org - Enable DNS and SQL query logging
- Send some DNS queries to the PowerDNS server with
dig
- Work on the VM machine
- Solution
- Entries in the PowerDNS configuration file
## Backend SQL logging query-logging=yes ## DNS query logging log-dns-queries=yes loglevel=6 log-dns-details=yes
4.9 Secondary zones
- PowerDNS can be operated in multi-primary mode where all instances are primary server where the replication happens on the database level
- Optional PowerDNS can also recieve secondary zone content via RFC
standard DNS zone transfer (TCP)
- To transfer a zone from a non-PowerDNS server
- PowerDNS secondary mode must be enabled on a global level in the PowerDNS configuration file
# Secondary operation secondary=on
- A secondary (slave) zone can be created with
pdnsutil:
% pdnsutil create-secondary-zone <zonename> <ip-address-of-primary> Creating secondary zone 'zone001.dnslab.org', with master(s) '138.68.87.93'
- Once created, the PowerDNS server will transfer the zone via DNS zone transfer from the primary and will store the content in the database. The secondary server is now authoritative for the zone
% dig @localhost zone001.dnslab.org soa +norec ; <<>> DiG 9.16.22-Debian <<>> @localhost zone001.dnslab.org soa +norec ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26321 ;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 [...]
- On the primary server we should see the incoming zone transfer request from the secondary server
Oct 30 03:15:50 pdns01 pdns_server[29144]: Remote 165.22.233.102 wants 'zone001.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 03:15:50 pdns01 pdns_server[29144]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:44233', transfer initiated Oct 30 03:15:50 pdns01 pdns_server[29144]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:44233', allowed: client IP is in allow-axfr-ips Oct 30 03:15:50 pdns01 pdns_server[29144]: gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Oct 30 03:15:50 pdns01 pdns_server[29144]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:44233', AXFR finished
- The server hosting the secondary zone will check for new zone
content on the primary server based on the refresh timer of the
zone. As this can create a notable delay in zone content
propagation, PowerDNS also support sending DNS
NOTIFYmessages from the primary server towards all secondary servers whenever the zone content has been changed
p>
- For
NOTIFYmessages to be send on changes, the primary server must be operated in primary mode (default is native mode where noNOTIFYmessages are send)
# Operate in primary mode primary=yes
- Also, the primary zone must be set into
primarystate
% pdnsutil set-kind <zone-name> primary
NOTIFYmessages will be send out 60 seconds after a change. To triggerNOTIFYmessages manually, usepdns_control:
% pdns_control notify <zone-name>
- Example Log Output on primary
Oct 30 03:36:12 pdns01 pdns_server[29637]: Notification request to host 165.22.233.102 for domain 'zone001.dnslab.org' received from operator Oct 30 03:36:14 pdns01 pdns_server[29637]: Remote 165.22.233.102 wants 'zone001.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 03:36:14 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:45783', transfer initiated Oct 30 03:36:14 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:45783', allowed: client IP is in allow-axfr-ips Oct 30 03:36:14 pdns01 pdns_server[29637]: gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Oct 30 03:36:14 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:45783', AXFR finished Oct 30 03:36:14 pdns01 pdns_server[29637]: Removed from notification list: 'zone001.dnslab.org' to 165.22.233.102:53 (was acknowledged)
- Incremental Zone-Transfer (IXFR) can speed up zone transfer for
large zones, as only the changes are transmitted. PowerDNS does not
serve IXFR, but other DNS server products do (BIND 9, NSD, MS
Windows DNS).
- Use IXFR when PowerDNS is hosting a secondary zone where the primary zone is on a DNS server that supports outgoing IXFR.
% pdnsutil set-meta example.com IXFR 1 Set 'example.com' meta IXFR = 1
- Log-output on a PowerDNS server hosing a primary zone and receiving a IXFR zone-transfer request
Oct 30 03:53:17 pdns01 pdns_server[29637]: Notification request for domain 'zone001.dnslab.org' received from operator Oct 30 03:53:17 pdns01 pdns_server[29637]: Queued notification of domain 'zone001.dnslab.org' to 165.22.233.102:53 Oct 30 03:53:18 pdns01 pdns_server[29637]: Remote 165.22.233.102 wants 'zone001.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 03:53:18 pdns01 pdns_server[29637]: Removed from notification list: 'zone001.dnslab.org' to 165.22.233.102:53 (was acknowledged) Oct 30 03:53:18 pdns01 pdns_server[29637]: IXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', transfer initiated with serial 1005 Oct 30 03:53:18 pdns01 pdns_server[29637]: IXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', allowed: client IP is in allow-axfr-ips Oct 30 03:53:18 pdns01 pdns_server[29637]: IXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', IXFR fallback to AXFR Oct 30 03:53:18 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', transfer initiated Oct 30 03:53:18 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', allowed: client IP is in allow-axfr-ips Oct 30 03:53:18 pdns01 pdns_server[29637]: gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Oct 30 03:53:18 pdns01 pdns_server[29637]: AXFR-out zone 'zone001.dnslab.org', client '165.22.233.102:37241', AXFR finished
- Log-output on the secondary server
Oct 30 03:53:23 pdns02 pdns_server[17960]: AXFR-in zone: 'zone001.dnslab.org', primary: '138.68.87.93', zone committed with serial 1006
- Exercise
- Work on the VM machine
pdnsNNNb.dnslab.org(this is the 2nd server!) - Install PowerDNS and MariaDB on the secondary machine, using the instructions from above
- Add the IP-Address(es) (IPv6 and IPv4) of the secondary server to the zone transfer access control on the primary PowerDNS server. Change the IP addresses in the example below to match the IP addresses of the secondary server
allow-axfr-ips=2001:db8::53,192.0.2.53
- Configure the primary server to be in
primarymode, configure the zonezoneNNN.dnslab.orgto be inorimarymode - On the secondary server, check that the primary is providing a regular zone transfer (AXFR)
% dig @pdnsNNNa.dnslab.org zone001.dnslab.org axfr
- Create the secondary zone on the secondary server
- Use the
edit-zonefunction ofpdnsutilon the primary server to add the required 2nd NS record for the new secondary machine
% export EDITOR=emacs % pdnsutil edit-zone zone001.dnslab.org Checked 5 records of 'zone001.dnslab.org', 0 errors, 0 warnings. Detected the following changes: -test.zone001.dnslab.org 60 IN TXT "Hello PowerDNS" +test.zone001.dnslab.org 60 IN TXT "Hello PowerDNS, how are you?" You have not updated the SOA record! Would you like to increase-serial? (y)es - increase serial, (n)o - leave SOA record as is, (e)dit your changes, (q)uit: y (a)pply these changes, (e)dit again, (r)etry with original zone, (q)uit: a Adding empty non-terminals for non-DNSSEC zone
- This is the NS record
zoneNNN.dnslab.org 60 IN NS pdnsNNNb.dnslab.org
- Check that
NOTIFYmessages are send and received and that the zone content propagates after the change. Both PowerDNS server should host the same zone (same SOA serial number)
- Work on the VM machine
- Solution
- PowerDNS configuration file (secondary)
# MySQL / MariaDB Database access configuration launch=gmysql gmysql-socket=/run/mysqld/mysqld.sock gmysql-dbname=powerdns gmysql-user=pdnsuser gmysql-password=securepw # Server for secondary zones secondary=on
- PowerDNS configuration file (primary)
[...] primary=yes allow-axfr-ips=142.93.145.28, 2604:a880:cad:d0::d8c:4001
- Mark zone as
primaryzone on the primary server
[primary]% pdnsutil set-kind zoneNNN.dnslab.org primary
- Create the secondary zone on the secondary server
[secondary]% pdnsutil create-secondary-zone zoneNNN.dnslab.org 2a03:b0c0:3:d0::138d:3001
- On the primary-server, add the 2nd NS record to the zone
[primary]% pdnsutil edit-zone zoneNNN.dnslab.org
- Use
dig +nssearchto verify that both authoritative server have the same SOA serial
[primary]% dig zoneNNN.dnslab.org +nssearch SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. 1003 3600 1800 3542400 60 from server 142.93.145.28 in 4 ms. SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. 1003 3600 1800 3542400 60 from server 46.101.218.115 in 104 ms.
- Note: PowerDNS sends
NOTIFYmessages over IPv4 only. To change theprimaryIP addresses on a secondary zone to contain the IPv4 address of the primary, use
% pdnsutil change-secondary-zone-primary zoneNNN.dnslab.org 46.101.218.115
4.10 Dynamic DNS (DDNS), NOTIFY, & Incremental Zone Transfers
4.10.1 Dynamic Updates
- DNSIND is shorthand for a group of extensions to the original DNS
protocol.
Iis for Incremental Zone TransferNis for NOTIFYDis for Dynamic Update
- Together, the DNSIND extensions allow DNS to handle dynamic networks.
- A dynamic update allows a node to change the contents of a
zone. DNS dynamic update is the RFC standard API to change DNS
content over the network. As it is a RFC standard, it works across
different DNS server products. Use cases:
- DHCP servers, for example, can add
A,AAAAandPTRrecords to reflect the leases they give out. - Microsoft Active Directory can update the SRV records required for service discovery via dynamic updates
- DNS management systems such as VinylDNS (https://www.vinyldns.io) or Men & Mice Micetro (https://menandmice.com) can manage zone content through dynamic updates
- ACME compatible x509 certificate management systems (e.g. Let's encrypt, RFC 8555 https://datatracker.ietf.org/doc/html/rfc8555) can authenticate the domain owner with the help of dynamic DNS updates, allowing centralized automated certificate management
- DHCP servers, for example, can add
- A dynamic update can:
- Add resource records to a zone
- Delete records from a zone:
- One record
- All records of a certain type with one domain name (an RRSet)
- All records with one domain name
- A server can be configured to only accept updates from senders with the proper PSK (Pre-Shared TSIG Key).
- A sender can define update prerequisites, such as the
existence/non-existence of:
- A particular record
- Resource Records with a specific domain name and type
- A sender first tries to transmit an update to a zone's primary master.
- Most compare the SOA's
mnamefield to the NS RRSet. - If the
mnamematches an NS RR, the update is sent there. - Otherwise the update is sent to one of the domain names in the NS
RRSet (from the sender's perspective, a secondary).
p>
- Most compare the SOA's
4.10.2 Dynamic Updates and PowerDNS
- PowerDNS supports dynamic updates on a server that hosts primary
(
master) zones. Dynamic updates are disabled and can be enabled in the configuration file (global)
dnsupdate=yes
- In addition to the global configuration, dynamic updates need to be enabled on a zone
% pdnsutil set-meta example.org ALLOW-DNSUPDATE-FROM 127.0.0.0/8 Oct 30 08:03:57 gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Oct 30 08:03:57 gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Set 'example.org' meta ALLOW-DNSUPDATE-FROM = 127.0.0.0/8
- The tool
nsupdate(Debian packetdnsutils) is the standard tool to send dynamic update messages. Here an example on how to add a new record to a zone:
$ nsupdate > server 127.0.0.1 > ttl 60 > add ddns.zoneNNN.dnslab.org in TXT "This is a dynamically added DNS record" > send > quit
- The dynamic update in the PowerDNS logfile
Oct 30 08:05:45 pdns01 pdns_server[30874]: Remote 127.0.0.1 wants 'ddns.zoneNNN.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 08:05:45 pdns01 pdns_server[30874]: Remote 127.0.0.1 wants 'zoneNNN.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 08:05:45 pdns01 pdns_server[30874]: UPDATE (9824) from 127.0.0.1 for zoneNNN.dnslab.org: Processing started. Oct 30 08:05:45 pdns01 pdns_server[30874]: UPDATE (9824) from 127.0.0.1 for zoneNNN.dnslab.org: starting transaction. Oct 30 08:05:45 pdns01 pdns_server[30874]: UPDATE (9824) from 127.0.0.1 for zoneNNN.dnslab.org: Adding record ddns.zoneNNN.dnslab.org|TXT Oct 30 08:05:45 pdns01 pdns_server[30874]: UPDATE (9824) from 127.0.0.1 for zoneNNN.dnslab.org: Increasing SOA serial (1111 -> 2021103001) Oct 30 08:05:45 pdns01 pdns_server[30874]: UPDATE (9824) from 127.0.0.1 for zoneNNN.dnslab.org: Update completed, 2 changed records committed. Oct 30 08:06:26 pdns01 pdns_server[30874]: 1 domain for which we are master needs notifications Oct 30 08:06:26 pdns01 pdns_server[30874]: Queued notification of domain 'zoneNNN.dnslab.org' to 165.22.233.102:53
- The record will be published immediately and can be queried over DNS:
% dig @localhost ddns.zone001.dnslab.org txt ; <<>> DiG 9.16.22-Debian <<>> @localhost ddns.zone001.dnslab.org txt ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2483 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;ddns.zone001.dnslab.org. IN TXT ;; ANSWER SECTION: ddns.zone001.dnslab.org. 60 IN TXT "This is a dynamically added DNS record" ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Oct 30 08:06:28 UTC 2021 ;; MSG SIZE rcvd: 103
- In the default configuration PowerDNS will wait 60 seconds after a
dynamic update before sending out
NOTIFYmessages to the secondary. This configuration changes PowerDNS to send a notification to all slave servers after every update. This will speed up the propagation of changes and is very useful for ACME TLS certificate verification
% pdnsutil set-meta example.org NOTIFY-DNSUPDATE 1
- Each dynamic update will increment the SOA serial number. PowerDNS
has a SOA serial number edit policy (
SOA-EDIT-DNSUPDATE) that defines how the SOA serial number should be incrementedDEFAULT: Generate a soa serial ofYYYYMMDDNN. If the current serial is lower than the generated serial, use the generated serial. If the current serial is higher or equal to the generated serial, increase the current serial by 1.INCREASE: Increase (increment) the current serial by 1.EPOCH: Change the serial to the number of seconds since the EPOCH (seconds since 1.1.1970, also known as unixtime)SOA-EDIT: Change the serial to whatever SOA-EDIT would provide. Used for DNSSEC zones to ensure freshness of signatures on secondary (slave) serverSOA-EDIT-INCREASE: Change the serial to whateverSOA-EDITwould provide. If whatSOA-EDITprovides is lower than the current serial, increase the current serial by 1. Exception: withSOA-EDIT=INCEPTION-EPOCH, the serial is bumped to at least the current EPOCH time.
% pdnsutil set-meta example.org SOA-EDIT-DNSUPDATE INCREASE
4.10.3 Using nsupdate
nsupdateis a BIND application for sending dynamic changes to a server.- It works both interactively and non-interactively.
- In both modes, commands are one-per-line.
- The three main commands are:
update addupdate deletesend
updateprepares RRs changes,sendexecutes them.- Note: ENTER by itself is the same as
send - Non-interactively, commands come from a file or STDIN.
$ nsupdate nsupdate.input.file $ nsupdate < nsupdate.input.file
- Interactive mode:
$ nsupdate >
- The interactive command show allows changes to be reviewed before being sent.
- Here no updates have been prepared.
$ nsupdate > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 >
update addprepares a RR to be added to a zone.- All fields, except the Class must be provided.
- TTL can be provided in a separate statement.
> update add a.example.com IN A 192.0.2.1 ttl 'IN': not a valid number > update add a.example.com 3600 IN A 192.0.2.1 > ttl 3600 > update add a.example.com AAAA 2001:db8:0:deaf::1 > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: a.example.com. 3600 IN A 192.0.2.1 a.example.com. 3600 IN AAAA 2001:db8:0:deaf::1 > send
update deleteprepares RRs to be deleted.- Class is optional, and TTL, if provided, is ignored.
- Providing all fields except TTL and Class deletes one RR.
> update delete b.example.com. 1800 A 192.0.2.99 > update delete example.net. MX 15 mailserver.example.net. > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: b.example.com. 0 NONE A 192.0.2.99 example.net. 0 NONE MX 15 mailserver.example.net.
update deleteProviding the RTYPE without RDATA, deletes a RRSet.
> update delete b.example.com. AAAA > update delete c.example.com IN SRV > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: b.example.com. 0 NONE A 192.0.2.99 example.net. 0 NONE MX 15 mailserver.example.net. b.example.com. 0 ANY AAAA c.example.com. 0 ANY SRV >
update deleteOmitting RTYPE and RDATA deletes all RRSets.
> update delete d.example.com. > show Outgoing update query: ;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0 ;; flags:; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 ;; UPDATE SECTION: b.example.com. 0 NONE A 192.0.2.99 example.net. 0 NONE MX 15 mailserver.example.net. b.example.com. 0 ANY AAAA c.example.com. 0 ANY SRV d.example.com. 0 ANY ANY
- Since BIND 9.9.0, the key word
updateis optional.
> delete www.example.com. A > add www.example.com. 600 A 192.0.2.80 > add www.example.com. 600 A 192.0.2.88
send- Transmit the prepared updates to the authoritative server.- WARNING - hitting ENTER is the same as send!
> send
answer- shows the results received from the server after asend.
> send update failed: REFUSED > answer Answer: ;; ->>HEADER<<- opcode: UPDATE, status: REFUSED, id: 13117 ;; flags: qr; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0 >
prereq nxdomain <domain name>- requires that "domain name" doesn't exist (no RRs of any type).
> prereq nxdomain www.example.com > update add www.example.com 3600 CNAME example.com. > send
prereq yxdomain <domain name>- requires that "domain name" does exist.
> prereq yxdomain www.example.com > update add web.example.com 3600 CNAME www.example.com. > send
server <servername or IP> [port]- specifies the authoritative server that will receive the update.- If not set,
nsupdateusesMNAMEfrom the SOA RR and port 53. - Generally, updates should be sent to the primary authoritative server.
- If not set,
> server ns0.example.com
nsupdate -lsends all updates to localhost.- The
MNAMEis not checked, and server commands are ignored. - This is easy use, and is recommended if you are on the primary server
- The
local <IP address> [port]- specifies the outgoing IP address. This is useful for multi-homed machines, especially when IPv6 is used, and when the server limits updates to specific IPs.
> local 2001:db8:100:0:ff:aa01:42:12:feaa
zone <zonename>- specify the zone to be changed.- This is necessary when the update is an NS or glue RR to be made in the parent zone.
$ nsupdate > zone example.com. > update add ns1.subdomain.example.com. 3600 IN A 192.0.2.53 > update add ns2.subdomain.example.com. 3600 IN A 203.0.113.53 > send
4.11 Extended DNS (EDNS)
- EDNS is an extension to the original DNS protocol RFC 6891 Extension Mechanisms for DNS (EDNS(0))
- The original DNS RFCs 1034/1035 set a maximum size for DNS messages
to 512 byte to avoid costly UDP fragmentation.
- EDNS allows for larger DNS messages, usually up to 4096 byte.
- However packets larger than 1280 byte (1232 byte DNS payload) are prone to DNS fragmentation attacks (Fragmentation Considered Poisonous by Amir Herzberg, Haya Shulman, http://arxiv-export-lb.library.cornell.edu/abs/1205.4011).
- It is recommended to restrict the UDP messages to 1232 byte (see DNS Flag day 2020: https://dnsflagday.net/2020/)
udp-truncation-threshold=1232
4.12 Autoprimary (Supermaster) operation
- PowerDNS as a secondary server can automatically create a new
secondary zone when receiving a
NOTIFYfrom a trusted primary server- The primary is trusted either by IP-address or by TSIG-key
- To use this function, the
autoprimaryfunction (old namesuperslave) needs to be enabled
# Automatically fetch new zones from primary superprimary=on
- Also on the secondary, the primary is configured as a new
superprimary. This creates the trust based on the source IP address
% pdnsutil add-superprimary 2a03:b0c0:3:d0::133d:1 ns001a.dnslab.org % pdnsutil add-superprimary 138.68.87.93 ns001a.dnslab.org
- Exercise
- Configure the secondary
pdnsNNNb.dnslab.orgto havepdnsNNNa.dnslab.orgas it's autoprimary (supermaster) - Create a new zone
example.comon the primary server, configure the zone as a primary (master) zone, and populate the zone usingpdnsutilwith a correct SOA record and NS records - Check that the new zone is being created on the secondary and that all zone content is synchronized
- Configure the secondary
- Solution
- On the secpndary server
pdnsNNNb.dnslab.org, set the PowerDNS server to be in superprimary mode (in/etc/powerdns/pdns.conf)
superprimary=on
- Mark the IP-Addresses of the primary server as trusted autoprimary:
pdnsutil add-superprimary <ip-v6-address-of-primary> nsNNNa.dnslab.org pdnsutil add-superprimary <ip-v4-address-of-primary> nsNNNa.dnslab.org
- On the (super)primary, add a new zones with content
% pdnsutil create-zone example.com Creating empty zone 'example.com' Oct 30 08:34:10 No serial for 'example.com' found - zone is missing? % pdnsutil replace-rrset example.com . SOA 3600 'pdnsNNNa.dnslab.org . 1001 3600 1800 3600000 3600' Current records for example.com IN SOA will be replaced New rrset: example.com. 3600 IN SOA pdnsNNNa.dnslab.org . 1001 3600 1800 3600000 3600 % pdnsutil add-record example.com . NS 1800 "pdnsNNNa.dnslab.org" New rrset: example.com. 1800 IN NS pdnsNNNa.dnslab.org % pdnsutil add-record example.com . NS 1800 "pdnsNNNb.dnslab.org" New rrset: example.com. 1800 IN NS pdnsNNNa.dnslab.org example.com. 1800 IN NS pdnsNNNb.dnslab.org
- Configure the new zone to be a master zone
% pdnsutil set-kind example.com primary
- Log on the primary server
Oct 30 08:41:29 pdns01 pdns_server[30874]: 1 domain for which we are master needs notifications Oct 30 08:41:29 pdns01 pdns_server[30874]: Queued notification of domain 'example.com' to 165.22.233.102:53 Oct 30 08:41:30 pdns01 pdns_server[30874]: Removed from notification list: 'example.com' to 165.22.233.102:53 (was acknowledged) Oct 30 08:41:30 pdns01 pdns_server[30874]: Remote 165.22.233.102 wants 'example.com|SOA', do = 0, bufsize = 512: packetcache MISS Oct 30 08:41:30 pdns01 pdns_server[30874]: Remote 165.22.233.102 wants 'example.com|NS', do = 0, bufsize = 512: packetcache MISS Oct 30 08:41:30 pdns01 pdns_server[30874]: Remote 165.22.233.102 wants 'example.com|SOA', do = 0, bufsize = 512: packetcache HIT Oct 30 08:41:30 pdns01 pdns_server[30874]: AXFR-out zone 'example.com', client '165.22.233.102:53777', transfer initiated Oct 30 08:41:30 pdns01 pdns_server[30874]: AXFR-out zone 'example.com', client '165.22.233.102:53777', allowed: client IP is in allow-axfr-ips Oct 30 08:41:30 pdns01 pdns_server[30874]: gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Oct 30 08:41:30 pdns01 pdns_server[30874]: AXFR-out zone 'example.com', client '165.22.233.102:53777', AXFR finished Oct 30 08:41:32 pdns01 pdns_server[30874]: No master domains need notifications
- Log on the secondary
Oct 30 08:41:29 pdns02 pdns_server[19475]: Received NOTIFY for example.com from 138.68.87.93:16522 for which we are not authoritative, trying supermaster Oct 30 08:41:30 pdns02 pdns_server[19475]: Created new slave zone 'example.com' from supermaster 138.68.87.93 Oct 30 08:41:31 pdns02 pdns_server[19475]: AXFR-in zone: 'example.com', primary: '138.68.87.93', zone committed with serial 1001
- On the secpndary server
4.13 Performance tuning
- Performance tuning an authoritative DNS server requires some
experience. DNS server performance is bound to different factors
(network, hardware, database, logging configuration etc)
- Most installations do not need any performance tuning, PowerDNS on modern hardware works just fine and is fast enough
- Only start tuning if you know performance can be an issue
- Measure, don't speculate
- It is recommended to validate each performance tuning step in a
test lab that mimics the real world DNS traffic
- PowerDNS provides a couple of tools (located in the
pdns-utilspackage in Debian 13) that can help with benchmarking a PowerDNS server:dnsreplayreads recorded DNS query and responses and replays them to a DNS server and reports on the matchesdnsscope- sends data from a PCAP (Packet Capture) file towards an authoritative serverdnstcpbench- Tool to perform a benchmark of TCP connections to a DNS serverdumpresp- a dump responder that just echo back the query. Useful to establish a baseline of network and operating system DNS message performance
- Other DNS benchmarking tools:
perf(Unbound): simple but reliable DNS benchmarking tool, sends queries to a DNS server and reports the queries per secondsqueryperf(https://gitlab.isc.org/isc-projects/queryperf) - DNS server benchmarking tool from BIND 9queryperf++(https://www.jinmei.org/blog/2012/04/02/3074) a framework for performance measurement on DNS server implementations, support UDP and TCP, can benchmark AXFR and IXFR over TCP
- PowerDNS provides a couple of tools (located in the
4.13.1 Hardware
- The hardware used to host the DNS server can have a big impact on
DNS server performance
- Turn off symmetric multi-threading (aka Hyper-Threading) and run the DNS server on real CPU cores
- 4-8 Cores are usually enough for an authoritative DNS
server. More CPU cores can kill CPU cache performance.
- Pin the PowerDNS processes and the Database processes to their own CPU cores
- Check for IRQ balancing of the network cards. Sometimes all IRQs are routed towards one CPU core, which becomes a bottleneck for DNS style IP traffic (many small packets)
- When selecting hardware, use server with less number of cores but high performance of each core
- Configure the PowerDNS
receiver-threadsto be one per core - Memory bandwidth between CPU, cache-memory und main-memory is important
- Select quality network cards with good driver support for you operating system
- Avoid system virtualization (VMWare, QEMU, VirtualBox etc). If virtualization is required, use PCI pass-through for the network cards
- The Spectre and Meltdown type of CPU vulnerabilities usually don't affect dedicated non-virtualized DNS server. Consider switching off the kernel mitigation for these security issue to gain more performance. Consult with your security department first.
- Possibly adjust the memory allocation scheme of the operating
system LIBC library (see
MALLOC_ARENA_MAXhttps://doc.powerdns.com/authoritative/performance.html)- Alternative memory allocation libraries can help performance
(
jmallochttps://github.com/jemalloc/jemalloc,mimallochttps://github.com/microsoft/mimalloc,tcmallochttps://gperftools.github.io/gperftools/tcmalloc.html,scudohttps://expertmiami.blogspot.com/2019/05/what-is-scudo-hardened-allocator_10.html)
- Alternative memory allocation libraries can help performance
(
4.13.2 Logging
- Logging can hurt the DNS server performance. Generating text base log message is CPU intensive, and can slow down the PowerDNS server under high query load. Disable query- and detail-logging.
4.13.3 Server placement
- The DNS protocol has a build in load-distribution function
- DNS query load will be spread over all authoritative server (primary and secondary)
- Deploy DNS server in many different networks and geographic regions
- Select data-center with fast Internet access that are near potential DNS user
- DNS load-balancer in front of authoritative server can hurt the performance and increase the query latency
4.13.4 Network
- PowerDNS configuration options that have an impact on the network
performance
- If the operating system support the
reuseportsocket option, configure PowerDNS to use this option to be able to have multiple processes/threads listening on the same IP address and port. This helps distributing the load over multiple CPU cores - For DNS server with many TCP connections (primary with many
secondaries, large Resource-Records set that demand TCP
connections, DNS-over-TLS/HTTPS) tune the TCP network stack of
your operating system and the PowerDNS TCP configuration:
- Enable
tcp-fast-openwhen available in the operating system - Adjust the
max-tcp-connectionsandmax-tcp-connections-per-clientto match your PowerDNS server workload. Monitor the PowerDNS server to detect if these threshold - Limit the time a TCP connection can be held open from a client
(see
max-tcp-connection-duration) - Limit the number of transactions that can be send through one
TCP connection (see
max-tcp-transactions-per-conn)
- Enable
- If the operating system support the
4.13.5 Cache
- For a PowerDNS server with database backend, the packet and query
caches are an important performance factor. The packet cache holds
DNS responses that have been fetched from the database. The query
cache holds results from additional database queries required to
find DNS data in the database. Carefully tune the PowerDNS caches:
max-cache-entries- Max entries in the query cachemax-packet-cache-entries- Max entries in the packet cachequery-cache-ttl- How long are database queries resulting in positive answers be stored in the query cachenegquery-cache-ttl- How long are database queries resulting in negative answers be stored in the query cachecache-ttl- How long are full DNS answer packets are stored in the packet cache
4.13.6 Database
- Database performance can be the bottleneck with a PowerDNS instance
using a database backend. PowerDNS stores DNS queries in a queue
waiting to the send to the database. Settings that effects the
performance of the database query queue
max-queue-lengthlength of the backend query queue. If this threshold is reached, close the database connection and restart operation (to work around database connection issues)overload-queue-lengthdefines a threshold size for the database query queue. Default unlimited. Once reached, DNS requests are only answered from the packet cachequeue-limit- Maximum time (milliseconds) that a query can be waiting in the backend queue
4.13.7 Benchmarking
- The PowerDNS command line tool
pdnsutilcontains a build-in benchmarking function for database connections
% pdnsutil bench-db
4.14 DNS-Debugging & PowerDNS Debugging
- The SOA serial must match on all authoritative servers.
- If the zone is changed but the serial number not incremented, the secondaries won't zone transfer… primary and secondary DATA will not match.
dig +nssearch <zone name>queries the SOA from all servers listed in the zone's NS RRset.
$ dig menandmice.com +nssearch SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 213.176.128.100 in 62 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 213.176.143.102 in 62 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 193.4.194.100 in 62 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 217.151.171.7 in 64 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 217.151.171.21 in 67 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 45.79.153.125 in 100 ms. SOA dns1.menandmice.com. hostmaster.menandmice.com. 2020052201 900 300 604800 900 from server 2600:3c03::f03c:91ff:fe67:57a0 in 100 ms.
4.14.1 External Domain Checking
- Many websites offer domain name checking.
- These are most useful for your authoritative zones.
- Some checkers are broken, outdated, or simply bad.
- Two are excellent and recommended:
- https://zonemaster.net (Alternative: https://zonemaster.iis.se)
- https://dnsviz.net
4.14.2 Exercise
- use the external website checkers above to check your
zoneXXX.dnslab.orgzone - try to understand the output
- are there any errors reported? Warnings? Recommendations?
4.15 Web-server, Prometheus Metrics and REST API
4.15.1 Web-server
- PowerDNS provides an optional build-in web-server. This web-server
provides:
- A simple web page that show vital performance data
- A metrics endpoint for the Prometheus (https://prometheus.io) monitoring system
- A URL endpoint for a restful API
- The web-server can be enabled in the PowerDNS configuration file
# Webserver webserver=yes webserver-address=127.0.0.1 webserver-password=powerDNS webserver-port=8053 webserver-allow-from=127.0.0.1/32
- After a restart, PowerDNS should now listen of the defined TCP port
% lsof -Poni :8053 COMMAND PID USER FD TYPE DEVICE OFFSET NODE NAME pdns_serv 29892 pdns 9u IPv4 85197 0t0 TCP 138.68.87.93:8053 (LISTEN)
4.15.2 Prometheus
- The URL endpoint
/metricsprovides a metrics page that get be used ("scraped") by Prometheus and compatible monitoring systems
4.15.3 API
- Access to the REST-API must be secured by an API key. At least 16 byte
of random key is recommended. Such a key can be generated as a
hexadecimal string with
openssl:
% openssl rand -hex 16
- The configuration settings below enable the API
api=yes api-key=<api-key>
- Testing the API from
curl. It is required to send the API-Key with theX-API-Keyheader with every request
# curl -s -H 'X-API-Key: ac90ae012cdaba61101a9061eda492d6' http://ns001a.dnslab.org:8053/api/v1/servers/localhost/zones | jq .
[
{
"account": "",
"dnssec": false,
"edited_serial": 1007,
"id": "zone001.dnslab.org.",
"kind": "Native",
"last_check": 0,
"masters": [],
"name": "zone001.dnslab.org.",
"notified_serial": 1007,
"serial": 1007,
"url": "/api/v1/servers/localhost/zones/zone001.dnslab.org."
}
]
- The API documentation is available from the PowerDNS server itself (benefit: it is always correct for the running version of PowerDNS). To dump out the API documentation, the API-Key needs to be send as well
$ curl -s -H 'X-API-Key: <api-key>' http://nsNNNa.dnslab.org:8053/api/docs | less
4.15.4 Exercise
- Enable the PowerDNS web-server to listen on the public IP addresses (IPv6 and IPv4) of the server, protect the access with a password
- Check out the statistics and Prometheus metrics page from a web browser
- Create an API key for your primary server using
openssl - Enable the API with the API-key, check the configuration
- Use
curlto download the API documentation - Find the API function to delete a record from a zone, test to
remove a record from the zone
- Does the SOA serial increment?
4.15.5 Solution
- API call to remove the IPv6 AAAA record from a PowerDNS hosted
zone. The
nameparameter must be fully qualified, ending with the dot.:
% curl -s -X PATCH --data '{"rrsets": [ {"name": "zoneNNN.dnslab.org.", "type": "AAAA", "changetype": "DELETE" } ] }' \
-H 'X-API-Key: <api-key>' http://pdnsNNNa.dnslab.org:8053/api/v1/servers/localhost/zones/zoneNNN.dnslab.org
% pdnsutil list-zone zoneNNN.dnslab.org
- As the
pdnsutil list-zoneshows, the SOA serial is not incremented. To increment the SOA record, another API call is required.
5 PowerDNS recursor
5.1 DNS Resolver placement
- in managed networks (company, university) the IT department manages one or more dedicated DNS resolvers
- ISP (Internet Service Provider) customers often use the DNS resolvers provided by the ISP
- although sometimes problematic from privacy and security point of view, many users today use public DNS resolvers in the Internet
- some operating systems support operating a full DNS resolver on each system
5.2 Compiling and Installing the PowerDNS Recursor
- There are several options to install a PowerDNS recursor on a
Linux/Unix operating system
- Using pre-compiled packages from the operating system repositories
- Using pre-compiled packages from PowerDNS B.V. The packages provided by PowerDNS B.V. might be more recent or have special features enabled that are not available in the Linux/Unix repository packages (https://repo.powerdns.com)
- Using a package manager that compiles the software from source, such as pkgsrc (http://www.pkgsrc.org) or nix (https://nixos.org/download.html)
- Compiling directly from source (https://github.com/PowerDNS)
5.2.1 Installation of the PowerDNS recursor on Debian 13
- In the hands-on lab sessions for this training, we will be installing the PowerDNS recursor from the Debain 11 repositories
% apt install pdns-recursor
- After installation, the PowerDNS recursor should be up and running
with the default configuration. You can use the
rec_controltool to check that all PowerDNS recursor threads are alive
% rec_control ping pong pong pong
- The PowerDNS recursor main binary is
pdns_recursor. Beside being used to start the PowerDNS recursor process, it can be used to print out the compile time configuration
# pdns_recursor --version
Oct 31 11:48:51 PowerDNS Recursor 4.4.2 (C) 2001-2020 PowerDNS.COM BV
Oct 31 11:48:51 Using 64-bits mode. Built using gcc 10.2.1 20210110.
Oct 31 11:48:51 PowerDNS comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2.
Oct 31 11:48:51 Features: fcontext libcrypto-ecdsa libcrypto-ed25519 libcrypto-ed448 libcrypto-eddsa lua protobuf dnstap-framestream snmp sodium
Oct 31 11:48:51 Configured with: " '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=${prefix}/include'
'--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var'
'--disable-option-checking' '--libdir=${prefix}/lib/x86_64-linux-gnu' '--runstatedir=/run' '--disable-maintainer-mode'
'--disable-dependency-tracking' '--sysconfdir=/etc/powerdns' '--enable-systemd' '--with-systemd=/lib/systemd/system'
'--enable-reproducible' '--enable-unit-tests' '--disable-silent-rules' '--with-service-user=pdns' '--with-service-group=pdns'
'--with-libsodium' '--with-lua' '--with-net-snmp' '--with-protobuf=yes' '--enable-dnstap'
'build_alias=x86_64-linux-gnu'
'CFLAGS=-g -O2 -ffile-prefix-map=/build/pdns-recursor-MyWXnC/pdns-recursor-4.4.2=. -fstack-protector-strong -Wformat -Werror=format-security'
'LDFLAGS=-Wl,-z,relro -Wl,-z,now'
'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'
'CXXFLAGS=-g -O2 -ffile-prefix-map=/build/pdns-recursor-MyWXnC/pdns-recursor-4.4.2=. -fstack-protector-strong -Wformat -Werror=format-security -DPACKAGEVERSION='\''"4.4.2-3.Debian"'\'''"
- The default security settings of the PowerDNS recursor service is
already quite good, as can be seen with
systemd-analyze:
% systemd-analyze security pdns-recursor
- However some additional hardening steps are possible (optional):
MemoryDenyWriteExecute- enables a function in the memory management unit (and modern CPUs) that makes memory pages either write-able (data) or executable (program code), but never both. This prevents certain attacks, such as buffer overflow attacksumask- Files created by the PowerDNS recursor processes can only be read or written by the PowerDNS recursor user orroot, but not by any other userMemoryMax- Restrict the memory consumption of the PowerDNS process to 1 GB. This is usually more than enough for an DNS resolver server and prevents system instability in case of a memory leak. For a DNS resolver with a large user base (millions of user), this setting might need to be adjusted. However values over 2 GB are usually not needed.TasksMax- restricts the number of threads (tasks) of the PowerDNS service to 512. This prevents DoS attacks through a security vulnerability that would allow and external attacker to start new threads. This setting should be monitored and adjusted to the real world scenario where PowerDNS is deloyed (number of CPU cores, network interfaces etc).
MemoryDenyWriteExecute=true UMask=077 MemoryMax=1G TasksMax=512
5.2.2 Exercise
- Login to your hands-on lab machine
pdnsrNNN.dnslab.org - Become
root - Install the PowerDNS recursor server from the Debian 13 package repository
- Use
systemctl edit --full pdns-recursorto add the additional hardening configuration seen above. Add the additional lines inside the[service]section - Restart the PowerDNS service, and check with
systemctl statusthat the Task and Memory restrictions are in place
5.3 PowerDNS recursor configuration
- The PowerDNS recursor configuration file is in
/etc/powerdns/recursor.conf. The default configuration file can be overwhelming in the beginning, so we start with a clean file and build our configuration from there. We backup the original configuration files.
% mv /etc/powerdns/recursor.conf /etc/powerdns/recursor.conf.debian11
- Below is a basic working configuration for a PowerDNS recursor
# Access allow-from=127.0.0.0/8 # Network local-address=127.0.0.1 local-port=53 reuseport=yes # Socket socket-dir=/run/pdns-recursor write-pid=yes # Logging disable-syslog=no # Security udp-truncation-threshold=1232 edns-outgoing-bufsize=1232 version-string="My PowerDNS" qname-minimization=yes security-poll-suffix= lowercase-outgoing=yes serve-rfc1918=yes
- After restart, the PowerDNS recursor listens on port 53 (DNS) UDP and TCP
% lsof -Poni :53 COMMAND PID USER FD TYPE DEVICE OFFSET NODE NAME pdns_recu 22415 pdns 6u IPv4 90499 0t0 UDP 127.0.0.1:53 pdns_recu 22415 pdns 9u IPv4 90502 0t0 TCP 127.0.0.1:53 (LISTEN)
- The resolver should now resolve DNS queries
% dig @localhost sys4.de ; <<>> DiG 9.16.22-Debian <<>> @localhost sys4.de ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25571 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;sys4.de. IN A ;; ANSWER SECTION: sys4.de. 3600 IN A 194.126.158.154 ;; Query time: 91 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Nov 01 06:44:22 UTC 2021 ;; MSG SIZE rcvd: 52
- Besides the normal key-value style configuration file, PowerDNS recursor can be configured using the Lua programming language. This allows more complex configurations and is required for some special functions, such as DNSTAP, Response-Policy-Zones and DNSSEC trust-anchor management.
- The Lua-Configuration file is loaded from the main PowerDNS
recursor configuration and is stored in
/etc/powerdns/recursor.lua. The Lua configuration file example below prints a log message to inform that the Lua configuration file has been loaded, and the loads the DNSSEC root-keys:
-- Debian default Lua configuration file for PowerDNS Recursor
pdnslog("PowerDNS recursor Lua config file loaded", pdns.loglevels.All)
-- Load DNSSEC root keys from dns-root-data package.
-- Note: If you provide your own Lua configuration file, consider
-- running rootkeys.lua too.
dofile("/usr/share/pdns-recursor/lua-config/rootkeys.lua")
- To load the Lua configuration file, add the line below to the
PowerDNS recursor config file in
/etc/powerdns/recursor.conf
# Lua config file lua-config-file=/etc/powerdns/recursor.lua
- Restart the PowerDNS recursor and watch for the message from the Lua configuration file in the log output
5.3.1 Exercise
- Save the original PowerDNS recursor configuration file on
pdnsrNNN.dnslab.organd replace the configuration with the example file above - Add the Lua configuration
- Restart the PowerDNS recursor, check the log-files (systemd journal) for errors and the Lua configuration log message configured
- Verify that the DNS resolver still works as expected and does resolver names in the Internet
- The operating system should use the same DNS "view" the DNS
namespace, esp. in the case of a split-horizon DNS setup.
- There are many ways on how to configure the operation system resolver (manual, DHCPv4, IPv6-SLAAC, DHCPv6 …). Here we use the brutal direct method which is not recommended in production:
rm /etc/resolv.conf echo "nameserver 127.0.0.1" > /etc/resolv.conf echo "search ." >> /etc/resolv.conf chattr +i /etc/resolv.conf
- After changing the operating system resolver config, check that DNS
name resolution still works from the operating system (
diguses/etc/resolv.confto find the DNS resolver, but used it's own resolver routines.getentuses the libc DNS lookup)
% dig sys4.de aaaa % getent hosts sys4.de 2001:1578:400:111::8 sys4.de
5.4 DNSSEC validation
5.4.1 DNSSEC intro
- Slides: DNSSEC Introduction
5.4.2 DNSSEC Validation with PowerDNS recursor
- PowerDNS comes with the DNSSEC trust anchors for the Internet DNS system
- Using DNSSEC validation is just a matter of switching it on
- Every DNS resolver for the Internet should have DNSSEC validation enabled, there is no downside of doing DNSSEC validation
- To enable DNSSEC validation, add the
dnssec=validatestatement to the PowerDNS recursor configuration file
# DNSSEC dnssec=validate
- The Root Trust Anchor for DNSSEC used in a Debian 13 system can be
found in
/usr/share/dns/root.keywhich is loaded from/usr/share/pdns-recursor/lua-config/rootkeys.lua
-- readTrustAnchorsFromFile reads the DNSSEC trust anchors from the provided file
-- and reloads it every 24 hours.
readTrustAnchorsFromFile("/usr/share/dns/root.key")
- Other values for the
dnssecsetting statement:off- completely disables DNSSECprocess-no-validate- (default until version 4.5.0): creates a "security aware, non-validating" nameserver, where PowerDNS will request DNSSEC data with the DO flag and will provide the data to a downstream client when requested, but will not do any DNSSEC validationprocess- (default since version 4.5.0): the PowerDNS recursor will always request DNSSEC data, but will only validate when requested by the client with either theDOor theADflag in the query from the clientlog-fail- same asprocess, but additionally will log DNSSEC validation issues. This can be used to find DNSSEC validation issues before enabling full validationvalidate- PowerDNS recursor does full DNSSEC validation on all DNS data that contains DNSSEC information
5.4.3 DNSSEC related configuration options
allow-trust-anchor-query- Allowtrustanchor.server CH TXTandnegativetrustanchor.server CH TXTqueries to view the configured DNSSEC (negative) trust anchors. Can be used to monitor trust anchors.dnssec-log-bogus- Log every DNSSEC validation failure. Note: This is not logged per-query but every time records are validated as Bogus.aggressive-nsec-cache-size- The number of records to cache in the aggressive cache. If set to a value greater than 0, the recursor will cacheNSECandNSEC3records to generate negative answers, as defined in RFC 8198. To use this, DNSSEC processing or validation must be enabled by setting dnssec toprocess,log-failorvalidate.max-cache-bogus-ttl- Maximum number of seconds to cache an item in the DNS cache (negative or positive) if its DNSSEC validation failed, no matter what the original TTL specified, to reduce the impact of a broken domain.nsec3-max-iterations- Maximum number of iterations allowed for an NSEC3 record. If an answer containing an NSEC3 record with more iterations is received, its DNSSEC validation status is treated as Insecure. New recommendation is to set this to 150 iterations, see Guidance for NSEC3 parameter settings - draft-ietf-dnsop-nsec3-guidancesignature-inception-skew- Allow the signature inception to be off by this number of seconds. Negative values are not allowed (Default 60 seconds since version 4.2.0).
- Exercise
- Enable DNSSEC validation on your PowerDNS recursor
- Test the following DNS queries with
digheise.de A- should resolve, but not validatesys4.de A- should resolver and validate (AD-Flag)fail03.dnssec.works- should not resolve (ErrorSERVFAIL, domain is bogus)
- Enable
dnssec-log-boguson the PowerDNS recursor, try the domainsfail01.dnssec.workstofail05.dnssec.works. Are the DNSSEC validation errors being written to the log?
5.5 DNS Cache
- Providing a DNS cache for faster DNS name resolution is a major
part of a DNS resolver (the other important function is the smart
resolver that can traverse the DNS namespace tree)
- Most of the time, the DNS cache is maintenance free
- But in case of attacks or external mis-configurations, the DNS resolver administrator might need to maintain the cache content manually
5.5.1 DNS Name Resolution
- DNS Query - what the client sends
p>
- DNS Name Resolution
p>
5.5.2 Caching
- DNS Resolver caching
p>
5.5.3 Negative Caching
NXDOMAIN- the domain name does not exist.NOERROR/NODATA- the domain name exists, but not the RR type. AKA:NOERROR/NOANSWER.- For
NXDOMAINandNOERROR/NODATA, the zone'sSOAis returned in the authoritative section. - The negative TTL is the minimum of SOA's TTL and the SOA's RDATA MIN field. (RFC 2308 -Negative Caching of DNS Queries (DNS NCACHE))
5.5.4 PowerDNS cache maintenance
- Sometimes wrong DNS data might be stored in the cache (caused by an operational error on the authoritative zone side, or through an cache-poisioning attack
- The command
rec_control dump-cachecan be used to write the content of the cache into a file in human readable form (RFC 1035 master file format)- Such a file can be quite large, up to 400% larger than the (binary) cache content in memory. Check the available space on the file system first before dumping a large cache!
% rec_control dump-cache /some/path/in/the/filesystem/cache.txt dumped 88 records
- Malicious or wrong content in the cache can be removed with the
wipe-cachesub-command ofrec_control- This command takes one or more domain names and removed all cached entries (all record types) of that name (but only that name).
- When the domain name is suffixed with a
$, the domain name and all sub-domains are removed as well
% rec_control wipe-cache powerdns.com$ sys4.de
- The sub-command
wipe-cache-typedcan be used to remove a specific record type (A, AAAA, MX, TXT …) of a domain name from the cache
% rec_control wipe-cache-typed MX powerdns.com$ sys4.de
5.5.5 Exercise
- Resolve the name
yahoo.co.jp(Yahoo Japan) from your PowerDNS recursor. Note the DNS resolution time - Repeat the query. The DNS resolution time should now be much lower,
as the answer comes from the cache
- Repeat the query, see the TTL decrease
- Wipe the name
yahoo.co.jpfrom the cache, repeat the query, note the query time - Wipe the top-level-domain
jpand all sub-domains from the cache, repeat the query foryahoo.co.jp, note the query time - Dump the content of the cache into
/tmp/cache.txt, try to view the file. Are you able to view the file? What might be wrong? How to solve this? Discuss with the other training participants.
5.5.6 Solution
- As a security measure, PowerDNS recursor run with a private
/tmpand/var/tmpdirectory- The file is written, but only the same process can see and access it (see systemd hardening above)
% rec_control dump-cache /tmp/cache.txt dumped 88 records % less /tmp/cache.txt /tmp/cache.txt: No such file or directory
- We need to write the file into a non-temp directory
% mkdir /var/cache/pdns % chown pdns /var/cache/pdns/ % rec_control dump-cache /var/cache/pdns/cache.txt % less /var/cache/pdns/cache.txt
5.5.7 PowerDNS cache configuration
- The PowerDNS cache function can be tuned in the configuration file
disable-packetcache- disables the cache. Only recommended in special cases where PowerDNS recursor is used to manipulate DNS data on-the-fly that should not be cached, for example though Lua scriptsmax-cache-entries- Maximum number of DNS record cache entries (default 1 million), shared by all threads. Each entry associates a name and type with a record set. The size of the negative cache is 10% of this number. Having a too large cache can hurt performance, as it fragments DNS cache memory. This value can be changed at runtime withrec_control set-max-cache-entries <num>. This is useful to dynamically re-size the cache to find the best cache size for a workload.max-packetcache-entries- While the normal cache holds DNS resource records, the packet cache holds the full DNS response packets. This setting controls the maximum number of Packet Cache entries (default 500.000). Each worker and each distributor thread has a packet cache instance. This number will be divided by the number of worker plus the number of distributor threads to compute the maximum number of entries per cache instance. Can be set at run-time withset-max-packetcache-entries <num>max-cache-ttl- Maximum number of seconds to cache an item in the DNS cache (default 86400 or 24 hours), no matter what the original TTL specified. The minimum value of this setting is 15. i.e. setting this to lower than 15 will make this value 15.max-negative-ttl- How long are negative responses (NXDOMAINandNXRRSET/NODATAbeing cached. Default 3600 (1 hour). Can overwrite the SOA negTTL/minTTL of the authoritative zoneminimum-ttl-override- This setting artificially raises all TTLs to be at least this long. Setting this to a value greater than 1 technically is an RFC violation (and might break applications and web-pages!), but might improve performance a lot. Using a value of 0 impacts performance of TTL 0 records greatly, since it forces the recursor to contact authoritative servers each time a client requests them. Can be set at runtime usingrec_control set-minimum-ttl <num>packetcache-ttl- Maximum number of seconds to cache an item in the packet cache, no matter what the original TTL specified. Default 3600 (1 hour)packetcache-servfail-ttlMaximum number of seconds to cache an answer indicating a failure to resolve in the packet cache. Before version 4.6.0 only ServFail answers were considered as such. Starting with 4.6.0, all responses with a code other thanNoErrorandNXDomain, or without records in the answer and authority sections, are considered as a failure to resolve.record-cache-shards- Sets the number of shards in the record cache (Default 1024). If you have high contention as reported byrecord-cache-contented/record-cache-acquired(see statistics/metrics), you can try to enlarge this value or run with fewer threads.
5.6 SplitDNS and Forward-Zones
- Sometimes it is desired that a DNS resolver can resolve names that
are not delegated from the Internet DNS root down
- Internal versions of a zone that also exists on the Internet (Split-DNS)
- Internal Active Directory domains
- Local-Domains (
home.arpa) - For testing purposes of new Internet domains, before connecting them to the Internet DNS delegation tree
- DNS resolver can send queries to upstream server in two different
modes
- Recursive mode (
RD– recursion desired – flag set) - these queries should be send to other DNS resolver - Iterative mode (
RD– recursion desired – flag clear) - these queries should be send to authoritative DNS server
- Recursive mode (
- In other DNS server software (BIND 9, Windows DNS),
forwardingalways is operating inrecursive mode. Iterative name resolution to authoritative server is implemented through Stub-Zones- The PowerDNS recursor can do forwarding in
recursiveanditerativemode
- The PowerDNS recursor can do forwarding in
5.6.1 Forwarding (Recursive mode)
- Forwarding in recursive mode is configured with one or more
forward-zones-recursestatements in the configuration file- This statement takes the domain to be forwarded (including all
sub-domains). Use
.to generate a global forwarding where all queries to being forwarded to the upstream DNS resolver - The second parameter are the IP addresses of the upstream DNS resolver. The addresses are separated by semicolons (not comma or space)!
- This statement takes the domain to be forwarded (including all
sub-domains). Use
forward-zones-recurse=example.org=192.0.2.53;2001:db8::53
- Exercise
- Configure a forwarding to 2 (!) upstream DNS resolver from Quad9
(https://www.quad9.net) for the domain name
powerdns.com(and everything below) - Restart the PowerDNS recursor
- Run
tcpdumpin a separate terminal window (or usetmux) to observe the DNS queries going out from the server machine. Send test queries forpowerdns.comand other domains. Validate that the requests forpowerdns.comare being send to Quad9.
- Configure a forwarding to 2 (!) upstream DNS resolver from Quad9
(https://www.quad9.net) for the domain name
- Solution
- PowerDNS recusor configuration
forward-zones-recurse=powerdns.com=9.9.9.9;149.112.112.112
tcpdump
% tcpdump port 53 and host 9.9.9.9 or host 149.112.112.112 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 15:34:03.721440 IP pdnsrNNN.dnslab.org.31778 > dns9.quad9.net.domain: 30694+% [1au] DS? www.powerdns.com. (45) 15:34:03.733552 IP dns9.quad9.net.domain > pdnsrNNN.dnslab.org.31778: 30694$ 0/4/1 (500) 15:34:03.733852 IP pdnsrNNN.dnslab.org.18160 > dns9.quad9.net.domain: 23994+% [1au] DNSKEY? powerdns.com. (41) 15:34:03.742156 IP dns9.quad9.net.domain > pdnsrNNN.dnslab.org.18160: 23994$ 3/0/1 DNSKEY, DNSKEY, RRSIG (765) 15:34:03.742854 IP pdnsrNNN.dnslab.org.22697 > dns9.quad9.net.domain: 57733+% [1au] A? www.powerdns.com. (45) 15:34:03.929210 IP dns9.quad9.net.domain > pdnsrNNN.dnslab.org.22697: 57733$ 2/0/1 A 188.166.104.92, RRSIG (233)
5.6.2 Sending queries to a non-delegated zone (Iterative forwarding)
- Iterative forwarding is configured with the
forward-zonestatement. The statement format is identical withforward-zone-recurse(IP addresses are separated by semicolons)
forward-zones=internal-zone.loc=10.0.0.1;192.168.10.53
- Exercise
- There is an undelegated DNS zone with the name
undelegated.home.arpahosted on the authoritative DNS serverns3.myinfrastructure.org- Check that this zone cannot be resolved with normal DNS name resolution
- Configure a non-recursive (iterative) forwarding for this zone
- Restart the PowerDNS recursor and test if you can now resolve the zone
- There is an undelegated DNS zone with the name
- Solution
- PowerDNS recursor configuration:
forward-zones=undelegated.home.arpa=5.45.109.212
- Now the DNS resolver can reach the undelegated zone
$ dig undelegated.home.arpa ; <<>> DiG 9.16.22-Debian <<>> undelegated.home.arpa ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56466 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;undelegated.home.arpa. IN A ;; ANSWER SECTION: undelegated.home.arpa. 3600 IN A 5.45.109.212 ;; Query time: 27 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Tue Nov 02 20:12:16 UTC 2021 ;; MSG SIZE rcvd: 66
5.6.3 DNSSEC Trust Anchor for non-delegated zones
- Sometimes an (internal or external) undelegated DNS zone is
secured with DNSSEC and the DNS resolver should validate the data
- Internal Active Directory domains
- Private domains
- Split-DNS domains
- As the zone is not delegated, there cannot be a DNSSEC chain-of-trust from the parent zone (as there is no parent zone)
- The solution is to create a dedicated Trust-Anchor for the undelegated zone(s)
- The PowerDNS recursor uses the Key-Signing-Key (KSK, DNSKEY
flag 257) of a zone as the trust anchor
- All trust anchors should be in a single file and loaded at startup
- It is possible to inject a trust anchor at runtime, but that trust anchor will be lost after an restart of the service
- Creating a Trust Anchor file for PowerDNS recursor
- In this example we fetch the KSK of the undelegated zone from one of their authoritative servers (manually validate that the KSK is the correct one!)
% dig undelegated.home.arpa dnskey | grep 257 undelegated.home.arpa. 3600 IN DNSKEY 257 3 13 Vc6u0+qBFFUcc/S7LVdURP1PlIDsXPcKKNpqqoVylcv3FQq97npGNp9A xNf6odw2W+LkUv5At6UoaN79ghrtJQ==
- The KSK data of the root KSK and all other zones is stored into a trust-anchor file, one KSK per line
% dig . dnskey | grep 257 > dnssec.ta % dig undelegated.home.arpa dnskey | grep 257 >> dnssec.ta
- In the PowerDNS recursor Lua configuration file
/etc/powerdns/recursor.lua, the new trust anchor file is being loaded. This will replace all previous loaded trust anchors!
-- Trust Anchor for undelegated.home.arpa readTrustAnchorsFromFile("/etc/powerdns/dnssec.ta")- After restart, the PowerDNS recursor should have all trust anchors configured:
# rec_control get-tas Configured Trust Anchors: . 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d undelegated.home.arpa 40068 13 2 566ec09d6e001eb78d4dfad2e4789e0c6ebcf3f2bcc5051fa2dce08df0a728a5- Now the undelegated zone should resolve and validate (check the
ADflag in the DNS response):
% dig undelegated.home.arpa ; <<>> DiG 9.16.22-Debian <<>> undelegated.home.arpa ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11174 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;undelegated.home.arpa. IN A ;; ANSWER SECTION: undelegated.home.arpa. 3600 IN A 5.45.109.212 ;; Query time: 63 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Tue Nov 02 20:44:40 UTC 2021 ;; MSG SIZE rcvd: 66
- Exercise
- Create a trust anchor for the zone
undelegated.home.arpaas shown in the example above
- Create a trust anchor for the zone
5.7 Webserver
- As the other PowerDNS products (PowerDNS authoritative server,
DNSdist), the PowerDNS recursor comes with a build in web-server
- The web-server does show the CPU utilization, current queries per second (QPS) and SERVFAIL per second, Query-Names and remote IP addresses from DNS clients
- For the PowerDNS recursor web-server to work, the API-key must be configured, even if not used
# Webserver webserver=yes webserver-address=<ip-address-of-server> webserver-password=PowerDNS webserver-port=8053 webserver-allow-from=0.0.0.0/0 webserver-loglevel=none # API api-key=56372de136e76af5d373eda664d0d30c
5.7.1 Exercise
- Enable the web-interface for PowerDNS recursor
- Login to the web-interface with a web-browser
- Send some DNS queries to the PowerDNS recursor, see the statistics change
5.8 DNStap (Advanced Query & Response Logging)
5.8.1 DNS server operations monitoring
- It is difficult to monitor the internal operation of a DNS server
- Classic monitoring has a huge performance impact (on busy DNS servers)
- Example: PowerDNS query-logging
- Up to 200% performance loss seen
- Speed of the disk storage is often the limiting factor
- Conversation from binary to text format is CPU intensive
- Classic monitoring has a huge performance impact (on busy DNS servers)
- Network packet capture
- An alternative solution is to look from the outside via a network traffic capture tool
- No performance impact on the DNS server
- Can only observe from the outside (no internal DNS server events, like cache-events, seen)
- Difficult to work with UDP fragments and DNS data in TCP streams
- Example: DNS statistics collector (DSC) https://www.caida.org/tools/utilities/dsc/
- An alternative solution is to look from the outside via a network traffic capture tool
- DNSTAP
- DNSTAP is an open protocol to capture and store DNS server events
- Events are recorded inside the server
- Fast and lightweight protocol
- Non-blocking, designed to have minimal impact on the DNS servers performance
- DNSTAP Operation
p>
- DNSTAP implementations
- DNSTAP has been developed by Farsight Security
(Paul Vixie and Robert Edmonds)
- Homepage is http://dnstap.info
- Implementations:
- Unbound
- Knot 2.x
- BIND 9
- NSD
- CoreDNS
- PowerDNS Recursor
- DNSDist (PowerDNS Load Balancer)
- DNSTAP has been developed by Farsight Security
(Paul Vixie and Robert Edmonds)
- DNSTAP dependencies
- DNSTAP support is a compile-time option
- Sometimes not enabled in distribution package code
- Might requires compilation from source
- Sometimes not enabled in distribution package code
fstrm(Frame Streams data transport protocol): lightweight protocol to transport frames of data, can be used with any data serialisation format that produces byte sequences https://github.com/farsightsec/fstrm- Google Protocol Buffers: Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serialising structured data. https://developers.google.com/protocol-buffers/
- DNSTAP support is a compile-time option
- DNSTAP Receiver Tools
- dnstap-golang https://github.com/dnstap/golang-dnstap
- dnstap-ldns https://github.com/dnstap/dnstap-ldns
- dnstap-read (part of BIND 9.11)http://source.isc.org
- Wireshark with dnstap support https://github.com/dnstap/wireshark
- Using DNSTAP with PowerDNS recursor
- Installing the
dnstapreader from the Debian 13 repositories
% apt install golang-github-dnstap-golang-dnstap-cli dnstap-ldns
- (Alternative): Installing the
dnstapreader from source
% apt install golang % go get -u github.com/dnstap/golang-dnstap/dnstap % mv ~/go/bin/dnstap /usr/local/bin/
- DNSTAP can be enabled in the PowerDNS Lua configuration file
/etc/powerdns/recursor.lua
-- DNSTAP dnstapFrameStreamServer("127.0.0.1:9999", {logQueries=true, logResponses=true})- Start DNSTAP reader from the command line. For a production
installation create a systemd unit. For forensic analysis, it is
recommended to trigger the
dnstapsystemd unit from a system event (high load, unusual traffic pattern etc)
% dnstap -l 127.0.0.1:9999
- Restart the PowerDNS recursor
- The DNSTAP reader will print out log information to
stderrafter successful connections from PowerDNS
2021/11/01 09:52:35 127.0.0.1:9999: accepted connection 1 from 127.0.0.1:47500 2021/11/01 09:52:35 127.0.0.1:9999: accepted connection 2 from 127.0.0.1:47502 2021/11/01 09:52:35 127.0.0.1:9999: accepted connection 3 from 127.0.0.1:47504 2021/11/01 09:52:35 127.0.0.1:9999: accepted connection 4 from 127.0.0.1:47506
- Example DNSTAP reader output of a resolution for
heise.de A
09:55:02.069423 RQ 2001:500:1::53 UDP 31b "de." IN DS 09:55:02.070849 RR 2001:500:1::53 UDP 366b "de." IN DS 09:55:02.071227 RQ 192.203.230.10 UDP 31b "de." IN A 09:55:02.079721 RR 192.203.230.10 UDP 736b "de." IN A 09:55:02.080183 RQ 194.0.0.53 UDP 37b "heise.de." IN DS 09:55:02.102337 RR 194.0.0.53 UDP 750b "heise.de." IN DS 09:55:02.102529 RQ 77.67.63.105 UDP 31b "de." IN DNSKEY 09:55:02.112821 RR 77.67.63.105 UDP 745b "de." IN DNSKEY 09:55:02.113324 RQ 194.146.107.6 UDP 37b "heise.de." IN A 09:55:02.126413 RR 194.146.107.6 UDP 810b "heise.de." IN A 09:55:02.126897 RQ 2001:500:d937::30 UDP 45b "pop-hannover.net." IN A 09:55:02.135566 RR 2001:500:d937::30 UDP 660b "pop-hannover.net." IN A 09:55:02.135752 RQ 62.48.67.66 UDP 37b "heise.de." IN A 09:55:02.145127 RR 62.48.67.66 UDP 255b "heise.de." IN A
- In production environment, the DNSTAP data should be written to disk for later analysis. The command below will receive DNSTAP traffic on Port 9999 and write the DNSTAP data to a file
% dnstap -l 127.0.0.1:9999 -w capture.dnstap
- To read the DNSTAP data from the file, open the file with a DNSTAP reader
% dnstap -r capture.dnstap
- Installing the
- Exercise
- Install a DNSTAP reader on the PowerDNS recursor machine
- Start the DNSTAP reader to listen on port 9999 and to print the output in verbose YAML format
- Configure DNSTAP in the PowerDNS recursor Lua configuration file
- Restart the PowerDNS recursor and send some test queries towards the recursor
- Observe the output of the DNSTAP reader
6 DNS Security with PowerDNS products
6.1 DNSDist Load-Balancer
6.1.1 DNSDist Intro
6.1.2 Exercise
- Installing dnsdist
- We work on the resolver machine
pdnsrNNN.dnslab.org - We install
dnsdistfrom the Debian 13 repositories
apt install -y dnsdist
- We work on the resolver machine
- DNSdist as load balancer for authoritative server
- In this session we build a load balancer for our authoritative PowerDNS servers
- Save and remove a previous dnsdist configuration
/etc/dnsdist/dnsdist.confand start with a clean file - We use Port 65053 on the IPv4 loopback address, as port 53 on all IP addresses is currently occupied by the PowerDNS recursor
newServer({address="<ip-v6-address-of-server1>", checkType="SOA", checkType=DNSClass.IN, checkName="zoneNNN.dnslab.org"}) newServer({address="<ip-v6-address-of-server2>", checkType="SOA", checkType=DNSClass.IN, checkName="zoneNNN.dnslab.org"}) newServer({address="<ip-v4-address-of-server1>", checkType="SOA", checkType=DNSClass.IN, checkName="zoneNNN.dnslab.org"}) newServer({address="<ip-v4-address-of-server2>", checkType="SOA", checkType=DNSClass.IN, checkName="zoneNNN.dnslab.org"}) setServerPolicy(leastOutstanding) setLocal("127.0.0.1:65053")- Starting dnsdist
- check the configuration of
dnsdistfor syntax errors
% /usr/bin/dnsdist -u dnsdist -g dnsdist --check-config Configuration '/etc/dnsdist/dnsdist.conf' OK!
- enable and start the
dnsdistservice (or restart)
% systemctl restart dnsdist
- check that the service has been started without errors:
% systemctl status dnsdist ● dnsdist.service - DNS Loadbalancer Loaded: loaded (/usr/lib/systemd/system/dnsdist.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2021-04-21 07:45:47 UTC; 2min 26s ago Docs: man:dnsdist(1) https://dnsdist.org Process: 27803 ExecStartPre=/usr/bin/dnsdist -u dnsdist -g dnsdist --check-config (code=exited, status=0/SUCCESS) Main PID: 27804 (dnsdist) Tasks: 25 (limit: 8192) Memory: 159.4M CGroup: /system.slice/dnsdist.service └─27804 /usr/bin/dnsdist -u dnsdist -g dnsdist --supervised --disable-syslog Apr 21 07:47:21 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'down' Apr 21 07:47:24 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'up' Apr 21 07:47:37 dnsdist001 dnsdist[27804]: Marking downstream [2001:4f8:1:f::73]:53 as 'down' Apr 21 07:47:38 dnsdist001 dnsdist[27804]: Marking downstream [2001:4f8:1:f::73]:53 as 'up' Apr 21 07:47:50 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'down' Apr 21 07:47:51 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'up' Apr 21 07:47:58 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'down' Apr 21 07:47:59 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'up' Apr 21 07:48:05 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'down' Apr 21 07:48:06 dnsdist001 dnsdist[27804]: Marking downstream 149.20.1.73:53 as 'up' - check the configuration of
- Testing the load-balancing setup
- we send the request to the port 65053 where dnsdist is listening
% dig -p 65053 @localhost zoneNNN.dnslab.org +norec ; <<>> DiG 9.16.22-Debian <<>> -p 65053 @localhost zoneNNN.dnslab.org +norec ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43793 ;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;zoneNNN.dnslab.org. IN A ;; ANSWER SECTION: zoneNNN.dnslab.org. 60 IN A 46.101.218.115 ;; Query time: 3 msec ;; SERVER: 127.0.0.1#65053(127.0.0.1) ;; WHEN: Tue Nov 02 21:20:54 UTC 2021 ;; MSG SIZE rcvd: 63
- The
AAFlag tell us that the response comes indeed from an authoritative DNS server
- Configuring the dnsdist webserver
- Add the following lines to the dnsdist configuration
webserver("0.0.0.0:8853") setWebserverConfig({acl="0.0.0.0/0",password="dnsdist-is-great"})- Reload the dnsdist
% systemctl restart dnsdist
- Access the web-interface from a web browser
http://pdnsrNNN.dnslab.org:8853/
- DNSdist as load balancer for DNS resolver
- In this session we build a load balancer for multiple DNS resolver. We use the local PowerDNS recursor together with a selection of public DNS resolver
- Save and remove a previous dnsdist configuration
/etc/dnsdist/dnsdist.confand start with a clean file - We use Port 65053 on the IPv4 loopback address, as port 53 on all IP addresses is currently occupied by the PowerDNS recursor
newServer({address="127.0.0.1", qps=10000, order=1}) -- our PowerDNS recursor newServer({address="1.1.1.1", qps=100, order=3}) -- Cloudflare Public DNS newServer({address="8.8.8.8", qps=100, order=2}) -- Google Public DNS -- Cache pc = newPacketCache(10000, {maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false}) getPool(""):setCache(pc) -- Load-balancing Policy setServerPolicy(leastOutstanding) -- local IP address for dnsdist setLocal("127.0.0.1:65053")- (Re-)start dnsdist
- check the configuration of
dnsdistfor syntax errors
% dnsdist -u dnsdist -g dnsdist --check-config Configuration '/etc/dnsdist/dnsdist.conf' OK!
- restart the
dnsdistservice
% systemctl restart dnsdist
- check that the service has been started without errors:
% systemctl status dnsdist ● dnsdist.service - DNS Loadbalancer Loaded: loaded (/usr/lib/systemd/system/dnsdist.service; enabled; vendor preset: disabled) Active: active (running) since Wed 2021-04-21 08:20:01 UTC; 1min 34s ago Docs: man:dnsdist(1) https://dnsdist.org Process: 29682 ExecStartPre=/usr/bin/dnsdist -u dnsdist -g dnsdist --check-config (code=exited, status=0/SUCCESS) Main PID: 29684 (dnsdist) Tasks: 23 (limit: 8192) Memory: 106.1M CGroup: /system.slice/dnsdist.service └─29684 /usr/bin/dnsdist -u dnsdist -g dnsdist --supervised --disable-syslog Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Listening on 127.0.0.1:65053 Apr 21 08:20:01 dnsdist001 dnsdist[29684]: dnsdist 1.6.0-rc1 comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to> Apr 21 08:20:01 dnsdist001 dnsdist[29684]: ACL allowing queries from: 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, ::1/128, fc00> Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Console ACL allowing connections from: 127.0.0.0/8, ::1/128 Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Webserver launched on 0.0.0.0:8053 Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Marking downstream 8.8.8.8:53 as 'up' Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Marking downstream 1.1.1.1:53 as 'up' Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Marking downstream 127.0.0.1:53 as 'up' Apr 21 08:20:01 dnsdist001 systemd[1]: Started DNS Loadbalancer. Apr 21 08:20:01 dnsdist001 dnsdist[29684]: Polled security status of version 1.6.0-rc1 at startup, no known issues reported: OK - check the configuration of
- Testing the load-balancing setup
- we send the request to the port 65053 where dnsdist is listening
% dig -p 65053 @localhost powerdns.com ; <<>> DiG 9.16.22-Debian <<>> -p 65053 @localhost powerdns.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2499 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;powerdns.com. IN A ;; ANSWER SECTION: powerdns.com. 3600 IN A 188.166.104.92 ;; Query time: 175 msec ;; SERVER: 127.0.0.1#65053(127.0.0.1) ;; WHEN: Tue Nov 02 21:53:37 UTC 2021 ;; MSG SIZE rcvd: 57
- The
RDandADFlags tell us that the response comes indeed from a DNS resolver
- Configuring the dnsdist webserver
- Add the following lines to the dnsdist configuration
webserver("0.0.0.0:8853") setWebserverConfig({acl="0.0.0.0/0",password="dnsdist-is-great"})- Reload the dnsdist
% systemctl restart dnsdist
- Access the web-interface from a browser
http://pdnsrXXX.dnslab.org:8853/
- More tests
- Performance testing a DNS resolver with
dnsblast dnsblastis a simple tool that sends random DNS queries for thecomTLD- compiling
dnsblast
% apt -y install gcc make % git clone https://github.com/jedisct1/dnsblast % cd dnsblast % make
- We use
dnsblastto send 5,000 queries at a rate of 100 qps to ourdnsdistload-balancer at port 65053
% ./dnsblast 127.0.0.1 5000 100 65053
- Watch the web-interface metrics during the test
- Try different parameters for
dnsblast - see https://github.com/jedisct1/dnsblast for additional information
on the
dnsblasttool
- Performance testing a DNS resolver with
- dnsdist as a DoT/DoH proxy
- In this exercise, we will configure dnsdist as a DoH/DoT proxy for the PowerDNS recursor
- Save and remove a previous dnsdist configuration
/etc/dnsdist/dnsdist.confand start with a clean file - Check that the PowerDNS recursor server is up and running (our pre-installed DNS resolver serving classic DNS over Port 53):
% dig @localhost powerdns.com
- the response should look like this
; <<>> DiG 9.16.22-Debian <<>> @localhost powerdns.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38445 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 512 ;; QUESTION SECTION: ;powerdns.com. IN A ;; ANSWER SECTION: powerdns.com. 3278 IN A 188.166.104.92 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Tue Nov 02 21:58:59 UTC 2021 ;; MSG SIZE rcvd: 57
- TLS x509 certificates
- Our server already has x509 certificates for TLS from Let's
Encrypt. We need to copy the certificate file and the private key
file into the
dnsdistconfiguration directory and adjust the file permissions, so thatdnsdistcan read the files
% cp /etc/ssl/private/dnslab.* /etc/dnsdist/ % chown _dnsdist: /etc/dnsdist/*
- Our server already has x509 certificates for TLS from Let's
Encrypt. We need to copy the certificate file and the private key
file into the
- Configuration for the "upstream" DNS resolver
- first we need to tell
dnsdistwhere to find the upstream (existing) DNS resolver. In our case, it is the PowerDNS recursor instance running on the same machine.- in
dnsdist, you can specify any number of upstream servers with load-balancing parameters, please see thednsdistwebsite for documentation.
- in
- we create the file
/etc/dnsdist/dnsdist.confwith one line of configuration that defines one upstream DNS resolver (use your favorite text editornano,emacs,vim):
newServer({address="127.0.0.1"}) - first we need to tell
- Configuration for DNS-over-TLS (DoT)
- our DNS-over-TLS service will run on the (loop-back) IP-Address
127.0.0.10. In an production environment, this would be one of the external addresses of the proxy machine that is reachable from DNS clients.- the new configuration line for DoT defines the listen address, the x509 certificate and the private key matching the certificate
- our configuration file
/etc/dnsdist/dnsdist.confshould now look like this:
newServer({address="127.0.0.1"}) addTLSLocal('127.0.0.10', '/etc/dnsdist/dnslab.crt', '/etc/dnsdist/dnslab.key') - our DNS-over-TLS service will run on the (loop-back) IP-Address
- Starting dnsdist
- check the configuration of
dnsdistfor syntax errors
% dnsdist -u dnsdist -g dnsdist --check-config Configuration '/etc/dnsdist/dnsdist.conf' OK!
- restart the
dnsdistservice
% systemctl restart dnsdist
- check that the service has been started without errors:
% systemctl status dnsdist ● dnsdist.service - DNS Loadbalancer Loaded: loaded (/usr/lib/systemd/system/dnsdist.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2021-02-09 09:05:34 UTC; 17s ago Docs: man:dnsdist(1) https://dnsdist.org Process: 111443 ExecStartPre=/usr/bin/dnsdist -u dnsdist -g dnsdist --check-config (code=exited, status=0/SUCCESS) Main PID: 111445 (dnsdist) Tasks: 19 (limit: 8192) Memory: 28.2M CGroup: /system.slice/dnsdist.service └─111445 /usr/bin/dnsdist -u dnsdist -g dnsdist --supervised --disable-syslog Feb 09 09:05:34 doh01 systemd[1]: Stopped DNS Loadbalancer. Feb 09 09:05:34 doh01 systemd[1]: Starting DNS Loadbalancer... Feb 09 09:05:34 doh01 dnsdist[111445]: Added downstream server 127.0.0.1:53 Feb 09 09:05:34 doh01 dnsdist[111445]: Listening on 127.0.0.10:853 for TLS Feb 09 09:05:34 doh01 dnsdist[111445]: dnsdist 1.6.0-alpha1 comes with ABSOLUTELY NO WARRANTY. This is free software, and you are we> Feb 09 09:05:34 doh01 dnsdist[111445]: ACL allowing queries from: 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0> Feb 09 09:05:34 doh01 dnsdist[111445]: Console ACL allowing connections from: 127.0.0.0/8, ::1/128 Feb 09 09:05:34 doh01 dnsdist[111445]: Marking downstream 127.0.0.1:53 as 'up' Feb 09 09:05:34 doh01 systemd[1]: Started DNS Loadbalancer. Feb 09 09:05:35 doh01 dnsdist[111445]: Polled security status of version 1.6.0-alpha1 at startup, no known issues reported: OK - check the configuration of
- Testing the DoT setup
- we use
kdig, the DNS query tool from the Knot DNS Server, to send DNS over TLS queries to our server. But first we installkdig
% apt install knot-dnsutils
- and now we test DNS-over-TLS
% kdig @127.0.0.10 powerdns.com +tls ;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM) ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 13574 ;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1 ;; EDNS PSEUDOSECTION: ;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR ;; QUESTION SECTION: ;; powerdns.com. IN A ;; ANSWER SECTION: powerdns.com. 2450 IN A 188.166.104.92 ;; Received 57 B ;; Time 2021-11-02 22:12:47 UTC ;; From 127.0.0.10@853(TCP) in 0.0 ms
kdigwill print information on the TLS connection in the first line:
;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM)
- we use
- Configuration for DNS-over-HTTPS (DoH)
- the configuration for DNS-over-HTTPS is very similar to the DoT
configuration. Please add the following line (replace the XXX with
your participant number) to the file
/etc/dnsdist/dnsdist.conf:
addDOHLocal('127.0.0.10:8443', '/etc/dnsdist/dnslab.crt', '/etc/dnsdist/dnslab.key')- check the configuration file for errors
% dnsdist -u dnsdist -g dnsdist --check-config
- and if no errors are reported, restart the
dnsdistservice
% systemctl restart dnsdist
- check that the service has been (re-)started
% systemctl status dnsdist ● dnsdist.service - DNS Loadbalancer Loaded: loaded (/usr/lib/systemd/system/dnsdist.service; enabled; vendor preset: disabled) Active: active (running) since Tue 2021-02-09 09:12:03 UTC; 5s ago Docs: man:dnsdist(1) https://dnsdist.org Process: 112038 ExecStartPre=/usr/bin/dnsdist -u dnsdist -g dnsdist --check-config (code=exited, status=0/SUCCESS) Main PID: 112040 (dnsdist) Tasks: 21 (limit: 8192) Memory: 31.2M CGroup: /system.slice/dnsdist.service └─112040 /usr/bin/dnsdist -u dnsdist -g dnsdist --supervised --disable-syslog Feb 09 09:12:02 doh01 systemd[1]: Starting DNS Loadbalancer... Feb 09 09:12:03 doh01 dnsdist[112040]: Added downstream server 127.0.0.1:53 Feb 09 09:12:03 doh01 dnsdist[112040]: Listening on 127.0.0.10:853 for TLS Feb 09 09:12:03 doh01 dnsdist[112040]: Listening on 127.0.0.10:443 for DoH Feb 09 09:12:03 doh01 dnsdist[112040]: dnsdist 1.6.0-alpha1 comes with ABSOLUTELY NO WARRANTY. This is free software, and you are we> Feb 09 09:12:03 doh01 dnsdist[112040]: ACL allowing queries from: 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0> Feb 09 09:12:03 doh01 dnsdist[112040]: Console ACL allowing connections from: 127.0.0.0/8, ::1/128 Feb 09 09:12:03 doh01 dnsdist[112040]: Marking downstream 127.0.0.1:53 as 'up' Feb 09 09:12:03 doh01 systemd[1]: Started DNS Loadbalancer. Feb 09 09:12:03 doh01 dnsdist[112040]: Polled security status of version 1.6.0-alpha1 at startup, no known issues reported: OK - the configuration for DNS-over-HTTPS is very similar to the DoT
configuration. Please add the following line (replace the XXX with
your participant number) to the file
- Testing DNS-over-HTTPS
- Again we use the
kdigtool to test our new DNS-over-HTTPS service:
% kdig -p 8443 @127.0.0.10 powerdns.com +https ;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(ECDSA-SECP256R1-SHA256)-(AES-256-GCM) ;; HTTP session (HTTP/2-POST)-(127.0.0.10/dns-query)-(status: 200) ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 0 ;; Flags: qr rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 1 ;; EDNS PSEUDOSECTION: ;; Version: 0; flags: ; UDP size: 512 B; ext-rcode: NOERROR ;; QUESTION SECTION: ;; powerdns.com. IN A ;; ANSWER SECTION: powerdns.com. 2159 IN A 188.166.104.92 ;; Received 57 B ;; Time 2021-11-02 22:17:38 UTC ;; From 127.0.0.10@8443(TCP) in 0.1 ms
kdigprint information about the TLS and HTTPS connection in the first two lines:
;; TLS session (TLS1.3)-(ECDHE-SECP256R1)-(RSA-PSS-RSAE-SHA256)-(AES-256-GCM) ;; HTTPS session (HTTP/2-POST)-(127.0.0.10/dns-query)-(status: 200)
- Again we use the
6.2 Response Rate Limiting
- Response Rate Limiting (RRL) reduces query responses sent by a DNS server.
- RRL is a defense against reflection/amplification DoS attacks
- Clients IPs are grouped into buckets. (e.g. 256 IPv4's)
- Identical responses to the same bucket are tracked.
- If identical responses go over a set rate, RRL kicks in.
- RRL significantly reduces the effect of using a domain name from a zone the server is authoritative for in a reflection attack.
- RRL is applicable to UDP queries, not those over TCP.
- A server drops or truncates when queries exceed its set rate.
- A valid client will likely re-query in response to a drop.
- Truncation prevents amplification but not reflection.
- Legitimate clients will re-query with TCP and get a reply.
- A valid client is only negatively effected, if its query is identical to the attacks, and is in a bucket being spoofed.
- RRL Info Website http://www.redbarn.org/dns/ratelimits
6.2.1 PowerDNS Authoritative
- Lua Policy Engine can be used to implement RRL https://ripe69.ripe.net/presentations/55-powerdns-ripe69.pdf
6.2.2 DNSdist
- DNSdist can be deployed to implement QPS limits https://dnsdist.org/advanced/qpslimits.html and Packet Actions https://dnsdist.org/rules-actions.html
- DNSdist can even use eBPF inside the Linux-Kernel to block incoming DNS messages deep in the network stack (before it reaches user space): https://dnsdist.org/advanced/ebpf.html
6.2.3 PowerDNS Recursor
- The PowerDNS recursor implements a query rate limiting when it
detects that a upstream authoritative server becomes unresponsive
- This prevents that the upstream authoritative DNS server get more overloaded by repeated queries from the DNS resolver
non-resolving-ns-max-fails- Number of failed address resolves of a nameserver name to start throttling it, 0 is disabled. Default: 5dont-throttle-namesexclude name server from throttling, can be set dynamically withrec_control add-dont-throttle-names NAME [NAME…]dont-throttle-netmasksexclude name servers from these networks from throttling, can be set dynamically withrec_control add-dont-throttle-netmasks NETMASK [NETMASK…]non-resolving-ns-max-throttle-timeNumber of seconds to throttle a nameserver with a name failing to resolve
server-down-max-failsIf a server has not responded in any way this many times in a row, no longer send it any queries forserver-down-throttle-timeseconds. Afterwards, the resolver will try a new packet, and if that also gets no response at all, it will again throttle forserver-down-throttle-timeseconds. Even a single response packet will clear the block.- Controlling the throttle lists
rec_control get-dont-throttle-nameswill print out the throttle exceptions for name serverrec_control get-dont-throttle-netmaskswill print out the throttle exceptions for networksrec_control dump-throttlemap FILENAMEwill write the throttle list to a filerec_control clear-dont-throttle-names NAME [NAME…]will remove a server from the throttle lustrec_control clear-dont-throttle-netmasks NETMASK [NETMASK…]will remove a network from a throttle list
6.3 Cryptography in DNS (Symmetric / Asymmetric), Transaction Signatures (TSIG)
6.3.1 Cryptography for DNS Admins
- Cryptography has four purposes:
- Confidentiality – keeping data secret
- Integrity – Is it "as sent"?
- Authentication – Did it come from the right place?
- Non-Repudiation – Don’t tell me you didn't say that.
- DNSSEC implements: Authentication & Integrity
- The IETF has added confidentiality since 2016:
- RFC 7858 "Specification for DNS over Transport Layer Security (TLS)" (DNS-over-TLS) https://tools.ietf.org/html/rfc7858
- RFC 8484 "DNS Queries over HTTPS (DoH)" (DNS-over-HTTPS) https://tools.ietf.org/html/rfc8484
- DNS uses different authenticity and integrity techniques depending on the application.
- Symmetric Cryptography
- Message Digests (aka: hashes, hash values, fingerprints)
- Message Authentication Codes
- Asymmetric Cryptography
- Digital Signatures
6.3.2 Symmetric Cryptography
- Symmetric cryptography provides both integrity and authenticity.
- A single key is stored and used by both (all) parties.
- The key encrypts and decrypts.
- The key is a shared secret.
- The system is known as pre-shared key (PSK).
- Securely getting the key to all parties can be a challenge.
- Symmetric cryptography requires mutual trust.
- "My security is good, but what about the other person's?"
- If all sides are administered by one party, trust is a non-issue.
- For DNS, Pre-Shared-Keys (PSK) work well:
- between primary and secondary servers (TSIG).
- for dynamic DNS updates (TSIG).
- for controlling BIND 9 with
rndc(TSIG).
- For DNS, PSKs do not work well:
- between DNS Resolver servers and auth servers (DNSSEC).
- between stub resolvers & DNS Resolver servers (DNSSEC amongst other).
6.3.3 Confidentiality: Not the Goal
- A Pre-Shared Key (PSK) could be used to encrypt a message.
- If it decrypts, confidentially, integrity, and authenticity are assured.
- However, confidentiality was not a design goal (of DNSSEC).
- Encrypting everything is computationally expensive.
- The alternative is more complicated but less expensive.
6.3.4 Message Digest
- Creating a hash of the message is a light-weight alternative to
encrypting everything.
- A hash is also known as a hash value, a message digest (MD) and a fingerprint.
- The sender runs a cryptographic hashing algorithm on the message to
produce a fixed-length hash.
- The message and hash are sent over an insecure path.
- As the sender did, the receiver hashes the message.
- If the hashes match, the message was not modified. Message integrity is proven.
- However, the receiver does not know if the message and hash were both replaced: Message authenticity is unknown.
- Confidentiality is not provided.
6.3.5 Message Authentication Codes
- Hashing, with a symmetric key added to the input, efficiently
provides integrity and authenticity.
- There is no confidentiality.
- A MAC is a fingerprint (MD, hash) created with the message and a PSK as input.
- The MAC described here, is a keyed HMAC (Hash-based message
authentication code).
- It is used by DNS.
- Although HMACs efficiently assure both the sender's authenticity,
and the message's integrity, not all applications can use
(pre)shared keys.
- "Am I really seeing the website
mybank.example?" - "Is the email I'm reading really from Edward Snowden?"
- "Is this RRSet actually for
theguardian.com?"
- "Am I really seeing the website
6.3.6 Asymmetric Cryptography
- In DNS, asymmetric cryptography is used for DNSSEC.
- This asymmetric cryptography section is a short overview.
- Asymmetric cryptography uses two keys, a pair.
- Data encrypted with one key can only be decrypted by the other.
- A key cannot decrypt what it encrypted!
- One key of a pair is declared as public, the other as private.
- The private key is highly sensitive, never shared, and must be well protected.
- The public key is made widely available without concern for who knows it.
- The technique is known as public key encryption.
6.3.7 Two Applications for public key (PK) Encryption
- PK encryption is used for privacy, to assure only the intended receiver can read a message.
- Data integrity is also assured.
- used in DNS-over-TLS and DNS-over-HTTPS
- PK encryption is used for authenticity, assuring the recipient,
that the message came from a specific sender.
- This is known as signing a message.
- Data integrity is also assured.
- used in DNSSEC, as well in DNS-over-TLS and DNS-over-HTTPS
6.3.8 PK Application 2: Encryption for Authenticity
- To assure authenticity, a sender encrypts a message with her
private key.
- Anyone decrypting the message with the public key is assured it came from the holder of the private key.
- The message is encrypted, but there is no privacy.
6.3.9 PK Application 2: Encryption for Authenticity: Digital Signatures
- For efficiency, the message itself is not encrypted.
- The message is first hashed to create a fingerprint.
- The fingerprint is encrypted.
- The signed fingerprint is a digital signature (aka encrypted fingerprint and encrypted hash).
6.3.10 Digital Signatures in DNSSEC
6.4 Transaction Signatures (TSIG)
- TSIGs secure the communication of two endpoints.
- TSIGs uses HMAC (i.e. symmetric encryption).
- Trust is required between all systems (all endpoints).
- Securely installing the key on all systems is external to DNS.
- The endpoints must have reasonably accurate clocks.
- TSIG is independent of DNSSEC.
- TSIG use cases:
- DNS dynamic updates (client / dhcp-server <-> server)
- BIND server control messages (rndc <-> server)
- Server communication (zone transfers, notifies, queries, …)
- Queries (client <-> server): Impractical and rare.
- A TSIG is a dynamically generated pseudo-RR.
- TSIG RRs are not found in zone files, but do have the standard format of RRs.
- TSIGs are never cached (TTL=0).
- A TSIG RR is sent in the additional section.
- A TSIG assures the integrity and authenticity of the entire DNS message.
- TSIG offers a choice of HMAC algorithms:
hmac-md5(deprecated)hmac-sha1(deprecated)- hmac-sha224
- hmac-sha256
- hmac-sha384
- hmac-sha512
- All the algorithms take a random length input and create a fixed length fingerprint.
Algorithm fingerprint length MD5 16 byte SHA1 20 byte SHA256 32 byte SHA512 64 byte
6.4.1 TSIG with PowerDNS
- TSIG is based on symmetric crypto
- The same TSIG key for a zone should be configured on the primary and on the secondary
- Zone can share keys, but it is recommended to have one key per
zone
- Or even one key per communication (primary -> secondary)
- TSIG signatures are time sensitive: the TSIG signature on DNS
messages contain a timestamp
- TSIG only allows little skew between the clocks of both communication endpoints (~ 5 Minutes)
- Make sure your DNS server always have the up-to-date time using a time synchronization protocol such as NTP
- On the primary (
master) generate a new TSIG key. By convention, the key is named<primary-hostname>-<secondary-hostname>, but can have any name. It is important that the key name has the same name on both endpoints of the communication
[primary]% pdnsutil generate-tsig-key pdns010a-pdns010b hmac-sha512 Create new TSIG key pdns010a-pdns010b hmac-sha512 L5jN+m3yTSfwoU2A43M0C/+0m7afqO1wL4OLd2auFEcA3MYyvJHixwHa0l0gZWRec10MQSw5bUByygkbJyQ/BA==
- On the primary (
master), the key is activated to be used for the outgoingNOTIFYmessages
[primary]% pdnsutil activate-tsig-key zoneNNN.dnslab.org pdns010a-pdns010b master Enabled TSIG key pdns010a-pdns010b for zoneNNN.dnslab.org
- On the secondary (
slave), import the same key (same name!)
[secondary]% pdnsutil import-tsig-key pdns010a-pdns010b hmac-sha512 L5jN+m3yTSfwoU2A43M0C/+0m7afqO1wL4OLd2auFEcA3MYyvJHixwHa0l0gZWRec10MQSw5bUByygkbJyQ/BA== Imported TSIG key pdns010a-pdns010b hmac-sha512
- On the secondary, the is used to sign the
AXFR(Zone-transfer) requests. Once the TSIG keys are in place and activated, theallow-axfr-ipsconfiguration is not required anymore
[secondary]% pdnsutil activate-tsig-key zoneNNN.dnslab.org pdns010a-pdns010b slave Enabled TSIG key pdns010a-pdns010b for zoneNNN.dnslab.org
- Log output on the primary server for a TSIG signed AXFR request
Nov 03 21:29:26 pdnsa010 pdns_server[59737]: Remote 142.93.145.28 wants 'zoneNNN.dnslab.org|SOA', do = 0, bufsize = 512: packetcache MISS Nov 03 21:29:26 pdnsa010 pdns_server[59737]: AXFR-out zone 'zoneNNN.dnslab.org', client '142.93.145.28:56771', transfer initiated Nov 03 21:29:26 pdnsa010 pdns_server[59737]: AXFR-out zone 'zoneNNN.dnslab.org', client '142.93.145.28:56771', allowed: TSIG signed request with authorized key 'pdns010a-pdns010b' and algorithm 'hmac-sha512'
- Log on the secondary server
Nov 03 21:29:26 pdnsb010 pdns_server[34111]: AXFR-in zone: 'zoneNNN.dnslab.org', primary: '46.101.218.115', zone committed with serial 1635974966
- When using the autoprimary/supermaster function of PowerDNS, after
deploying TSIG keys, the setting
allow-unsigned-autoprimary/allow-unsigned-supermastershould be set tonoto only allow TSIG signedNOTIFYto create new zones - On the secondary, the setting
allow-unsigned-notifyshould be set tonoto only allow TSIG signedNOTIFY
6.4.2 Exercise
- Create a new TSIG key (on the primary machine) to secure the zone transfer between the primary and the secondary
- Import the TSIG key on the secondary
- Mark the TSIG key as active for the zone
zoneNNN.dnslab.orgon both sides (see above= - Increment the SOA serial with
pdnsutil - Check that
NOTIFYmessages and AXFR requests are coming, and that the AXFR is TSIG secured (check the log files)
6.5 Negative Trust Anchor in PowerDNS recursor
6.5.1 Dealing with DNSSEC resolver issues
- often DNSSEC validation issues are caused by operational issues
(expired DNSSEC signatures, DS record and DNSKEY KSK mismatch etc)
- Negative Trust Anchors can be used to disable DNSSEC validation for mis-configured domains
- Negative Trust Anchors are defined in RFC 7646 Definition and Use of DNSSEC Negative Trust Anchors
- negative trust anchors (nta) disable DNSSEC validation for a
specific domain for a certain amount of time
- NTA can be used by operators in case a misconfiguration for a remote DNSSEC signed zone is detected. Care should be take to check that the DNSSEC validation failure is indeed a misconfiguration and not attack
- domains with an NTA are processed as if there is no trust-anchor for that domain
- NTAs should always have an operational lifetime
- Don't add a NTA and forget about it
- Re-evaluate the NTA every few days
- Having an NTA configured should flag a warning in the monitoring system
- Remove the NTA as soon as the DNSSEC issue is fixed
- Example: adding an NTA:
% rec_control add-nta example.com 'Signatures expired'
- Example: list active NTAs in the PowerDNS recursor
% rec_control get-ntas
- Example: removing an NTA
% rec_control clear-nta example.com
- Removing all NTAs (be careful!)
% rec_control clear-nta '*'
6.5.2 Exercise: negative trust anchor for failNN.dnssec.works
- Work on the DNS resolver (PowerDNS recursor) machine
- There are the broken DNS zones
fail01.dnssec.workstofail05.dnssec.works - Create negative trust anchor (NTA) for
fail01tofail03in your DNSSEC validating resolver machinednsrNNN - Check that a client can now retrieve DNS data from these zones
$ dig @127.0.0.1 fail01.dnssec.works A
- Remove the NTA for
fail01.dnssec.works. Check that the zone now does not validate and returnSERVFAIL
6.6 DNSSEC signing with PowerDNS
6.6.1 Add DNSSEC to an existing zone
- To sign DNS zone inside PowerDNS, a basic DNSSEC configuration must
be added to the configuration
- For the MySQL/MariaDB backend, the backend needs to have DNSSEC
enabled with
gmysql-dnssec - It is a good idea to have a basic DNSSEC signing policy (default key algorithms and sizes, NSEC3 iterations and how the SOA serial is incremented). Increment the SOA serial is important in a primary/secondary setup with classic DNS zone transfer.
- For the MySQL/MariaDB backend, the backend needs to have DNSSEC
enabled with
# DNSSEC gmysql-dnssec default-ksk-algorithm=rsasha256 default-ksk-size=2048 default-zsk-algorithm=rsasha256 default-zsk-size=1024 max-nsec3-iterations=100 default-soa-edit-signed=EPOCH
- First step of signing a zone is to create a zone signing key (ZSK). For RSA keys, the ZSK usually is smaller than the KSK.
% pdnsutil add-zone-key zoneNNN.dnslab.org ZSK active published 1536 rsasha256 Added a ZSK with algorithm = 8, active=1 Requested specific key size of 1536 bits 1
- Next step is the creation of the key signing key (KSK)
% pdnsutil add-zone-key zoneNNN.dnslab.org KSK active published 2048 rsasha256 Added a KSK with algorithm = 8, active=1 Requested specific key size of 2048 bits 2
- The command
pdnsutil show-zone <zone-name>will show the zone keys, including the delegation signer (DS) record that need to go into the parent zone
% pdnsutil show-zone zoneNNN.dnslab.org This is a Master zone Last SOA serial number we notified: 1012 == 1012 (serial in the database) Metadata items: None Zone has NSEC semantics keys: ID = 1 (ZSK), flags = 256, tag = 37441, algo = 8, bits = 1536 Active Published ( RSASHA256 ) ID = 2 (KSK), flags = 257, tag = 26177, algo = 8, bits = 2048 Active Published ( RSASHA256 ) KSK DNSKEY = zoneNNN.dnslab.org. IN DNSKEY 257 3 8 AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvbsk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMfk2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq408ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3cjHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuKHCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoyqiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWIjsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E= ; ( RSASHA256 ) DS = zoneNNN.dnslab.org. IN DS 26177 8 1 2416dc421e6debc0c0fd75b8742086df862f054f ; ( SHA1 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 2 5993bff9c0f53af0162495f9b5c72a8fc5d05b24602e3905d3f4641da55a6f2c ; ( SHA256 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 4 2810a931cf90eb4977eafdaaa3cfc8d90bb439ab836b3e05b23aef88ea0368f200a1b145472d36efc1b40c3567af3e71 ; ( SHA-384 digest )
- As the keys are active, PowerDNS will start signing the responses with RRSIG records
# dig @localhost zoneNNN.dnslab.org soa +dnssec +multi
; <<>> DiG 9.16.22-Debian <<>> @localhost zoneNNN.dnslab.org soa +dnssec +multi
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44805
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN SOA
;; ANSWER SECTION:
zoneNNN.dnslab.org. 60 IN SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. (
1012 ; serial
3600 ; refresh (1 hour)
1800 ; retry (30 minutes)
3542400 ; expire (5 weeks 6 days)
60 ; minimum (1 minute)
)
zoneNNN.dnslab.org. 60 IN RRSIG SOA 8 3 60 (
20211111000000 20211021000000 37441 zoneNNN.dnslab.org.
InqX6esX3pl2GdGratuae544DO41egiVRLaLIPa41c9H
JqJjr2uMH5IcUtRtfDX4q296SSq5nNL9aouDtrvw+zNN
xGc/0qJ/aVr/uTqEXJBLGVbdZnCjpfvYNrDh3IIMBcSm
2TVifrT6JuGvIRUB/GskXvTYIDZW5DQ3YVP131sp4u9t
SgKWDvdt93N43maqy0imqJKwU7mV+t9Rx+El37c/CQZD
V+ERB5enFiqUr8e08wjc7rvDLAMFzBYbnc+3 )
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Nov 03 19:48:02 UTC 2021
;; MSG SIZE rcvd: 345
- The default authenticated denial of existence is NSEC, so there are NSEC records
% dig @localhost zoneNNN.dnslab.org srv +dnssec +multi
; <<>> DiG 9.16.22-Debian <<>> @localhost zoneNNN.dnslab.org srv +dnssec +multi
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39295
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN SRV
;; AUTHORITY SECTION:
zoneNNN.dnslab.org. 60 IN SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. (
1012 ; serial
3600 ; refresh (1 hour)
1800 ; retry (30 minutes)
3542400 ; expire (5 weeks 6 days)
60 ; minimum (1 minute)
)
zoneNNN.dnslab.org. 60 IN RRSIG SOA 8 3 60 (
20211111000000 20211021000000 37441 zoneNNN.dnslab.org.
InqX6esX3pl2GdGratuae544DO41egiVRLaLIPa41c9H
JqJjr2uMH5IcUtRtfDX4q296SSq5nNL9aouDtrvw+zNN
xGc/0qJ/aVr/uTqEXJBLGVbdZnCjpfvYNrDh3IIMBcSm
2TVifrT6JuGvIRUB/GskXvTYIDZW5DQ3YVP131sp4u9t
SgKWDvdt93N43maqy0imqJKwU7mV+t9Rx+El37c/CQZD
V+ERB5enFiqUr8e08wjc7rvDLAMFzBYbnc+3 )
zoneNNN.dnslab.org. 60 IN NSEC zoneNNN.dnslab.org. A NS SOA RRSIG NSEC DNSKEY
zoneNNN.dnslab.org. 60 IN RRSIG NSEC 8 3 60 (
20211111000000 20211021000000 37441 zoneNNN.dnslab.org.
QYedsQarfZicH7Pbawra6TAUH2XPK6zuH+jaVjKVffOe
GFyCDNwTxIx8U8MT7ntR1mJxUjuFf+byftkS3WkNxxNa
Fs+73xLeWgro+J3zY2t+M4rozZBdHKX0zsU0b/XMDYl+
PW5w+0zgcIoTs7aTexwsHg587TwaluBZI6sQhxLJ0tsB
wPOEu7BoIBhCaTqrgI4aQiK6uO3R9k2f5pieXrxtDHNC
lDf/3cdgIhMPQkpIeB7Pph1f+5bHfZ01JBPd )
;; Query time: 7 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Nov 03 19:48:52 UTC 2021
;; MSG SIZE rcvd: 628
- After making changes to a DNSSEC signed zone, it is always advised
to execute
pdnsutil rectify-zone <zone-name>.rectify-zonewill recreate missing signatures and NSEC/NSEC3 records.rectify-zoneis important when making changes to the zone on the database level or through the API. For zones that are managed through the API, set theAPI-RECTIFYmeta-data on the zone, or make sure thatdefault-api-rectifyis set toyesin the configuration
% pdnsutil rectify-zone zoneNNN.dnslab.org Adding NSEC ordering information
- Send the DS-Record or the DNSKEY record of the KSK to the operator
of the parent zone. The DS-Record(s) and the DNSKEY-Record can be
listed with
pdnsutil show-zone <zonename> - Add a new record
% pdnsutil add-record zoneNNN.dnslab.org test TXT 60 '"Hello PowerDNS"' New rrset: test.zoneNNN.dnslab.org. 60 IN TXT "Hello PowerDNS" test.zoneNNN.dnslab.org. 60 IN TXT "Hello DNSSEC"
- The new record (set) is immediately signed
% dig @localhost test.zoneNNN.dnslab.org. txt +dnssec ; <<>> DiG 9.16.22-Debian <<>> @localhost test.zoneNNN.dnslab.org. txt +dnssec ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10652 ;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags: do; udp: 1232 ;; QUESTION SECTION: ;test.zoneNNN.dnslab.org. IN TXT ;; ANSWER SECTION: test.zoneNNN.dnslab.org. 60 IN RRSIG TXT 8 4 60 20211111000000 20211021000000 37441 zoneNNN.dnslab.org. H0MNWJ/xP9xfLYxaTaqEyhe+jLszDxZ4MP6AR6pz1S3GsHhMktR3/P6u DrBihkZlNMi+7ZhTWHFmndCwd9vK/nnaHZXNV2JL72oMPS4vhXWgw6AP T+mUsOkRyHudJRoASpyOOPhqGxjDVUXanDdpbVAfoEjhWnZ6a+NWC47C 04zT/4NSaIpZPtCIYKftbiPB0CjEFPsViloRNAUFwbYHZ4o9TZYdDekQ nOXAapLooAh0DFk21ijjrVV1jbigS6oV test.zoneNNN.dnslab.org. 60 IN TXT "Hello PowerDNS" test.zoneNNN.dnslab.org. 60 IN TXT "Hello DNSSEC" ;; Query time: 3 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Nov 03 20:03:34 UTC 2021 ;; MSG SIZE rcvd: 346
- After making changes to a DNSSEC signed zone, it is a good idea to
increment the SOA serial a last time and fix the DNSSEC NSEC(3)
chain in the zone with
rectify-zone
% pdnsutil increase-serial zoneNNN.dnslab.org % pdnsutil rectify-zone zoneNNN.dnslab.org
- Check for a successful zone transfer to all secondary DNS server of the zone
6.6.2 Exercise
- Add the required DNSSEC configuration statements to the PowerDNS configuration, check and reload the PowerDNS service
- Add a ZSK and KSK with the ECDSA algorithm to the zone
zoneNNN.dnslab.org - Rectify the zone and increment the SOA serial number
- Show the DS-Record for the zone, send it by email to the trainer
(use
cs@sys4.de) - Wait for the DS-Record to arrive in the parent zone (
dnslab.org) - Query a record from this zone on the PowerDNS recursor machine, check for the AD-Flag that indicates successful DNSSEC validation
6.7 DNSSEC Key-Rollover
6.7.1 ZSK rollover with pre-publication
- To start a ZSK key rollover for a zone on PowerDNS, create and publish (but don't activate) a new ZSK. The new key should have the same algorithm then the previous key. The size can be different.
% pdnsutil add-zone-key zoneNNN.dnslab.org ZSK inactive published 1536 rsasha256 Added a ZSK with algorithm = 8, active=1 Requested specific key size of 1536 bits 3
- The zone should now have 2 ZSK DNSKEY records published
% pdnsutil show-zone zoneNNN.dnslab.org This is a Master zone Last SOA serial number we notified: 1635970166 == 1635970166 (serial in the database) Metadata items: None Zone has NSEC semantics keys: ID = 1 (ZSK), flags = 256, tag = 37441, algo = 8, bits = 1536 Active Published ( RSASHA256 ) ID = 4 (ZSK), flags = 256, tag = 14634, algo = 8, bits = 1536 Inactive Published ( RSASHA256 ) ID = 2 (KSK), flags = 257, tag = 26177, algo = 8, bits = 2048 Active Published ( RSASHA256 ) KSK DNSKEY = zoneNNN.dnslab.org. IN DNSKEY 257 3 8 AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvbsk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMfk2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq408ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3cjHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuKHCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoyqiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWIjsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E= ; ( RSASHA256 ) DS = zoneNNN.dnslab.org. IN DS 26177 8 1 2416dc421e6debc0c0fd75b8742086df862f054f ; ( SHA1 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 2 5993bff9c0f53af0162495f9b5c72a8fc5d05b24602e3905d3f4641da55a6f2c ; ( SHA256 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 4 2810a931cf90eb4977eafdaaa3cfc8d90bb439ab836b3e05b23aef88ea0368f200a1b145472d36efc1b40c3567af3e71 ; ( SHA-384 digest )
- Rectify the zone so that all signatures and NSEC/NSEC3 records are present
% pdnsutil rectify-zone zoneNNN.dnslab.org
- Increment the SOA serial number to trigger
NOTIFYfor zone-transfer
% pdnsutil increase-serial zoneNNN.dnslab.org
- The new ZSK is now visible in the DNS zone
% dig dnskey zoneNNN.dnslab.org +multi
; <<>> DiG 9.16.22-Debian <<>> dnskey zoneNNN.dnslab.org +multi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59184
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN DNSKEY
;; ANSWER SECTION:
zoneNNN.dnslab.org. 38 IN DNSKEY 256 3 8 (
AwEAAa56Jv3sjwd2yKNbbdcoTNMViBFDv3StAD1Kif7+
G/X993ac8cwevgp77dgGx/gmdLTu9/sV3df5/Y31l9j/
55QzquNU4Svxnkbf+4onN9dB0Vzh+ASUzrCTfu592tso
xpM6YxQUbjgYDI8308u/dgcBSsl5uaJjIcxUNUaP/oC0
qn2l4x7TtmHsoMXlrjJB5/oChdvyuU10i0ts3GOpJmka
vuynXawWuE5LQAXxNS+POXbKCHf7dzbtUzAQjFBXAw==
) ; ZSK; alg = RSASHA256 ; key id = 14634
zoneNNN.dnslab.org. 38 IN DNSKEY 256 3 8 (
AwEAAdSEeKfBK/EXKfKtwB1rpSForHhwVBekz2ZyOd+F
uHdNXlCRyhRlok3zUq9BOQLPpqPFm+GGdFttACu3sAeO
aq7NIrpFHVijWwXMX0zBeak7ujwFKlC4cKszfEVB6kaq
m62JyAGQF6Z6mzDz4q/iW8gq1LmtdMwG+ked3lp5zQk/
0MZUBfJcqrya1biDnfOteCv/InoTrydYbFvUNVBe2VlA
FZG7pUhQcZs+CQn8y71GU+pepogCM8IJOiE7Fw+7zQ==
) ; ZSK; alg = RSASHA256 ; key id = 37441
zoneNNN.dnslab.org. 38 IN DNSKEY 257 3 8 (
AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvb
sk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMf
k2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq4
08ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3c
jHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuK
HCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoy
qiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWI
jsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E=
) ; KSK; alg = RSASHA256 ; key id = 26177
;; Query time: 3 msec
;; SERVER: 67.207.67.3#53(67.207.67.3)
;; WHEN: Wed Nov 03 20:28:06 UTC 2021
;; MSG SIZE rcvd: 747
- Wait for the TTL of the DNSKEY record set (60 seconds in our example)
- Activate the new key, deactivate the old key, rectify zone and increment the SOA serial. The new ZSK is now active
% pdnsutil activate-zone-key zoneNNN.dnslab.org 4 % pdnsutil deactivate-zone-key zoneNNN.dnslab.org 1 % pdnsutil rectify-zone zoneNNN.dnslab.org Adding NSEC ordering information % pdnsutil increase-serial zoneNNN.dnslab.org SOA serial for zone zoneNNN.dnslab.org set to 1635971832
- Check that the signatures on the SOA record are now created by the new ZSK (Keytag 14634 in this example)
% dig soa zoneNNN.dnslab.org +multi +dnssec
; <<>> DiG 9.16.22-Debian <<>> soa zoneNNN.dnslab.org +multi +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27737
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN SOA
;; ANSWER SECTION:
zoneNNN.dnslab.org. 60 IN SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. (
1635971879 ; serial
3600 ; refresh (1 hour)
1800 ; retry (30 minutes)
3542400 ; expire (5 weeks 6 days)
60 ; minimum (1 minute)
)
zoneNNN.dnslab.org. 60 IN RRSIG SOA 8 3 60 (
20211111000000 20211021000000 14634 zoneNNN.dnslab.org.
NwewpF4JnrwWOj6TInXN4mcczGySQ21uVZJXkCzQcLnH
GrA8sZwG16yM97YjYSIUf2HqRSlAs1e7sxWwI+QACLg5
BG9W3qelTjeczV3aQex5r2dsjOofPuAPTth8FmOJslPB
9klh3RDUtWLTmeDzr82lucc4NtvU0zFUpvL1UOwLWg0x
J/N/EshkZBwN9odpGcZU+FIyaci7hs/FYXSnJS0FD3Tp
MJcsSjt9u4aNtwQbBzWe/jIteyDlZxcmk0lH )
;; Query time: 27 msec
;; SERVER: 67.207.67.3#53(67.207.67.3)
;; WHEN: Wed Nov 03 20:37:59 UTC 2021
;; MSG SIZE rcvd: 345
- Wait for the maximum TTL in the zone
- Remove the old ZSK from the zone
% pdnsutil remove-zone-key zoneNNN.dnslab.org 1 % pdnsutil rectify-zone zoneNNN.dnslab.org Adding NSEC ordering information % pdnsutil increase-serial zoneNNN.dnslab.org SOA serial for zone zoneNNN.dnslab.org set to 1635972173
- The zone should now only have one ZSK left in the DNSKEY record set
% pdnsutil show-zone zoneNNN.dnslab.org Nov 03 20:41:31 gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. Nov 03 20:41:31 gmysql Connection successful. Connected to database 'powerdns' on '/run/mysqld/mysqld.sock'. This is a Master zone Last SOA serial number we notified: 1635971832 == 1635971832 (serial in the database) Metadata items: None Zone has NSEC semantics keys: ID = 4 (ZSK), flags = 256, tag = 14634, algo = 8, bits = 1536 Active Published ( RSASHA256 ) ID = 2 (KSK), flags = 257, tag = 26177, algo = 8, bits = 2048 Active Published ( RSASHA256 ) KSK DNSKEY = zoneNNN.dnslab.org. IN DNSKEY 257 3 8 AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvbsk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMfk2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq408ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3cjHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuKHCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoyqiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWIjsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E= ; ( RSASHA256 ) DS = zoneNNN.dnslab.org. IN DS 26177 8 1 2416dc421e6debc0c0fd75b8742086df862f054f ; ( SHA1 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 2 5993bff9c0f53af0162495f9b5c72a8fc5d05b24602e3905d3f4641da55a6f2c ; ( SHA256 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 4 2810a931cf90eb4977eafdaaa3cfc8d90bb439ab836b3e05b23aef88ea0368f200a1b145472d36efc1b40c3567af3e71 ; ( SHA-384 digest )
- The new DNSKEY record set should also be seen in the DNS zone
% dig dnskey zoneNNN.dnslab.org +multi
; <<>> DiG 9.16.22-Debian <<>> dnskey zoneNNN.dnslab.org +multi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16831
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN DNSKEY
;; ANSWER SECTION:
zoneNNN.dnslab.org. 60 IN DNSKEY 256 3 8 (
AwEAAa56Jv3sjwd2yKNbbdcoTNMViBFDv3StAD1Kif7+
G/X993ac8cwevgp77dgGx/gmdLTu9/sV3df5/Y31l9j/
55QzquNU4Svxnkbf+4onN9dB0Vzh+ASUzrCTfu592tso
xpM6YxQUbjgYDI8308u/dgcBSsl5uaJjIcxUNUaP/oC0
qn2l4x7TtmHsoMXlrjJB5/oChdvyuU10i0ts3GOpJmka
vuynXawWuE5LQAXxNS+POXbKCHf7dzbtUzAQjFBXAw==
) ; ZSK; alg = RSASHA256 ; key id = 14634
zoneNNN.dnslab.org. 60 IN DNSKEY 257 3 8 (
AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvb
sk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMf
k2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq4
08ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3c
jHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuK
HCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoy
qiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWI
jsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E=
) ; KSK; alg = RSASHA256 ; key id = 26177
;; Query time: 135 msec
;; SERVER: 67.207.67.3#53(67.207.67.3)
;; WHEN: Wed Nov 03 20:43:36 UTC 2021
;; MSG SIZE rcvd: 535
6.7.2 KSK rollover with double-signing
- To start a KSK rollover with PowerDNS, create, publish and activate a new KSK (same algorithm as existing KSK, size can differ)
% pdnsutil add-zone-key zoneNNN.dnslab.org KSK active published 2048 rsasha256 Added a KSK with algorithm = 8, active=1 Requested specific key size of 2048 bits 5 % pdnsutil rectify-zone zoneNNN.dnslab.org % pdnsutil increase-serial zoneNNN.dnslab.org
- The zone should now have 2 KSK DNSKEY records
% pdnsutil show-zone zoneNNN.dnslab.org This is a Master zone Last SOA serial number we notified: 1635972173 != 1635972638 (serial in the database) Metadata items: None Zone has NSEC semantics keys: ID = 4 (ZSK), flags = 256, tag = 14634, algo = 8, bits = 1536 Active Published ( RSASHA256 ) ID = 2 (KSK), flags = 257, tag = 26177, algo = 8, bits = 2048 Active Published ( RSASHA256 ) KSK DNSKEY = zoneNNN.dnslab.org. IN DNSKEY 257 3 8 AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvbsk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMfk2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq408ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3cjHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuKHCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoyqiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWIjsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E= ; ( RSASHA256 ) DS = zoneNNN.dnslab.org. IN DS 26177 8 1 2416dc421e6debc0c0fd75b8742086df862f054f ; ( SHA1 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 2 5993bff9c0f53af0162495f9b5c72a8fc5d05b24602e3905d3f4641da55a6f2c ; ( SHA256 digest ) DS = zoneNNN.dnslab.org. IN DS 26177 8 4 2810a931cf90eb4977eafdaaa3cfc8d90bb439ab836b3e05b23aef88ea0368f200a1b145472d36efc1b40c3567af3e71 ; ( SHA-384 digest ) ID = 5 (KSK), flags = 257, tag = 45824, algo = 8, bits = 2048 Active Published ( RSASHA256 ) KSK DNSKEY = zoneNNN.dnslab.org. IN DNSKEY 257 3 8 AwEAAaicwPSEdFMZAfofnKAVbAb6nzZyRqYW+1GLNIMKFRw/YZ97Gi+ZfAjkJWOkeVLbNmeKgZSMz185NkoSwlWFdrJv8hR43Hu1UJgMdKr3EzKti7W8U3YwEnBl7W1yv518LhOPFata3H5i082/qiP2c9j4JXmH1fC1TqtwTDGDpS9myPgidRgMPqeqtZ+5aQYfcEo+Kw0EJT0xD1lUURGwUztEdM4nfjIcaMf6o3//Te5KJZEhhesBgUvpbYN13ZQjA3EmzcQqoFj8HW9QZ8lC7JlYxHucA+SluGgg4BmkefAlUhuPAuF9cLvri720DVATqSQwezTIgJNromdhfjnpvec= ; ( RSASHA256 ) DS = zoneNNN.dnslab.org. IN DS 45824 8 1 c2eff1df58bf152036fd8d556553c1096136f0d0 ; ( SHA1 digest ) DS = zoneNNN.dnslab.org. IN DS 45824 8 2 33509b6659026377b337b7009442f45ae0d2a08b21e3ba726094bbac0f121635 ; ( SHA256 digest ) DS = zoneNNN.dnslab.org. IN DS 45824 8 4 213c2eba14d47e7418feea186ff0c565accd81cc65353524bff2c9894fb203995fea8b868046932a7d3bedb20351ee99 ; ( SHA-384 digest )
- Two KSK DNSKEY records are in the zone
% dig dnskey zoneNNN.dnslab.org +multi
; <<>> DiG 9.16.22-Debian <<>> dnskey zoneNNN.dnslab.org +multi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3417
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN DNSKEY
;; ANSWER SECTION:
zoneNNN.dnslab.org. 60 IN DNSKEY 256 3 8 (
AwEAAa56Jv3sjwd2yKNbbdcoTNMViBFDv3StAD1Kif7+
G/X993ac8cwevgp77dgGx/gmdLTu9/sV3df5/Y31l9j/
55QzquNU4Svxnkbf+4onN9dB0Vzh+ASUzrCTfu592tso
xpM6YxQUbjgYDI8308u/dgcBSsl5uaJjIcxUNUaP/oC0
qn2l4x7TtmHsoMXlrjJB5/oChdvyuU10i0ts3GOpJmka
vuynXawWuE5LQAXxNS+POXbKCHf7dzbtUzAQjFBXAw==
) ; ZSK; alg = RSASHA256 ; key id = 14634
zoneNNN.dnslab.org. 60 IN DNSKEY 257 3 8 (
AwEAAaicwPSEdFMZAfofnKAVbAb6nzZyRqYW+1GLNIMK
FRw/YZ97Gi+ZfAjkJWOkeVLbNmeKgZSMz185NkoSwlWF
drJv8hR43Hu1UJgMdKr3EzKti7W8U3YwEnBl7W1yv518
LhOPFata3H5i082/qiP2c9j4JXmH1fC1TqtwTDGDpS9m
yPgidRgMPqeqtZ+5aQYfcEo+Kw0EJT0xD1lUURGwUztE
dM4nfjIcaMf6o3//Te5KJZEhhesBgUvpbYN13ZQjA3Em
zcQqoFj8HW9QZ8lC7JlYxHucA+SluGgg4BmkefAlUhuP
AuF9cLvri720DVATqSQwezTIgJNromdhfjnpvec=
) ; KSK; alg = RSASHA256 ; key id = 45824
zoneNNN.dnslab.org. 60 IN DNSKEY 257 3 8 (
AwEAAdmaHnizfuBb89XXhYBoQBnsJ/d+K7zkelu8rAvb
sk3pzgwWMEufNXEqBxyQxxKYmqk/m+Wcq2UtuGnRugMf
k2iaCod9DHp2iJj9qZ6C2Gqv9jVzwK1OE3yHq9xTuzq4
08ibgrxQvhZwYcH4mbqTlopFz/qACNKYdr52zCFnmK3c
jHSphNqo3pGlBBGFLrXdLS8oHW6Ec+G7DObTqk+rGUuK
HCStG0qPKoKj20L0j2frmcG5h5X0aH+7vHyBeikwuJoy
qiwmEg0PYmknAnicuh3ubcPB5P+5ZcItpe6xY52eKqWI
jsjcZI0aUmlOqI/ISuwP5b7UhYPgEc8JWlu6T9E=
) ; KSK; alg = RSASHA256 ; key id = 26177
;; Query time: 215 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Wed Nov 03 20:54:11 UTC 2021
;; MSG SIZE rcvd: 811
- Send the DS-Record or the DNSKEY record of the new KSK to the operator of the parent zone
- Wait for the new DS record to appear in the parent zone
- Remove the old KSK from the zone
% pdnsutil remove-zone-key zoneNNN.dnslab.org 2 % pdnsutil rectify-zone zoneNNN.dnslab.org Adding NSEC ordering information % pdnsutil increase-serial zoneNNN.dnslab.org SOA serial for zone zoneNNN.dnslab.org set to 1635973094
- KSK rollover completed
6.8 PowerDNS and NSEC3 signing
- Zones can switch from NSEC to NSEC3 and back at any time
- Use
pdnsutil set-nsec3 <zone-name> <nsec3-parameter>to switch to NSEC3 - Use
pdnsutil unset-nsec3 <zone-name>to switch back to NSEC
% pdnsutil set-nsec3 zoneNNN.dnslab.org "1 0 10 -" NSEC3 set, please rectify your zone if your backend needs it % pdnsutil rectify-zone zoneNNN.dnslab.org Adding NSEC3 hashed ordering information for 'zoneNNN.dnslab.org' % pdnsutil increase-serial zoneNNN.dnslab.org SOA serial for zone zoneNNN.dnslab.org set to 1635973224
- The zone is now secured with NSEC3
# dig @localhost xyz.zoneNNN.dnslab.org +dnssec +multi +norec
; <<>> DiG 9.16.22-Debian <<>> @localhost xyz.zoneNNN.dnslab.org +dnssec +multi +norec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 33387
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;xyz.zoneNNN.dnslab.org. IN A
;; AUTHORITY SECTION:
zoneNNN.dnslab.org. 60 IN SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. (
1636009907 ; serial
3600 ; refresh (1 hour)
1800 ; retry (30 minutes)
3542400 ; expire (5 weeks 6 days)
60 ; minimum (1 minute)
)
zoneNNN.dnslab.org. 60 IN RRSIG SOA 8 3 60 (
20211118000000 20211028000000 14634 zoneNNN.dnslab.org.
QOtJT7bfN6OvuVbWBTn326PwCuqJ717jQ+kTo61Nymhe
ReOKa6IvIyiUBCKXxyrvzhASxR3CAw0x3CukL3Gwdm4F
kS3nILwsyKIv/IeREpXLcU1KrUK4fxAXQ81IJh1R96IH
s0xAeurl4hdzGgYeydLqGlRdhAics8vGpuqPtnzBybDp
5SImpw7KGI50229jpdbgA67c89E4nAkBszLYI8IfhJKM
rN0zj7JXNJPHGmA+oeCQnBy5yh+E/6IeTlA2 )
6egermavujrtij09ssmf3r4kg1bhbihl.zoneNNN.dnslab.org. 60 IN NSEC3 1 0 10 - (
6TNSMUD7JF5CKL4QMPHMSJ1VCVNIGP2I
A NS SOA RRSIG DNSKEY NSEC3PARAM )
6egermavujrtij09ssmf3r4kg1bhbihl.zoneNNN.dnslab.org. 60 IN RRSIG NSEC3 8 4 60 (
20211118000000 20211028000000 14634 zoneNNN.dnslab.org.
VXf8bF+/EqVndIzWhbUlsuJJ1lNHaF7bYnOpZ3bm9Ij9
XOFtG8Oa+YBg4bAr82B2Ra565jVK4uAZ5tL1/69H7xlj
BIkZ74KSRgoeI69yjT1fzN04l7V1RHDEjZtz6/NFy1qG
9R+J9/vVZXdhJBPhlia6+A5x5+RDdLlZcB2wrWjdvjpR
z4hfoy5T4p3MHx4rXRDp3zNQrRMkcdW3Kg/mK1+a5rYA
1/WJl+pCVaWLTspwY6wnybNnmx/eBf6H0bO5 )
6tnsmud7jf5ckl4qmphmsj1vcvnigp2i.zoneNNN.dnslab.org. 60 IN NSEC3 1 0 10 - (
34KQL2SE77RDH2S50C8DR19DI2OB75VD
TXT RRSIG )
6tnsmud7jf5ckl4qmphmsj1vcvnigp2i.zoneNNN.dnslab.org. 60 IN RRSIG NSEC3 8 4 60 (
20211118000000 20211028000000 14634 zoneNNN.dnslab.org.
fl0z50DIEOtombxYRST2ANGsLtxUSX2Yo6ceMPYTHnvS
5gvw3m7+TDkTRVB39Ezcw/W9y7aPMp6HNCk0+ZCytWHI
4E4tV0uzrN/dVYSCv1+ooX54JbF23Zk7C76MYKjYO33V
cOarWoA8VYiy3uKaKyE752tUWGhVW6X8iQYQbQ0oZmXM
z2gOVlPnxLsrV5IRyhRIaFhKTFfcu4TA54l+Dpgz7rd4
x3/eHepeaPPlFsBclKZ3rmZ+gIQ1YqAPzqpz )
;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Nov 04 07:11:47 UTC 2021
;; MSG SIZE rcvd: 992
- The
NSEC3PARAMrecord in the zone
% dig @localhost nsec3param zoneNNN.dnslab.org +dnssec +multi +norec
; <<>> DiG 9.16.22-Debian <<>> @localhost nsec3param zoneNNN.dnslab.org +dnssec +multi +norec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35689
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN NSEC3PARAM
;; ANSWER SECTION:
zoneNNN.dnslab.org. 60 IN NSEC3PARAM 1 0 10 -
zoneNNN.dnslab.org. 60 IN RRSIG NSEC3PARAM 8 3 60 (
20211118000000 20211028000000 14634 zoneNNN.dnslab.org.
JTPUqdF6YqfhcpUBHMomhqspp5ijzDCOiNMXwRbQm1Xp
VGTOo8CNRWNCbCnYgpjILz5itUcLSnJPzz6gdKXGuGVI
sxFVR/3OKLweaj+pWrlgSkRG1mskYiFN58Y2PRL42P6j
oYCXJOyj/J5VcQBJyKWoJWP801t+581hBNEkZOVaELeQ
HjH2shbKX5un/0Bc2f4pKM/8W4a2O/K/0avSeFGKklIK
g3C4NZKaYFkAxaGapAMQp5CXrpilt7moAXmp )
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Nov 04 07:12:54 UTC 2021
;; MSG SIZE rcvd: 306
6.8.1 NSEC3 "narrow" mode
- PowerDNS supports a special NSEC3 mode called the narrow mode
- In this mode, it will create NSEC3 records on the fly that cover just the minimal gap in the zone from the requested domain name
- NSEC3 narrow prevents zone walking
- NSEC3 narrow mode requires life-signing, which demands that all
authoritative server have access to the private DNSSEC keys (a
potential security risk)
- All PowerDNS server authoritative for a NSEC3 narrow signed zone should operate in native mode (not master / slave mode)
- narrow mode is recommended for zones that contain sensitive data (such as email addresses -> SMIMEA or OPENPGPKEY data)
- To switch to NSEC3 narrow mode
% pdnsutil set-nsec3 zoneNNN.dnslab.org "1 0 10 -" narrow % pdnsutil rectify-zone zoneNNN.dnslab.org % pdnsutil increase-serial zoneNNN.dnslab.org
- Narrow-Mode NSEC3 records
% dig srv zoneNNN.dnslab.org +dnssec @1.1.1.1 +multi
; <<>> DiG 9.16.22-Debian <<>> srv zoneNNN.dnslab.org +dnssec @1.1.1.1 +multi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19702
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;zoneNNN.dnslab.org. IN SRV
;; AUTHORITY SECTION:
zoneNNN.dnslab.org. 60 IN SOA pdns010a.dnslab.org. hostmaster.zoneNNN.dnslab.org. (
1635973813 ; serial
3600 ; refresh (1 hour)
1800 ; retry (30 minutes)
3542400 ; expire (5 weeks 6 days)
60 ; minimum (1 minute)
)
zoneNNN.dnslab.org. 60 IN RRSIG SOA 8 3 60 (
20211111000000 20211021000000 14634 zoneNNN.dnslab.org.
SYfqwgtasVpUhKpBPAutbNTeXdGuY3A2F8Nv0cYFwqVI
uJDeJiRpUVk9HbqPqh6b7Q7QNFt7c5lD9onT+kegkqHR
5DEKAzPMPcNTdqx9ZjQrYXZrDpin7Zo/Mf+kEPCMArgC
opDlfppFhEcUSZL3mHU/WPJlj1Zr9JwIq+Ll+TCiaJ02
tY4a59LTEcB10HNrD5KHdURU7EE9uwg6BhEFXzvNAnW7
uHTYbd6v8K7yj2bukDAn3qfHTwBpgcgRKE3u )
6egermavujrtij09ssmf3r4kg1bhbihl.zoneNNN.dnslab.org. 60 IN NSEC3 1 0 10 - (
6EGERMAVUJRTIJ09SSMF3R4KG1BHBIHM
A NS SOA RRSIG DNSKEY NSEC3PARAM )
6egermavujrtij09ssmf3r4kg1bhbihl.zoneNNN.dnslab.org. 60 IN RRSIG NSEC3 8 4 60 (
20211111000000 20211021000000 14634 zoneNNN.dnslab.org.
MHO22RkxtdJmcXsDeij7JuKVHMLVF1SwvreztmCVAebK
/dGv98g+843LoCXi2yDRmYWeKtVodsATmr5+SI3JV4a5
TGG9JMThzcJ5ytHHYXp+17DoSygx0ppI8y8mbAYFBhLM
1HLpSBWHw9YzTzJhRqkeG7R0E6hTSX1y0fSJt58ov+hU
MyiwZwN9HMw+ulDLDa5DxEUXfNar+PS9WC08EAemiitZ
6a2xgH0fHCHWky+go2DddRrQvM6BkTIMsvc9 )
;; Query time: 39 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Wed Nov 03 21:10:23 UTC 2021
;; MSG SIZE rcvd: 667
6.9 DNSSEC Troubleshooting
6.9.1 Checking DNS resolution issues
- dig
The DNS name resolution tool
digcan be used to test the general function of a DNS resolver, or to test if an error condition exist at the remote DNS authoritative servers of a domain.- testing one DNS resolver over UDP
To test the general connectivity and operation of a DNS resolver, a query for well known DNS data can be sent, such as for the list of name-server (NS records) of the root zone
".". The answer should contain the list of all 13 root name server in the Internet (with the namesa-m.root-servers.net)$ dig @IP-of-DNS-resolver NS .
- what are reasons we recommend using the IP address of a resolver instead of its name?
- Testing one DNS resolver over TCP
The DNS resolvers must also be reachable over TCP. To send a query via TCP, add the
+tcpflag to queries.$ dig @IP-of-DNS-resolver NS . +tcp
- you can save 33% typing by using
+vcinstead of+tcp. What doesvcdo? Check the manual page fordig(1).
- you can save 33% typing by using
- Testing reachability of all authoritative DNS servers
The
digfunction+nssearchwill first query all NS records for a given domain and then will try to query directly (without going to a DNS-resolver) the authoritative DNS servers of that domain:$ dig @IP-of-DNS-resolver example.com +nssearch
The function will print out the SOA record of the zone (here
example.com) for each DNS server that has send an answer to the query, including the SOA serial, the IPv4 and/or IPv6 address and the round-trip-time (RTT) of the query.All SOA serial numbers should show the same number, else there might be an issue with zone synchronization via zone transfer which might be a possible cause for DNS lookup problems.
- Which type of DNS servers (authoritative, recursive, primary, secondary) are at fault if the SOA serial numbers of a zone are not in sync? Who can correct the fault?
- Testing the resolution chain
The function
+traceindigwill trace the DNS name resolution starting from the root DNS server system down to the requested name.$ dig @IP-of-DNS-resolver example.com +trace
Only the very first query to find the root-server addresses will be done towards the DNS resolver given in the command, all other queries will be sent directly to the authoritative DNS servers. This function tests and prints one of usually many possible DNS resolution paths. A successful return of the command does not indicate that the resolution path is without errors, it is only an indication that at least one successful path exists.
- Testing for DNSSEC validation issues
If a DNS query returns a
SERVFAILanswer, it can be a DNSSEC validation issue at the DNS resolver, or it can be some kind of server malfunction on the DNS resolver or the remote authoritative server.In order the check for DNSSEC validation issues, the administrator can send a DNS query with the
+cdflag (Checking Disabled). With this flag set, the DNS resolver will skip DNSSEC validation and will return the DNS data todigeven in case the DNSSEC validation would fail.So if a DNS query returns data when
+cdis set, but returnsSERVFAILwhen+cdis not set, this indicates a DNSSEC validation issue. If the answer is alwaysSERVFAIL, it is some other kind of problem (usually not DNSSEC).
- testing one DNS resolver over UDP
- External web services to check DNS
Several website services exist that help DNS administrators to check the health of a DNS system
- Zonemaster
The website Zonemaster https://zonemaster.net is a collaboration between the French TLD registry AFNIC and the Swedish registry IIS. The website takes a domain name and will generate a report of errors and best practice recommendations of the setup of this domain name.
- DNSViz
DNSViz https://dnsviz.net is a tool for visualizing the status of a DNS zone. It provides a visual analysis of the DNSSEC authentication chain for a domain name and its resolution path in the DNS namespace, and it lists configuration errors detected by the tool.
- Zonemaster
6.9.2 Looking into DNSSEC validation issues
DNSSEC validation issues are often a problem with misconfiguration at the authoritative DNS server side of the domain, not an issue of the DNS resolver system. However to be able to debug DNSSEC issues, for example to decide if an NTA (negative trust anchor) should be inserted into the DNS resolver system to temporarily disable DNSSEC validation for a specific domain, the DNSSEC validation issue should be investigated first.
- DNSSEC validation troubleshooting with "delv"
The tool
delvis part of the BIND 9 DNS server and implements a full DNS resolver and DNSSEC validator inside the command line tool. This tool works very similarly todig(and shares the same command line syntax), but wheredigalways needs a DNS resolver to get the DNS information,delvcan query the data and can validate the DNSSEC information itself. - Message trace
The flag
+mtraceenables the message tracing indelv, the tool will print all DNS queries and answers during the processing of the query.$ delv example.com +mtrace
- Validation trace
The flag
+vtracewill print a debug trace of all DNSSEC validation steps the tool will do in order to validate the received DNS answers$ delv example.com +vtrace
- DNSSEC path validation with drill
The tool
drillis part of the LDNS tools (Debian/Ubuntu packageldnsutils) and is adiglookalike tool with additional features. One notable feature is the function to trace the DNSSEC validation and to print the DNSSEC chain-of-trust together with the DNSSEC key information.drillrequires the current DNSSEC root trust anchor in a file to be able to work. This trust anchor can be received withdrill, but also withdigordelve:$ dig @a.root-servers.net . DNSKEY | grep 257 > root.key
This DNSSEC root trust-anchor key can be used to do a DNSSEC chain chase with
drill:$ drill -SD -k root.key example.com
- In the example above we fetched the root DNSKEY with
dig. Is this method for obtaining the root DNSKEY record foolproof, and do you consider it secure?
- In the example above we fetched the root DNSKEY with
6.10 Response Policy Zones (RPZ)
- RPZ is an RDNS security mechanism to protect queriers from Internet dangers.
- It is like a firewall. RPZ prevents access to domain names identified as disreputable.
- A domain name identified as disreputable triggers a policy with an
action that denies normal resolution.
- E.G. a domain name in a URL known for having malware, gets an NXDOMAIN response.
- RPZs are already being widely implemented, but are still only a draft RFC: https://tools.ietf.org/html/draft-vixie-dnsop-dns-rpz (expired 12/2018)
- other RPZ implementations: Bind 9, Unbound 1.11+, policy.rpz (Knot) - partial support, commercial DNS products, …
- RPZ policies are implemented in zone files.
- RPZs have some unique values, but conform to Master File Format.
- The RPZ zones are deployed on DNS resolver, not on auth servers.
- A DNS resolver is usually the secondary to a central RPZ management server that hosts the primary RPZ zones
- There is no delegation and the NS RRs are unused.
- An RPZ typically has policies for unrelated names. E.G.:
www.verybad.org 30 IN CNAME google.com. evilstuff.net 30 IN CNAME google.com.
- Note: the owner names in the example above are not fully qualified (FQDN)
- There are five triggers for an RPZ policy.
- Two are based on the query.
- Three are based on the RDATA of the response.
- For some of the triggers, special labels are required in the RR owner name.
- There are six actions that a policy can trigger.
- NXDOMAIN is one, the others are covered soon.
6.10.1 Policy Triggers Based on The Query
- QNAME: The queried domain-name triggers the policy.
- This is the most common trigger.
- No special label is required for the owner name.
- Client IP: The client's address triggers the policy.
- The label
.rpz-client-ipis used in the owner name.
- The label
6.10.2 Policy Triggers Based on The Response
- Response IP: The IP address in the RR triggers the policy.
- This is only applicable to
A&AAAARRs. - It is only applicable to the Answer section of the DNS message.
- The label
.rpz-ipis used in the owner name.
- This is only applicable to
- NSDNAME: Any NS referral in the path to getting a final response
triggers the policy.
- The label
.rpz-nsdnameis used in the owner name.
- The label
- NSIP: An IP address of a NS in the path of getting a final
response triggers the policy.
- The label
.rpz-nsipis used in the owner name.
- The label
p>
6.10.3 Policy Actions
- Six actions are available when a policy is triggered:
- Respond with local data trapping the query in a walled garden. (Most commonly this is a CNAME.)
- Respond NXDOMAIN
- Respond NOERROR/NODATA
- Respond normally (passthru)
- Respond with the TC flag
- Drop the query
- The bold actions are most common.
- When more than one action could apply (e.g. NXDOMAIN and passthru), precedence rules select which is used. The rules are beyond the scope of this course.
6.10.4 PowerDNS recursor RPZ configuration
- PowerDNS can load RPZ zones from files or transfer a RPZ zone via standard DNS zone transfer
- See PowerDNS documentation on RPZ for the details
- Example: loading an RPZ zone from a file inside the PowerDNS
recursor Lua configuration file
/etc/powerdns/recursor.lua
-- RPZ from file
rpzFile("/etc/powerdns/rpz/malware.rpz", {defpol=Policy.NXDOMAIN})
- Loading a RPZ zone via zone transfer
-- RPZ via Zone transfer
rpzPrimary({"192.0.2.4","192.0.2.5:5301"}, "policy.rpz", {defpol=Policy.Drop})
6.10.5 RPZ: Zone File
- The response policy zone is not delegated and NS RRs are unused.
- The draft RFC recommends the convention of using
localhost.
- The draft RFC recommends the convention of using
- Other than the
MNAME, all fields in theSOAshould be valid and reasonable for the sake of any secondary using the RPZ.
$TTL 1h $ORIGIN rpz-z01. @ SOA localhost. pm.example.com. 1 4h 1h 8w 1h NS localhost.
- The domain name below is being declared disreputable.
- The owner names should NOT be FQDNs!
- A
CNAMEto the root,., is RPZ's code for anNXDOMAINaction.$TTL 1h $ORIGIN rpz-z01. @ SOA localhost. pm.example.com. 1 4h 1h 8w 1h NS localhost. evilstuff.com CNAME . ; NXDOMAIN - Wildcards usage in RPZ files is common.
- Also match everything under
evilstuff.com.
*.evilstuff.com CNAME . ; NXDOMAIN
- Also match everything under
- A CNAME to
*.is RPZ's code for aNODATAaction.badplace.us CNAME *. ; NOERROR/NODATA *.badplace.us CNAME *. ; NOERROR/NODATA
- Local Data is a standard RR without any special RPZ
encoding. Most commonly, a
CNAMEis used to point to a walled garden.vile.org CNAME fbi.gov. ; redirect *.vile.org CNAME fbi.gov. ; redirect
- A
CNAMEto the RPZ special targetrpz-drop.makes the RDNS server to simply drop the query (no response is sent).- The querier will eventually time-out.
yuck.reddit.com CNAME rpz-drop. ; drop
- A
CNAMEto the RPZ special targetrpz-tcp-only.makes the DNS resolver server set theTCflag (truncated) in the response.- A legitimate querier will re-query over TCP. This is tool to mitigate reflection attacks.
innocent.com CNAME rpz-tcp-only. ; truncate *.innocent.com CNAME rpz-tcp-only. ; truncate
6.10.6 Client IP Address Trigger
- To trigger on the querier's IP, use the
.rpz-client-ipencoding. The IPv4 address is reversed like in a PTR RR, but an additional first label indicates the netmask.16.0.0.31.172.rpz-client-ip CNAME rpz-passthru. 12.0.0.16.172.rpz-client-ip CNAME rpz-drop. 32.1.0.0.127.rpz-client-ip CNAME rpz-passthru.
- Drop traffic from all class B private clients 172.16/12 except the 172.31/16 block which is not subject to any policies. The 127.0.0.1 host is also except for policies, which is useful for testing.
- IPv6 addresses are reversed per four hex-digit field. Colons are
replaced by periods. The double-colon for zero compression with
"zz". Zero suppression and zero compression are required. The
addresses shown are:
2001:db8:bad::/64::1/12864.zz.bad.db8.2001.rpz-client-ip CNAME rpz-drop. 128.1.zz.rpz-client-ip CNAME rpz-passthru.
6.10.7 Response IP Address Trigger
- If the given IP addresses appear in
AorAAAAanswer sections, an action is triggered.- In the example, the IPs are associated with dangers on the
Internet, and get an
NXDOMAINresponse.192.0.2.99/322001:db8:ea::/48
32.99.2.0.192.rpz-ip CNAME . ; NXDOMAIN 48.zz.ea.db8.2001.rpz-ip CNAME . ; NXDOMAIN
- In the example, the IPs are associated with dangers on the
Internet, and get an
6.10.8 NS Domain-Name and NS IP Triggers
- If a referral contains
ns1.badactor.chor a referral'sARR is198.51.100.1, the response will beNXDOMAIN.ns1.badActor.ch.rpz-nsdname CNAME . ; NXDOMAIN 32.1.100.51.198.rpz-nsip CNAME . ; NXDOMAIN
6.10.9 RPZ - the full example
- the full RPZ zone with different trigger and actions
$TTL 1h $ORIGIN rpz-z01. @ SOA localhost. pm.example.com. 1 4h 1h 8w 1h NS localhost. evilstuff.com CNAME . ; NXDOMAIN *.evilstuff.com CNAME . ; NXDOMAIN badplace.us CNAME *. ; NOERROR/NODATA *.badplace.us CNAME *. ; NOERROR/NODATA vile.org CNAME fbi.gov. ; redirect *.vile.org CNAME fbi.gov. ; redirect yuck.reddit.com CNAME rpz-drop. ; drop innocent.com CNAME rpz-tcp-only. ; truncate *.innocent.com CNAME rpz-tcp-only. ; truncate 16.0.0.31.172.rpz-client-ip CNAME rpz-passthru. ; permit 12.0.0.16.172.rpz-client-ip CNAME rpz-drop. ; drop 32.1.0.0.127.rpz-client-ip CNAME rpz-passthru. ; permit 64.zz.bad.db8.2001.rpz-client-ip CNAME rpz-drop. ; drop 128.1.zz.rpz-client-ip CNAME rpz-passthru. ; permit 32.99.2.0.192.rpz-ip CNAME . ; NXDOMAIN 48.zz.ea.db8.2001.rpz-ip CNAME . ; NXDOMAIN ns1.badActor.ch.rpz-nsdname CNAME . ; NXDOMAIN 32.1.100.51.198.rpz-nsip CNAME . ; NXDOMAIN
6.10.10 RPZ Data Feeds
- The site https://dnsrpz.info maintains a list of providers of reputation data.
- Different techniques are used to access the feed.
- For example SpamHaus makes it available via zone transfer (AXFR/IXFR).
- Prices vary. Since 2018-02 SpamHaus has a free but very limited service: https://www.spamhaus.org/news/article/669
6.10.11 Response-Policies without RPZ
- Limited RPZ functionality is available without RPZ.
- A DNS resolver server can be authoritative for zones to block or wall garden.
- If there are 1000 zones, the server must be authoritative for all 1000.
- With RPZ, only one zone is required.
6.10.12 RPZ Notes
- The following types must not be RPZ data:
SOA,NS,DNAME, all DNSSEC related records
6.10.13 Exercise
- Download the RPZ generator from
https://raw.githubusercontent.com/ohrrkan/bind-rpz/main/bind-rpz.py
- This Python script will generate a RPZ zone from public available ad-blocking lists
- Execute the Python script to generate the zone-file. Inspect the zone file
- Load the RPZ file into the PowerDNS recursor from the Lua configuration file, restart the PowerDNS recursor
- Dump the RPZ file from the running PowerDNS memory into a new file to validate that the RPZ zone is loaded
- Query the name
ad-channel.wikawika.xyzfrom your PowerDNS recursor and from Quad9/Cloudflare public DNS. You should see aNOERROR/NODATAanswer from your PowerDNS recursor, and a regular answer from the public DNS services - Change the RPZ Policy for this zone from
NODATAtoNXDOMAIN - Use
digto verify that the return status is nowNXDOMAIN
6.10.14 Solution
- Download Python script
wget https://raw.githubusercontent.com/ohrrkan/bind-rpz/main/bind-rpz.py
- Execute Python scrip to crate the RPZ zone file
% python3 bind-rpz.py % ls -l total 2320 -rw-r--r-- 1 root root 1536 Nov 3 22:08 bind-rpz.py -rw-r--r-- 1 root root 2370166 Nov 3 22:08 db.banlist
- Inspect the RPZ zone
% head db.banlist
$TTL 1H
@ SOA LOCALHOST. localhost (1 1h 15m 30d 2h)
NS LOCALHOST.
0.le4net00.net CNAME *.
0.weathdata.nu CNAME *.
00-gov.cn CNAME *.
000.gaysexe.free.fr CNAME *.
000007.ru CNAME *.
- Load the RPZ zone into the PowerDNS recursor
-- RPZ
rpzFile("/etc/powerdns/rpz/db.banlist")
- Dump the RPZ zone from memory into a file
% rec_control dump-rpz rpzFile /tmp/rpz.out
- This is how to overwrite the policy
rpzFile("/etc/powerdns/rpz/db.banlist", {defpol=Policy.NXDOMAIN})
6.11 Security Best Practices
- Keep your PowerDNS software up-to-date
- use the package manager of your Linux/Unix distribution
- configure automatic unattended updates
- consider using the PowerDNS supplied packages
- or use a cross-platform package manager
- pkgsrc — https://www.pkgsrc.org
- Nix — https://nixos.org/nix/
- use the package manager of your Linux/Unix distribution
- subscribe to PowerDNS announce mailing list (low volume, new versions and security announcements only) https://mailman.powerdns.com/mailman/listinfo/pdns-announce
6.11.1 Separating authoritative and recursive DNS
- authoritative DNS server and DNS resolver are separate functions in
the DNS infrastructure
- they have different security requirements
- benefits of separate authoritative and recursive DNS
- required for DNSSEC validation of own zones
- security configuration optimised for the function (for example query ACLs)
- helps troubleshooting (logging)
- easier maintenance (Updates)
6.11.2 Process isolation
- isolate the PowerDNS DNS server process from the operating system and
other applications
- reduces the impact of a security breach
- classic Unix operating systems offer the chroot function to
isolate a process into its own filesystem-tree
- while many security tutorials still explain chroot, it might not be the best option available today
- modern systems offer much richer isolation functions:
- Linux container (LXC/LXD, Docker, Podman, systemd-nspawn, Firejail)
- FreeBSD jails
6.11.3 Firewalls Architectures
- Packet Filter
- A packet filter is a simple firewall, examining only fields in the IP header.
- It filters on IP source and destination, and on TCP/UDP ports.
- With low latency, it protects a DNS server, but provides no protection to the DNS process.
- Packet filters are typical in low-end routers and home-use network hardware.
- A packet filter is a simple firewall, examining only fields in the IP header.
- Application Gateway
- An application gateway intercept DNS packets from internal clients
heading externally, and generates new packets.
- Clients are typically resolvers.
- Returning data is send to the client by the application gateway.
- An application gateway examines DNS packets to detect anomalies (e.g. DNS tunneling), but the latency is far greater than that of a packet filter.
- If an application gateway doesn't support a feature, it fails (EDNS0, DNSSEC, ENUM, IPv6 as transport protocol, random src port, etc. ).
- An application gateway intercept DNS packets from internal clients
heading externally, and generates new packets.
- Statefull Packet Filter
- Stateful Firewalls, like packet filters, examine IP header fields,
but additionally track the connection in both directions.
- They offer little advantage over packet filters for DNS.
- Most DNS traffic is UDP, which is fundamentally stateless.
- They can detect some, but not all, IP address spoofing.
- The latency is generally low, but it depends on the quality of the firewall's internal state-table.
- Stateful Firewalls, like packet filters, examine IP header fields,
but additionally track the connection in both directions.
- Stateful Firewalls Issues
- Detecting state for UDP traffic, including DNS, is a challenge:
- Each query must be entered in the firewalls state-table.
- The state-table becomes huge for busy DNS servers.
- Some stateful firewalls fail on high DNS traffic load.
- If NAT is run on the firewall, some firewalls can run out of NAT-Table space because of very busy DNS servers.
- It is highly recommended to avoid having DNS NATed if possible.
- Detecting state for UDP traffic, including DNS, is a challenge:
- Content Inspection
- Inspect the payload of IP packets on the Application Level (Layer 7)
- Often combined with stateful packet-filter
- Can detect some DNS misuse and protocol attacks (e.g. buffer overflow)
- Can be the "least common denominator" for DNS (EDNS0, DNSSEC, IPv6, ENUM …)
- Latency is implementation dependent, but is usually high
- Content Inspection Algorithms can be single point of failure
- Inspect the payload of IP packets on the Application Level (Layer 7)
6.11.4 DNS and fragmentation
- if a EDNS maximum message size of 1232 is advertised from the DNS
resolver server (recommendation from DNS Flag Day 2020), there
should be no UDP fragmentation seen (as most of the Internet is on
Ethernet with an MTU of 1500 byte)
- all incoming fragmented DNS messages towards a DNS resolver are most likely mis-configuration or attack
- to prevent attacks on the DNS cache of a DNS resolver, it is
possible to drop all incoming fragmented UDP traffic towards a
DNS resolver
- it is recommended to run such a configuration in permissive mode for some time (log, but not drop fragmentation) before activating