From f235dc0c4a16a8e61617fc4ba8532e2ab6168824 Mon Sep 17 00:00:00 2001 From: Pieter Lexis Date: Tue, 12 Aug 2014 15:53:24 +0200 Subject: [PATCH] All auth docs are done --- .../authoritative/backend-generic-mypgsql.md | 617 ++++++++++++++++++ .../markdown/authoritative/backend-oracle.md | 439 +++++++++++++ pdns/docs/markdown/authoritative/dnssec.md | 467 +++++++++++++ .../markdown/authoritative/fancy-records.md | 24 + pdns/docs/markdown/authoritative/migration.md | 57 ++ .../authoritative/modes-of-operation.md | 1 - .../markdown/authoritative/performance.md | 40 ++ pdns/docs/markdown/authoritative/recursion.md | 35 + pdns/docs/markdown/authoritative/security.md | 33 + pdns/docs/markdown/authoritative/settings.md | 16 +- pdns/docs/markdown/authoritative/virtual.md | 8 + 11 files changed, 1733 insertions(+), 4 deletions(-) diff --git a/pdns/docs/markdown/authoritative/backend-generic-mypgsql.md b/pdns/docs/markdown/authoritative/backend-generic-mypgsql.md index e69de29bb..d482c4cc7 100644 --- a/pdns/docs/markdown/authoritative/backend-generic-mypgsql.md +++ b/pdns/docs/markdown/authoritative/backend-generic-mypgsql.md @@ -0,0 +1,617 @@ +# Generic MySQL and PgSQL backends +| | | +|:--|:--| +|Native|Yes| +|Master|Yes| +|Slave|Yes| +|Superslave|Yes| +|Autoserial|Yes (v3.1 and up)| +|Case|All lower| +|DNSSEC|Yes (set `gmysql-dnssec` or `gpgsql-dnssec`)| +|Disabled data|Yes (v3.4.0 and up)| +|Comments|Yes (v3.4.0 and up)| +|Module name < 2.9.3|pgmysql| +|Module name > 2.9.2|gmysql and gpgsql| +|Launch name| gmysql and gpgsql2 and gpgsql| + +PostgreSQL and MySQL backend with easily configurable SQL statements, allowing you to graft PDNS on any PostgreSQL or MySQL database of your choosing. Because all database schemas will be different, a generic backend is needed to cover all needs. + +**Warning**: Host names and the MNAME of a SOA records are NEVER terminated with a '.' in PowerDNS storage! If a trailing '.' is present it will inevitably cause problems, problems that may be hard to debug. + +The template queries are expanded using the C function 'snprintf' which implies that substitutions are performed on the basis of %-place holders. To place a % in a query which will not be substituted, use %%. Make sure to fill out the search key, often called 'name' in lower case! + +There are in fact two backends, one for PostgreSQL and one for MySQL but they accept the same settings and use almost exactly the same database schema. + +# MySQL specifics + +**Warning**: If using MySQL with 'slave' support enabled in PowerDNS you **must** run MySQL with a table engine that supports transactions. + +In practice, great results are achieved with the 'InnoDB' tables. PowerDNS will silently function with non-transaction aware MySQLs but at one point this is going to harm your database, for example when an incoming zone transfer fails. + +The default setup conforms to the following schema: + +``` +CREATE TABLE domains ( + id INT AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial INT DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE UNIQUE INDEX name_index ON domains(name); + +CREATE TABLE records ( + id INT 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, + change_date INT DEFAULT NULL, + disabled TINYINT(1) DEFAULT 0, + ordername VARCHAR(255) BINARY DEFAULT NULL, + auth TINYINT(1) DEFAULT 1, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR(64) NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) DEFAULT NULL, + PRIMARY KEY (ip, nameserver) +) Engine=InnoDB; + + +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) NOT NULL, + comment VARCHAR(64000) NOT NULL, + PRIMARY KEY (id) +) Engine=InnoDB; + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +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; + +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, + content TEXT, + PRIMARY KEY(id) +) Engine=InnoDB; + +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; + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); +``` + +`zone2sql` with the `--gmysql` flag also assumes this layout is in place. + +For full migration notes, please see [Migration](migration.md). + +This schema contains all elements needed for master, slave and superslave operation. + +When using the InnoDB storage engine, we suggest adding the following lines to the 'create table records' command above: + +``` +CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`) REFERENCES `domains` +(`id`) ON DELETE CASCADE +``` + +Or, if you have already created the tables, execute: + +``` +ALTER TABLE `records` ADD CONSTRAINT `records_ibfk_1` FOREIGN KEY (`domain_id`) +REFERENCES `domains` (`id`) ON DELETE CASCADE; +``` + +This automates deletion of records on deletion of a domain from the domains table. + +# PostgreSQL specifics + +The default setup conforms to the following schema, which you should add to a PostgreSQL database. + +``` +CREATE TABLE domains ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + master VARCHAR(128) DEFAULT NULL, + last_check INT DEFAULT NULL, + type VARCHAR(6) NOT NULL, + notified_serial INT DEFAULT NULL, + account VARCHAR(40) DEFAULT NULL, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX name_index ON domains(name); + + +CREATE TABLE records ( + id SERIAL PRIMARY KEY, + domain_id INT DEFAULT NULL, + name VARCHAR(255) DEFAULT NULL, + type VARCHAR(10) DEFAULT NULL, + content VARCHAR(65535) DEFAULT NULL, + ttl INT DEFAULT NULL, + prio INT DEFAULT NULL, + change_date INT DEFAULT NULL, + disabled BOOL DEFAULT 'f', + ordername VARCHAR(255), + auth BOOL DEFAULT 't', + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX rec_name_index ON records(name); +CREATE INDEX nametype_index ON records(name,type); +CREATE INDEX domain_id ON records(domain_id); +CREATE INDEX recordorder ON records (domain_id, ordername text_pattern_ops); + + +CREATE TABLE supermasters ( + ip INET NOT NULL, + nameserver VARCHAR(255) NOT NULL, + account VARCHAR(40) DEFAULT NULL, + PRIMARY KEY(ip, nameserver) +); + + +CREATE TABLE comments ( + id SERIAL PRIMARY KEY, + domain_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(10) NOT NULL, + modified_at INT NOT NULL, + account VARCHAR(40) DEFAULT NULL, + comment VARCHAR(65535) NOT NULL, + CONSTRAINT domain_exists + FOREIGN KEY(domain_id) REFERENCES domains(id) + ON DELETE CASCADE, + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE INDEX comments_domain_id_idx ON comments (domain_id); +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 SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + kind VARCHAR(32), + content TEXT +); + +CREATE INDEX domainidmetaindex ON domainmetadata(domain_id); + + +CREATE TABLE cryptokeys ( + id SERIAL PRIMARY KEY, + domain_id INT REFERENCES domains(id) ON DELETE CASCADE, + flags INT NOT NULL, + active BOOL, + content TEXT +); + +CREATE INDEX domainidindex ON cryptokeys(domain_id); + + +CREATE TABLE tsigkeys ( + id SERIAL PRIMARY KEY, + name VARCHAR(255), + algorithm VARCHAR(50), + secret VARCHAR(255), + CONSTRAINT c_lowercase_name CHECK (((name)::TEXT = LOWER((name)::TEXT))) +); + +CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm); +``` + +`zone2sql` with the `--gpgsql` flag also assumes this layout is in place. + +This schema contains all elements needed for master, slave and superslave operation. + +For full migration notes, please see [Migration](migration.md). + +With PostgreSQL, you may have to run `createdb powerdns` first and then connect to that database with `psql powerdns`, and feed it the schema above. + +# Oracle specifics + +Generic Oracle support is only available since version 2.9.18. The default setup conforms to the following schema, which you should add to an Oracle database. You may need or want to add `namespace` statements. + +``` +CREATE TABLE domains ( + id INTEGER NOT NULL, + name VARCHAR2(255) NOT NULL, + master VARCHAR2(128) DEFAULT NULL, + last_check INTEGER DEFAULT NULL, + type VARCHAR2(6) NOT NULL, + notified_serial NUMBER(10,0) DEFAULT NULL, + account VARCHAR2(40) DEFAULT NULL, + PRIMARY KEY (id) +); + +CREATE SEQUENCE domains_id_sequence; +CREATE INDEX domains$name ON domains (name); + + +CREATE TABLE records ( + id INTEGER NOT NULL, + domain_id INTEGER DEFAULT NULL REFERENCES domains (id) ON DELETE CASCADE, + name VARCHAR2(255) DEFAULT NULL, + type VARCHAR2(10) DEFAULT NULL, + content VARCHAR2(4000) DEFAULT NULL, + ttl INTEGER DEFAULT NULL, + prio INTEGER DEFAULT NULL, + change_date INTEGER DEFAULT NULL, + disabled NUMBER(1,0) DEFAULT 0 NOT NULL, + ordername VARCHAR2(255) DEFAULT NULL, + auth NUMBER(1,0) DEFAULT 1 NOT NULL, + PRIMARY KEY (id) +) pctfree 40; + +CREATE SEQUENCE records_id_sequence; +CREATE INDEX records$nametype ON records (name, type); +CREATE INDEX records$domain_id ON records (domain_id); +CREATE INDEX records$recordorder ON records (domain_id, ordername); + + +CREATE TABLE supermasters ( + ip VARCHAR2(64) NOT NULL, + nameserver VARCHAR2(255) NOT NULL, + account VARCHAR2(40) DEFAULT NULL, + PRIMARY KEY (ip, nameserver) +); + + +CREATE TABLE comments ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL REFERENCES domains (id) ON DELETE CASCADE, + name VARCHAR2(255) NOT NULL, + type VARCHAR2(10) NOT NULL, + modified_at INTEGER NOT NULL, + account VARCHAR2(40) NOT NULL, + "comment" VARCHAR2(4000) NOT NULL +); +CREATE SEQUENCE comments_id_sequence; +CREATE INDEX comments$nametype ON comments (name, type); +CREATE INDEX comments$domain_id ON comments (domain_id); +CREATE INDEX comments$order ON comments (domain_id, modified_at); + + +CREATE TABLE domainmetadata ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL, + kind VARCHAR2(32), + content VARCHAR2(4000), + PRIMARY KEY (id) +); + +CREATE SEQUENCE domainmetadata_id_sequence; +CREATE INDEX domainmetadata$domain_id ON domainmetadata (domain_id); + + +CREATE TABLE cryptokeys ( + id INTEGER NOT NULL, + domain_id INTEGER NOT NULL, + flags INTEGER NOT NULL, + active INTEGER NOT NULL, + content VARCHAR2(4000), + PRIMARY KEY (id) +); + +CREATE SEQUENCE cryptokeys_id_sequence; +CREATE INDEX cryptokeys$domain_id ON cryptokeys (domain_id); + + +CREATE TABLE tsigkeys ( + id INTEGER NOT NULL, + name VARCHAR2(255), + algorithm VARCHAR2(50), + secret VARCHAR2(255), + PRIMARY KEY (id) +); + +CREATE SEQUENCE tsigkeys_id_sequence; +CREATE UNIQUE INDEX tsigkeys$namealgo ON tsigkeys (name, algorithm); +``` + +This schema contains all elements needed for master, slave and superslave operation. + +Inserting records is a bit different compared to MySQL and PostgreSQL, you should use: + +``` +insert into domains (id,name,type) values (domains_id_sequence.nextval,'example.net','NATIVE'); +``` + +Furthermore, use the `goracle-tnsname` setting to specify which TNSNAME the Generic Oracle Backend should be connecting to. There are no `goracle-dbname`, `goracle-host` or `goracle-port` settings, their equivalent is in `/etc/tnsnames.ora`. + +# Basic functionality +4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers. + +The 4+4 regular queries must return the following 6 fields, in this exact order: + +* content: This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example. +* ttl: TTL of this record, in seconds. Must be a real value, no checking is performed. +* prio: For MX records, this should be the priority of the mail exchanger specified. +* qtype: The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this field returns an exact answer - PDNS won't recognise 'A ' as 'A'. This can be achieved by using a VARCHAR instead of a CHAR. +* domain\_id: Each domain must have a unique domain\_id. No two domains may share a domain\_id, all records in a domain should have the same. A number. +* name: Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain! +* disabled: If set to true, this record is hidden from DNS clients, but can still be modified from the REST API. See [Disabled data](#disabled-data). (Available since version 3.4.0.) + +Please note that the names of the fields are not relevant, but the order is! + +As said earlier, there are 8 SQL queries for regular lookups. To configure them, set `gmysql-basic-query` or `gpgsql-basic-query`, depending on your choice of backend. If so called 'MBOXFW' fancy records are not used, four queries remain: + +# Queries and settings +## Regular Queries +### `basic-query` +Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'` This is the most used query, needed for doing 1:1 lookups of qtype/name values. First %s is replaced by the ASCII representation of the qtype of the question, the second by the name. + +### id-query +Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d` Used for doing lookups within a domain. First %s is replaced by the qtype, the %d which should appear after the %s by the numeric domain\_id. + +### any-query +For doing ANY queries. Also used internally. Default: `select content,ttl,prio,type,domain_id,name from records where name='%s'` The %s is replaced by the qname of the question. + +### any-id-query +For doing ANY queries within a domain. Also used internally. Default: `select content,ttl,prio,type,domain_id,name from records where name='%s' and domain_id=%d` The %s is replaced by the name of the domain, the %d by the numerical domain id. + +The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally: + +### list-query +To list an entire zone. Default: `select content,ttl,prio,type,domain_id,name from records where domain_id=%d` + +## DNSSEC queries +If DNSSEC is enabled (through the `-dnssec` flag on a gsql backend), many queries are replaced by slightly extended variants that also query the auth column. The auth column is always added as the rightmost column. These are the -auth defaults: + +### basic-query-auth +Basic query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name='%s'` + +### id-query-auth +Basic with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name='%s' and domain_id=%d` + +### wildcard-query-auth +Wildcard query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name like '%s'` + +### wildcard-id-query-auth +Wildcard with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where type='%s' and name like '%s' and domain_id='%d'` + +### any-query-auth +Any query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name='%s'` + +### any-id-query-auth +Any with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name='%s' and domain_id=%d` + +### wildcard-any-query-auth +Wildcard ANY query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name like '%s'` + +### wildcard-any-id-query-auth +Wildcard ANY with ID query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where name like '%s' and domain_id='%d'` + +### list-query-auth +AXFR query. Default: `select content,ttl,prio,type,domain_id,name, auth from records where domain_id='%d' order by name, type` + +Additionally, there are some new queries to determine NSEC(3) order: + +### get-order-first-query +DNSSEC Ordering Query, first. Default: `select ordername, name from records where domain_id=%d and ordername is not null order by 1 asc limit 1` + +### get-order-before-query +DNSSEC Ordering Query, before. Default: `select ordername, name from records where ordername <= '%s' and domain_id=%d and ordername is not null order by 1 desc limit 1` + +### get-order-after-query +DNSSEC Ordering Query, after. Default: `select min(ordername) from records where ordername > '%s' and domain_id=%d and ordername is not null` + +### get-order-last-query +DNSSEC Ordering Query, last. Default: `select ordername, name from records where ordername != '' and domain_id=%d and ordername is not null order by 1 desc limit 1` + +Finally, these two queries are used to set ordername and auth correctly in a database: + +### set-order-and-auth-query +DNSSEC set ordering query. Default: `update records set ordername='%s',auth=%d where name='%s' and domain_id='%d'` + +### nullify-ordername-and-auth-query +DNSSEC nullify ordername query. Default: `update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'` + +Make sure to read [Rules for filling out fields in database backends](dnssec.md#rules-for-filling-out-fields-in-database-backends) if you wish to calculate ordername and auth without using pdns-rectify. + +## Master/slave queries +Most installations will have zero need to change the following settings, but should the need arise, here they are: + +### master-zone-query +Called to determine the master of a zone. Default: `select master from domains where name='%s' and type='SLAVE'` + +### info-zone-query +Called to retrieve (nearly) all information for a domain: Default: `select id,name,master,last_check,notified_serial,type from domains where name='%s'` + +### info-all-slaves-query +Called to retrieve all slave domains Default: `select id,name,master,last_check,type from domains where type='SLAVE'` + +### supermaster-query +Called to determine if a certain host is a supermaster for a certain domain name. Default: `select account from supermasters where ip='%s' and nameserver='%s';` + +### insert-slave-query +Called to add a domain as slave after a supermaster notification. Default: `insert into domains (type,name,master,account) values('SLAVE','%s','%s','%s')` + +### insert-record-query +Called during incoming AXFR. Default: `insert into records (content,ttl,prio,type,domain_id,name) values ('%s',%d,%d,'%s',%d,'%s')` + +### update-serial-query +Called to update the last notified serial of a master domain. Default: `update domains set notified_serial=%d where id=%d` + +### update-lastcheck-query +Called to update the last time a slave domain was checked for freshness. Default: `update domains set last_check=%d where id=%d` + +### info-all-master-query +Called to get data on all domains for which the server is master. Default: `select id,name,master,last_check,notified_serial,type from domains where type='MASTER'` + +### delete-zone-query +Called to delete all records of a zone. Used before an incoming AXFR. Default: `delete from records where domain_id=%d` + +## Comments queries +For listing/modifying comments. For defaults, please see `pdns_server --load=BACKEND --config`. + +### list-comments-query +Called to get all comments in a zone. Returns fields: domain\_id, name, type, modified\_at, account, comment. + +### insert-comment-query +Called to create a single comment for a specific RRSet. Given fields: domain\_id, name, type, modified\_at, account, comment + +### delete-comment-rrset-query +Called to delete all comments for a specific RRset. Given fields: domain\_id, name, type + +### delete-comments-query +Called to delete all comments for a zone. Usually called before deleting the entire zone. Given fields: domain\_id + +## Fancy records +**Warning**: Fancy records are unsupported as of version 3.0 + +If PDNS is used with so called 'Fancy Records', the 'MBOXFW' record exists which specifies an email address forwarding instruction, wildcard queries are sometimes needed. This is not enabled by default. A wildcard query is an internal concept - it has no relation to \*.domain-type lookups. You can safely leave these queries blank. + +### wildcard-query +Can be left blank. See above for an explanation. Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name like '%s'` + +### wildcard-id-query +Can be left blank. See above for an explanation. Default: `select content,ttl,prio,type,domain_id,name from records where type='%s' and name like '%s' and domain_id=%d` Used for doing lookups within a domain. + +### wildcard-any-query +For doing wildcard ANY queries. Default: `select content,ttl,prio,type,domain_id,name from records where name like '%s'` + +### wildcard-any-id-query +For doing wildcard ANY queries within a domain. Default: `select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d` + +## Settings and specifying queries +The queries above are specified in pdns.conf. For example, the basic-query would appear as: + +``` +gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' +``` + +When using the Generic PostgreSQL backend, they appear as above. When using the generic MySQL backend, change the "gpgsql-" prefix to "gmysql-". + +Queries can span multiple lines, like this: + +``` +gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \ +where type='%s' and name='%s' +``` + +Do not wrap statements in quotes as this will not work. Besides the query related settings, the following configuration options are available, where one should substitute 'gmysql', 'gpgsql', or 'goracle' for the prefix 'backend'. So 'backend-dbname' can stand for 'gpgsql-dbname' or 'gmysql-dbname' etc. + +### `backend-dbname` +Database name to connect to + +### `backend-host` +Database host to connect to. WARNING: When specified as a hostname a chicken/egg situation might arise where the database is needed to resolve the IP address of the database. It is best to supply an IP address of the database here. + +**Only for postgres**: If host begins with a slash, it specifies Unix-domain communication rather than TCP/IP communication; the value is the name of the directory in which the socket file is stored. + +### backend-port +Database port to connect to. + +### gmysql-socket (only for MySQL!) +File name where the MySQL connection socket resides. Often `/tmp/mysql.sock` or `/var/run/mysqld/mysqld.sock`. + +### backend-password +Password to connect with + +### backend-user +User to connect as + +### backend-group (MySQL only, since 3.2) +MySQL 'group' to connect as, defaults to 'client'. + +## Native operation +To add a domain, issue the following: + +``` +insert into domains (name,type) values ('powerdns.com','NATIVE'); +``` + +The records table can now be filled by with the domain\_id set to the id of the domains table row just inserted. + +## Slave operation +These backends are fully slave capable. To become a slave of the 'powerdns.com' domain, execute this: + +``` + insert into domains (name,master,type) values ('powerdns.com','213.244.168.217','SLAVE'); +``` + +And wait a while for PDNS to pick up the addition - which happens within one minute. There is no need to inform PDNS that a new domain was added. Typical output is: + +``` + Apr 09 13:34:29 All slave domains are fresh + Apr 09 13:35:29 1 slave domain needs checking + Apr 09 13:35:29 Domain powerdns.com is stale, master serial 1, our serial 0 + Apr 09 13:35:30 [gPgSQLBackend] Connected to database + Apr 09 13:35:30 AXFR started for 'powerdns.com' + Apr 09 13:35:30 AXFR done for 'powerdns.com' + Apr 09 13:35:30 [gPgSQLBackend] Closing connection +``` + +From now on, PDNS is authoritative for the 'powerdns.com' zone and will respond accordingly for queries within that zone. + +Periodically, PDNS schedules checks to see if domains are still fresh. The default [`slave-cycle-interval`](settings.md#slave-cycle-interval) is 60 seconds, large installations may need to raise this value. Once a domain has been checked, it will not be checked before its SOA refresh timer has expired. Domains whose status is unknown get checked every 60 seconds by default. + +## Superslave operation +To configure a supermaster with IP address 10.0.0.11 which lists this installation as 'autoslave.powerdns.com', issue the following: + +``` + insert into supermasters ('10.0.0.11','autoslave.powerdns.com','internal'); +``` + +From now on, valid notifies from 10.0.0.11 that list a NS record containing 'autoslave.powerdns.com' will lead to the provisioning of a slave domain under the account 'internal'. See [Supermaster](modes-of-operation.md#supermaster-automatic-provisioning-of-slaves) for details. + +## 3.13. Master operation +The PostgreSQL backend is fully master capable with automatic discovery of serial changes. Raising the serial number of a domain suffices to trigger PDNS to send out notifications. To configure a domain for master operation instead of the default native replication, issue: + +``` + insert into domains (name,type) values ('powerdns.com','MASTER'); +``` + +Make sure that the assigned id in the domains table matches the domain\_id field in the records table! + +## 3.14. Disabled data +PowerDNS understands the notion of disabled records. They are marked by setting "disabled" to 1 (for PostgreSQL: true). By extension, when the SOA record for a domain is disabled, the entire domain is considered to be disabled. + +Effects: the record (or domain, respectively) will not be visible to DNS clients. The REST API will still see the record (or domain). Even if a domain is disabled, slaving still works. Slaving considers a disabled domain to have a serial of 0; this implies that a slaved domain will not stay disabled. diff --git a/pdns/docs/markdown/authoritative/backend-oracle.md b/pdns/docs/markdown/authoritative/backend-oracle.md index e69de29bb..ed9d1c269 100644 --- a/pdns/docs/markdown/authoritative/backend-oracle.md +++ b/pdns/docs/markdown/authoritative/backend-oracle.md @@ -0,0 +1,439 @@ +# Oracle backend +| | | +|:--|:--| +|Native|Yes| +|Master|Yes| +|Slave|Yes| +|Superslave|Yes| +|Autoserial|Yes| +|DNSSEC|Yes| +|Comments|No| +|Module name|oracle| +|Launch name|oracle| + +This is the Oracle Database backend, completely rewritten for the 3.0 release, with easily configurable SQL statements, allowing you to graft PowerDNS functionality onto any Oracle database of your choosing. + +The Oracle backend is difficult, and possibly illegal, to distribute in binary form. To use it, you will probably need to compile PowerDNS from source. OCI headers are expected in `$ORACLE_HOME/rdbms/public`, and OCI libraries in `$ORACLE_HOME/lib`. That is where they should be with a working installation of the full Oracle Database client. Oracle InstantClient should work as well, but you will need to make the libraries and headers available in appropriate paths. + +This backend uses two kinds of database connections. First, it opens a session pool. Connections from this pool are used only for queries reading DNS data from the database. Second, it opens normal (non-pooled) connections on demand for any kind of write access. The reason for this split is to allow redundancy by replication. Each DNS frontend server can have a local read-only replicated instance of your database. Open the session pool to the local replicated copy, and all data will be available with high performance, even if the main database goes down. The writing connections should go directly to the main database. + +Of course, if you do not require this kind of redundancy, or want to avoid the substantial Oracle Database licensing costs, all connections can just go to the same database with the same credentials. Also, the write connections should be entirely unnecessary if you do not plan to use either master or slave mode. + +## Configuration Parameters +### `oracle-pool-database`, `oracle-pool-username`, `oracle-pool-password` +The database to use for read access. OracleBackend will try to create a session pool, so make sure this database user has the necessary permissions. If your connection requires environment variables to be set, e.g. `ORACLE_HOME`, `NLS_LANG`, or `LD_LIBRARY_PATH`, make sure these are set when PowerDNS runs. `/etc/default/pdns` might help. + +### `oracle-master-database`, `oracle-master-username`, `oracle-master-password` +The database to use for write access. These are normal connections, not a session pool. The backend may open more than one at a time. + +### `oracle-session-min`, `oracle-session-max`, `oracle-session-inc` +Parameters for the connection pool underlying the session pool. OCI will open `session-min` connections at startup, and open more connections as needed, `session-inc` at a time, until `session-max` connections are open. + +### `oracle-nameserver-name` +This can be set to an arbitrary string that will be made available in the optional bind variable `:nsname` for all SQL statements. You can use this to run multiple PowerDNS instances off the same database, while serving different zones. + +There are many more options that are used to define the different SQL statements. These will be discussed after the reference database schema has been explained. + +## The Database Schema +You can find an example database schema in `schema.sql` in the PowerDNS source distribution. It is intended more as a starting point to come up with a schema that works well for your organisation, than as something you should run as it is. As long as the semantics of the SQL statements still work out, you can store your DNS data any way you like. + +You should read this while having `schema.sql` to hand. Columns will not be specifically explained where their meaning is obvious. + +**Note**: All FQDNs should be specified in lower case and without a trailing dot. Where things are lexicographically compared or sorted, make sure a sane ordering is used. `'NLS_LANG=AMERICAN_AMERICA.AL32UTF8'` should generally work well enough; when in doubt, enforce a plain ordering with `"NLSSORT(value, 'NLS_SORT = BINARY')"`. + +### Zones Table +This table lists the zones for which PowerDNS is supposed to be an authoritative nameserver, plus a small amount of information related to master/slave mode. + +#### name +The FQDN of the zone apex, e.g. 'example.com'. + +#### type +Describes how PowerDNS should host the zone. Valid values are 'NATIVE', 'MASTER', and 'SLAVE'. PowerDNS acts as an authoritative nameserver for the zone in all modes. In slave mode, it will additionally attempt to acquire the zone's content from a master server. In master mode, it will additionally send 'NOTIFY' packets to other nameservers for the zone when its content changes. + +**Tip**: There is a global setting to make PowerDNS send 'NOTIFY' packets in slave mode. + +#### last\_check +This value, updated by PowerDNS, is the unix timestamp of the last successful attempt to check this zone for freshness on the master. + +#### refresh +The number of seconds PowerDNS should wait after a successful freshness check before performing another one. This value is also found in the zone's SOA record. You may want to make sure to put the same thing in both places. + +#### serial +The serial of the version of the zone's content we are hosting now. This value is also found in the zone's SOA record. You may want to make sure to put the same thing in both places. + +#### notified\_serial +The latest serial for which we have sent `NOTIFY` packets. Updated by PowerDNS. + +### The Zonemasters and ZoneAlsoNotify Tables +These are lists of hosts PowerDNS will interact with for a zone in master/slave mode. 'Zonemasters' lists the hosts PowerDNS will attempt to pull zone transfers from, and accept 'NOTIFY' packets from. 'ZoneAlsoNotify' lists hosts PowerDNS will send 'NOTIFY' packets to, in addition to any hosts that have NS records. + +Host entries can be IPv4 or IPv6 addresses, in string representation. If you need to specify a port, use `192.0.2.4:5300` notation for IPv4 and brackets for IPv6: `[2001:db8::1234]:5300`. + +### The Supermasters Table +In superslave mode, PowerDNS can accept 'NOTIFY' packets for zones that have not been defined in the zone table yet. PowerDNS will then create an entry for the zone and attempt a zone transfer. This table defines the list of acceptable sources for supernotifications. + +#### name +An identifying string for this entry. Only used for logging. + +#### ip +The alleged originating IP address of the notification. + +#### nameserver +The FQDN of an authoritative nameserver. + +A supernotification will be accepted if an entry is found such that the notification came from 'ip' and 'nameserver' appears in an NS record for that zone. + +### The ZoneMetadata Table +This is a per-zone key-value store for various things PowerDNS needs to know that are not part of the zone's content or handled by other tables. Depending on your needs, you may not want this to exist as an actual table, but simulate this in PL/SQL instead. + +The currently defined metadata types are: + +#### 'PRESIGNED' +If set to 1, PowerDNS should assume that DNSSEC signatures for this zone exist in the database and use them instead of signing records itself. For a slave zone, this will also signal to the master that we want DNSSEC records when attempting a zone transfer. + +#### 'NSEC3PARAM' +The NSEC3 hashing parameters for the zone. + +#### 'TSIG-ALLOW-AXFR' +The value is the name of a TSIG key. A client will be allowed to AXFR from us if the request is signed with that key. + +#### 'AXFR-MASTER-TSIG' +The value is the name of a TSIG key. Outgoing `NOTIFY` packets for this zone will be signed with that key. + +### The Tables for Cryptographic Keys +We have two of them: 'TSIGKeys' for symmetric TSIG keys, and 'ZoneDNSKeys' for DNSSEC signing keys. + +### The Records Table +The actual DNS zone contents are stored here. + +#### zone\_id +The zone this records belongs to. Normally, this is obvious. When you are dealing with zone delegations, you have to insert some records into the parent zone of their actual zone. See also `auth`. + +#### fqdn +The owner name of this record. Again, this is lower case and without a trailing dot. + +#### revfqdn +This should be a string that consists of the labels of the owner name, in reverse order, with spaces instead of dots separating them, for example: + +``` +'www.example.com' => 'com example www' +``` + +This is used as a quick and dirty way to get canonical zone ordering. You can chose a more correct and much more complicated implementation instead if you prefer. In the reference schema, this is automatically set by a trigger. + +#### fqdnhash +The NSEC3 hash of the owner name. The reference schema provides code and a trigger to calculate this, but they are not production quality. The recommendation is to load the dnsjava classes into your database and use their facilities for dealing with DNS names and NSEC3 hashes. + +#### ttl +The TTL for the record set. This should be the same for all members of a record set, but PowerDNS will quietly use the minimum if it encounters different values. + +#### type +The type of the record, as a canonical identification string, e.g. 'AAAA' or 'MX'. You can set this and 'content' NULL to indicate a name that exists, but doesn't carry any record (a so called empty non-terminal) for NSEC/NSEC3 ordering purposes. + +#### content +The data part of the DNS record, in canonical string representation, except that if this includes FQDNs, they should be specified without a trailing dot. + +#### last\_change +The unix timestamp of the last change to this record. Used only for the deprecated autoserial feature. You can omit this unless you want to use that feature. + +#### auth +0 or 1 depending on whether this record is an authoritative member of the zone specified in `zone_id`. These are the rules for determining that: A record is an authoritative member of the zone its owner name belongs to, except for DS records, which are authoritative members of the parent zone. Delegation records, that is, NS records and related A/AAAA glue records, are additionally non-authoritative members of the parent zone. + +PowerDNS has a function to automatically set this. OracleBackend doesn't support that. Do it in the database. + +### The SQL Statements +#### Fetching DNS records +There are five queries to do this. They all share the same set of return columns: + +* fqdn: The owner name of the record. +* ttl: The TTL of the record set. +* type: The type of the record. +* content: The content of the record. +* zone\_id: The numerical identifier of the zone the record belongs to. A record can belong to two zones (delegations/glue), in which case it may be returned twice. +* last\_change: The unix timestamp of the last time this record was changed. Can safely be set as a constant 0, unless you use the autoserial feature. +* auth: 1 or 0 depending on the zone membership (authoritative or not). + +Record sets (records for the same name of the same type) must appear consecutively, which means **ORDER BY** clauses are needed in some places. Empty non-terminals should be suppressed. + +The queries differ in which columns are restricted by 'WHERE' clauses: + +##### oracle-basic-query +Looking for records based on owner name and type. Default: + +``` +SELECT fqdn, ttl, type, content, zone_id, last_change, auth +FROM Records +WHERE type = :type AND fqdn = lower(:name) +``` + +##### oracle-basic-id-query +Looking for records from one zone based on owner name and type. Default: + +``` +SELECT fqdn, ttl, type, content, zone_id, last_change, auth +FROM Records +WHERE type = :type AND fqdn = lower(:name) AND zone_id = :zoneid +``` + +##### oracle-any-query +Looking for records based on owner name. Default: + +``` +SELECT fqdn, ttl, type, content, zone_id, last_change, auth +FROM Records +WHERE fqdn = lower(:name) + AND type IS NOT NULL +ORDER BY type +``` + +##### oracle-any-id-query +Looking for records from one zone based on owner name. Default: + +``` +SELECT fqdn, ttl, type, content, zone_id, last_change, auth +FROM Records +WHERE fqdn = lower(:name) + AND zone_id = :zoneid + AND type IS NOT NULL +ORDER BY type +``` + +##### oracle-list-query +Looking for all records from one zone. Default: + +``` +SELECT fqdn, ttl, type, content, zone_id, last_change, auth +FROM Records +WHERE zone_id = :zoneid + AND type IS NOT NULL +ORDER BY fqdn, type +``` + +#### Zone Metadata and TSIG + +##### oracle-get-zone-metadata-query +Fetch the content of the metadata entries of type ':kind' for the zone called ':name', in their original order. Default: + +``` +SELECT md.meta_content +FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id +WHERE z.name = lower(:name) AND md.meta_type = :kind +ORDER BY md.meta_ind +``` + +##### oracle-del-zone-metadata-query +Delete all metadata entries of type ':kind' for the zone called ':name'. You can skip this if you do not plan to manage zones with the `pdnssec` tool. Default: + +``` +DELETE FROM ZoneMetadata md +WHERE zone_id = (SELECT id FROM Zones z WHERE z.name = lower(:name)) +AND md.meta_type = :kind +``` + +##### oracle-set-zone-metadata-query +Create a metadata entry. You can skip this if you do not plan to manage zones with the `pdnssec` tool. Default: + +``` +INSERT INTO ZoneMetadata (zone_id, meta_type, meta_ind, meta_content) +VALUES ( + (SELECT id FROM Zones WHERE name = lower(:name)), + :kind, :i, :content +) +``` + +##### oracle-get-tsig-key-query +Retrieved the TSIG key specified by ':name'. Default: + +``` +SELECT algorithm, secret +FROM TSIGKeys +WHERE name = :name +``` + +#### DNSSEC +##### oracle-get-zone-keys-query +Retrieve the DNSSEC signing keys for a zone. Default: + +``` +SELECT k.id, k.flags, k.active, k.keydata +FROM ZoneDNSKeys k JOIN Zones z ON z.id = k.zone_id +WHERE z.name = lower(:name) +``` + +##### oracle-del-zone-key-query +Delete a DNSSEC signing key. You can skip this if you do not plan to manage zones with the `pdnssec` tool. Default: + +``` +DELETE FROM ZoneDNSKeys WHERE id = :keyid +``` + +##### oracle-add-zone-key-query +Add a DNSSEC signing key. You can skip this if you do not plan to manage zones with the `pdnssec` tool. Default: + +``` +INSERT INTO ZoneDNSKeys (id, zone_id, flags, active, keydata) " +VALUES ( + zonednskeys_id_seq.NEXTVAL, + (SELECT id FROM Zones WHERE name = lower(:name)), + :flags, + :active, + :content +) RETURNING id INTO :keyid +``` + +##### oracle-set-zone-key-state-query +Enable or disable a DNSSEC signing key. You can skip this if you do not plan to manage zones with the **pdnssec** tool. Default: + +``` +UPDATE ZoneDNSKeys SET active = :active WHERE id = :keyid +``` + +##### oracle-prev-next-name-query +Determine the predecessor and successor of an owner name, in canonical zone ordering. See the reference implementation for the quick and dirty way, and the RFCs for the full definition of canonical zone ordering. + +This statement is a PL/SQL block that writes into two of the bind variables, not a query. + +Default: + +``` +BEGIN + get_canonical_prev_next(:zoneid, :name, :prev, :next); +END; +``` + +##### oracle-prev-next-hash-query +Given an NSEC3 hash, this call needs to return its predecessor and successor in NSEC3 zone ordering into `:prev` and `:next`, and the FQDN of the predecessor into `:unhashed`. Default: + +``` +BEGIN + get_hashed_prev_next(:zoneid, :hash, :unhashed, :prev, :next); +END; +``` + +#### Incoming AXFR + +#####oracle-zone-info-query +Get some basic information about the named zone before doing master/slave things. Default: + +``` +SELECT id, name, type, last_check, serial, notified_serial +FROM Zones +WHERE name = lower(:name) +``` + +##### oracle-delete-zone-query +Delete all records for a zone in preparation for an incoming zone transfer. This happens inside a transaction, so if the transfer fails, the old zone content will still be there. Default: + +``` +DELETE FROM Records WHERE zone_id = :zoneid +``` + +##### oracle-insert-record-query +Insert a record into the zone during an incoming zone transfer. This happens inside the same transaction as delete-zone, so we will not end up with a partially transferred zone. Default: + +``` +INSERT INTO Records (id, fqdn, zone_id, ttl, type, content) +VALUES (records_id_seq.NEXTVAL, lower(:name), :zoneid, :ttl, :type, :content) +``` + +##### oracle-finalize-axfr-query +A block of PL/SQL to be executed after a zone transfer has successfully completed, but before committing the transaction. A good place to locate empty non-terminals, set the `auth` bit and NSEC3 hashes, and generally do any post-processing your schema requires. The do-nothing default: + +``` +DECLARE + zone_id INTEGER := :zoneid; +BEGIN + NULL; +END; +``` + +#### Master/Slave Stuff + +##### oracle-unfresh-zones-query +Return a list of zones that need to be checked and their master servers. Return multiple rows, identical except for the master address, for zones with more than one master. Default: + +``` +SELECT z.id, z.name, z.last_check, z.serial, zm.master +FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id +WHERE z.type = 'SLAVE' + AND (z.last_check IS NULL OR z.last_check + z.refresh < :ts) +ORDER BY z.id +``` + +##### oracle-zone-set-last-check-query +Set the last check timestamp after a successful check. Default: + +``` +UPDATE Zones SET last_check = :lastcheck WHERE id = :zoneid +``` + +##### oracle-updated-masters-query +Return a list of zones that need to have `NOTIFY` packets sent out. Default: + +``` +SELECT id, name, serial, notified_serial +FROM Zones +WHERE type = 'MASTER' +AND (notified_serial IS NULL OR notified_serial < serial) +``` + +##### oracle-zone-set-notified-serial-query +Set the last notified serial after packets have been sent. Default: + +``` +UPDATE Zones SET notified_serial = :serial WHERE id = :zoneid +``` + +##### oracle-also-notify-query +Return a list of hosts that should be notified, in addition to any nameservers in the NS records, when sending `NOTIFY` packets for the named zone. Default: + +``` +SELECT an.hostaddr +FROM Zones z JOIN ZoneAlsoNotify an ON z.id = an.zone_id +WHERE z.name = lower(:name) +``` + +##### oracle-zone-masters-query +Return a list of masters for the zone specified by id. Default: + +``` +SELECT master +FROM Zonemasters +WHERE zone_id = :zoneid +``` + +##### oracle-is-zone-master-query +Return a row if the specified host is a registered master for the named zone. Default: + +``` +SELECT zm.master +FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id +WHERE z.name = lower(:name) AND zm.master = :master +``` + +#### Superslave Stuff +##### oracle-accept-supernotification-query +If a supernotification should be accepted from ':ip', for the master nameserver ':ns', return a label for this supermaster. Default: + +``` +SELECT name +FROM Supermasters +WHERE ip = :ip AND nameserver = lower(:ns) +``` + +##### oracle-insert-slave-query +A supernotification has just been accepted, and we need to create an entry for the new zone. Default: + +``` +INSERT INTO Zones (id, name, type) +VALUES (zones_id_seq.NEXTVAL, lower(:zone), 'SLAVE') +RETURNING id INTO :zoneid +``` + +##### oracle-insert-master-query +We need to register the first master server for the newly created zone. Default: + +``` +INSERT INTO Zonemasters (zone_id, master) +VALUES (:zoneid, :ip) +``` diff --git a/pdns/docs/markdown/authoritative/dnssec.md b/pdns/docs/markdown/authoritative/dnssec.md index e69de29bb..1e5331a86 100644 --- a/pdns/docs/markdown/authoritative/dnssec.md +++ b/pdns/docs/markdown/authoritative/dnssec.md @@ -0,0 +1,467 @@ +# Serving authoritative DNSSEC data +(only available in PowerDNS 3.0 and beyond, not yet available in the PowerDNS Recursor) + +PowerDNS contains support for DNSSEC, enabling the easy serving of DNSSEC secured data, with minimal administrative overhead. + +In PowerDNSSEC, DNS and signatures and keys are (usually) treated as separate entities. The domain & record storage is thus almost completely devoid of DNSSEC record types. + +Instead, keying material is stored separately, allowing operators to focus on the already complicated task of keeping DNS data correct. In practice, DNSSEC related material is often stored within the same database, but within separate tables. + +If a DNSSEC configuration is found for a domain, the PowerDNS daemon will provide keys, signatures and (hashed) denials of existence automatically. + +As an example, securing an existing zone can be as simple as: + +``` +$ pdnssec secure-zone powerdnssec.org +$ pdnssec rectify-zone powerdnssec.org +``` + +Alternatively, PowerDNS can serve pre-signed zones, without knowledge of private keys. + +# A brief introduction to DNSSEC +DNSSEC is a complicated subject, but it is not required to know all the ins and outs of this protocol to be able to use PowerDNSSEC. In this section, we explain the core concepts that are needed to operate a PowerDNSSEC installation. + +Zone material is enhanced with signatures using 'keys'. Such a signature (called an RRSIG) is a cryptographic guarantee that the data served is the original data. DNSSEC keys are asymmetric (RSA, DSA or GOST), the public part is published over DNS and is called a DNSKEY record, and is used for verification. The private part is used for signing and is never published. + +To make sure that the internet knows that the key that is used for signing is the authentic key, confirmation can be gotten from the parent zone. This means that to become operational, a zone operator will have to publish a representation of the signing key to the parent zone, often a ccTLD or a gTLD. This representation is called a DS record, and is a shorter (hashed) version of the DNSKEY. + +Once the parent zone has the DS, and the zone is signed with the DNSSEC key, we are done in theory. + +However, for a variety of reasons, most DNSSEC operations run with another layer of keys. The so called 'Key Signing Key' is sent to the parent zone, and this Key Signing Key is used to sign a new set of keys called the Zone Signing Keys. + +This setup allows us to change our keys without having to tell the zone operator about it. + +A final challenge is how to DNSSEC sign the answer 'no such domain'. In the language of DNS, the way to say 'there is no such domain' (NXDOMAIN) or there is no such record type is to send an empty answer. Such empty answers are universal, and can't be signed. + +In DNSSEC parlance we therefore sign a record that says 'there are no domains between A.powerdnssec.org and C.powerdnssec.org'. This securely tells the world that B.powerdnssec.org does not exist. This solution is called NSEC, and is simple but has downsides - it also tells the world exactly which records DO exist. + +So alternatively, we can say that if a certain mathematical operation (an 'iterated salted hash') is performed on a question, that no valid answers exist that have as outcome of this operation an answer between two very large numbers. This leads to the same 'proof of non-existence'. This solution is called NSEC3. + +A PowerDNSSEC zone can either be operated in NSEC or in one of two NSEC3 modes ('inclusive' and 'narrow'). + +# Profile, Supported Algorithms, Record Types & Modes of operation +PowerDNSSEC aims to serve unexciting, standards compliant, DNSSEC information. One goal is to have relevant parts of our output be identical or equivalent to important fellow-traveller software like NLNetLabs' NSD. + +Particularly, if a PowerDNSSEC secured zone is transferred via AXFR, it should be able to contain the same records as when that zone was signed using `ldns-signzone` using the same keys and settings. + +PowerDNS supports serving pre-signed zones, as well as online ('live') signed operations. In the last case, Signature Rollover and Key Maintenance are fully managed by PowerDNS. + +## Supported Algorithms +Supported Algorithms (See the [IANA website](http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1) for more information): +- DS records (algorithm 1, 2, 3) +- RSASHA1 (algorithm 5, algorithm 7) +- RSASHA256 (algorithm 8) +- RSASHA512 (algorithm 10) +- ECC-GOST (algorithm 12) +- ECDSA (algorithm 13 and 14) + +This corresponds to: +- [RFC 4033](http://tools.ietf.org/html/rfc4033): DNS Security Introduction and Requirements +- [RFC 4034](http://tools.ietf.org/html/rfc4034): Resource Records for the DNS Security Extensions, Protocol Modifications for the DNS Security Extensions +- [RFC 4035](http://tools.ietf.org/html/rfc4035): Protocol Modifications for the DNS Security Extensions +- [RFC 4509](http://tools.ietf.org/html/rfc4509): Use of SHA-256 in DNSSEC Delegation Signer (DS) Resource Records (RRs) +- [RFC 5155](http://tools.ietf.org/html/rfc5155): DNS Security (DNSSEC) Hashed Authenticated Denial of Existence +- [RFC 5702](http://tools.ietf.org/html/rfc5702): Use of SHA-2 Algorithms with RSA in DNSKEY and RRSIG Resource Records for DNSSEC +- [RFC 5933](http://tools.ietf.org/html/rfc5933): Use of GOST Signature Algorithms in DNSKEY and RRSIG Resource Records for DNSSEC +- [RFC 6605](http://tools.ietf.org/html/rfc6605): Elliptic Curve Digital Signature Algorithm (DSA) for DNSSEC + +## DNSSEC Modes of Operation +Traditionally, DNSSEC signatures have been added to unsigned zones, and then this signed zone could be served by any DNSSEC capable authoritative server. PowerDNS supports this mode fully. + +In addition, PowerDNS supports taking care of the signing itself, in which case PowerDNS operates differently from most tutorials and handbooks. This mode is easier however. + +For relevant tradeoffs, please see [Security](#security) and [Performance](#performance.html). + +PowerDNSSEC can operate in several modes. In the simplest situation, there is a single "SQL" database that contains, in separate tables, all domain data, keying material and other DNSSEC related settings. + +This database is then replicated to all PowerDNS instances, which all serve identical records, keys and signatures. + +In this mode of operation, care should be taken that the database replication occurs over a secure network, or over an encrypted connection. This is because keying material, if intercepted, could be used to counterfeit DNSSEC data using the original keys. + +Such a single replicated database requires no further attention beyond monitoring already required during non-DNSSEC operations. + +### PowerDNSSEC Pre-signed records +In this mode, PowerDNS serves zones that already contain DNSSEC records. Such zones can either be slaved from a remote master, or can be signed using tools like OpenDNSSEC, ldns-signzone or dnssec-signzone. + +### PowerDNSSEC Front-signing +As a special feature, PowerDNSSEC can operate as a signing server which operates as a slave to an unsigned master. + +In this way, if keying material is available for an unsigned zone that is retrieved from a master server, this keying material will be used when serving data from this zone. + +As part of the zone retrieval, the equivalent of 'pdnssec rectify-zone' is run to make sure that all DNSSEC-related fields are set correctly. + +### PowerDNSSEC BIND-mode operation +Starting with PowerDNS 3.1, the bindbackend can manage keys in an SQLite3 database without launching a separate gsqlite3 backend. + +To use this mode, add "bind-dnssec-db=/var/db/bind-dnssec-db.sqlite3" to pdns.conf, and run "pdnssec create-bind-db /var/db/bind-dnssec-db.sqlite3". Then, restart PowerDNS. + +After this, you can use "pdnssec secure-zone" and all other pdnssec commands on your BIND zones without trouble. + +### PowerDNSSEC hybrid BIND-mode operation +**Warning**: This mode is only supported in 3.0, 3.0.1 and 3.4.0 and up! In 3.1 to 3.3.1, the bindbackend always did its own key storage. In 3.4.0 and up hybrid bind mode operation is optional and enabled with the bindbackend `hybrid` config option. + +PowerDNS can also operate based on 'BIND'-style zone & configuration files. This 'bindbackend' has full knowledge of DNSSEC, but has no native way of storing keying material. + +However, since PowerDNS supports operation with multiple simultaneous backends, this is not a problem. + +In hybrid mode, keying material and zone records are stored in different backends. This allows for 'bindbackend' operation in full DNSSEC mode. + +To benefit from this mode, include at least one database-based backend in the 'launch' statement. The Generic SQLite backend version 3 (gsqlite3) probably complements BIND mode best, since it does not require a database server process. + +**Warning**: For now, it is necessary to execute a manual SQL 'insert' into the domains table of the backend hosting the keying material. This is needed to generate a zone-id for the relevant domain. Sample SQL statement: **insert into domains (name, type) values ('powerdnssec.org', 'NATIVE');**. + +### Rules for filling out fields in database backends +**Note**: The BIND Backend automates all the steps outlined below, and does not need 'manual' help + +In PowerDNS 3.0 and up, two additional fields are important: 'auth' and 'ordername'. These fields are set correctly on an incoming zone transfer, and also by running `pdnssec rectify-zone`. zone2sql with the --dnssec flag aims to do this too but there are minor bugs in there, so please run `pdnssec rectify-zone` after `zone2sql`. + +The 'auth' field should be set to '1' for data for which the zone itself is authoritative, which includes the SOA record and its own NS records. + +The 'auth' field should be 0 however for NS records which are used for delegation, and also for any glue (A, AAAA) records present for this purpose. Do note that the DS record for a secure delegation should be authoritative! + +The 'ordername' field needs to be filled out depending on the NSEC/NSEC3 mode. When running in NSEC3 'Narrow' mode, the ordername field is ignored and best left empty. In NSEC/NSEC3 mode, the ordername field should be NULL for any glue but filled in for all delegation NS records and all authoritative records. In NSEC3 opt-out mode, ordername is NULL for any glue and insecure delegation NS records, but filled in for secure delegation NS records and all authoritative records. + +In 'NSEC' mode, it should contain the *relative* part of a domain name, in reverse order, with dots replaced by spaces. So 'www.uk.powerdnssec.org' in the 'powerdnssec.org' zone should have 'uk www' as its ordername. + +In 'NSEC3' non-narrow mode, the ordername should contain a lowercase base32hex encoded representation of the salted & iterated hash of the full record name. **pdnssec hash-zone-record zone record** can be used to calculate this hash. + +In addition, from 3.2 and up, PowerDNS fully supports empty non-terminals. If you have a zone example.com, and a host a.b.c.example.com in it, rectify-zone (and the AXFR client code) will insert b.c.example.com and c.example.com in the records table with type NULL (SQL NULL, not 'NULL'). Having these entries provides several benefits. We no longer reply NXDOMAIN for these shorter names (this was an RFC violation but not one that caused trouble). But more importantly, to do NSEC3 correctly, we need to be able to prove existence of these shorter names. The type=NULL records entry gives us a place to store the NSEC3 hash of these names. + +If your frontend does not add empty non-terminal names to records, you will get DNSSEC replies of 3.1-quality, which has served many people well, but we suggest you update your code as soon as possible! + +If you import presigned zones into your database, please do not import the NSEC or NSEC3 records. PowerDNS will synthesize these itself. Putting them in the database might cause duplicate records in responses. zone2sql filters NSEC and NSEC3 automatically. + +# Migration +This chapter discusses various migration strategies, from existing PowerDNS setups, from existing unsigned installations and finally from previous non-PowerDNS DNSSEC deployments. + +## From an existing PowerDNS installation +To migrate an existing database-backed PowerDNS installation, a few changes must be made to the database schema. First, the records table gains two new fields: 'auth' and 'ordername'. Some data in a zone, like glue records, should not be signed, and this is signified by setting 'auth' to 0. + +**Warning**: Once the database schema has been updated, and the relevant `gsql-dnssec` switch has been set, stricter rules apply for filling out the database! The short version is: run `pdnssec rectify-all-zones`, even those not secured with DNSSEC! + +Additionally, NSEC and NSEC3 in non-narrow mode require ordering data in order to perform (hashed) denial of existence. The 'ordername' field is used for this purpose. + +Finally, two new tables are needed. DNSSEC keying material is stored in the 'cryptokeys' table (in a portable standard format). Domain metadata is stored in the 'domainmetadata' table. This includes NSEC3 settings. + +Once the database schema has been changed for DNSSEC usage (see the relevant backend chapters or [the PowerDNSSEC wiki](http://wiki.powerdns.com/trac/wiki/PDNSSEC) for the update statements), the `pdnssec` tool can be used to fill out keying details, and 'rectify' the auth and ordername fields. + +In short, `pdnssec secure-zone powerdnssec.org ; pdnssec rectify-zone powerdnssec.org` will deliver a correctly NSEC signed zone. + +In addition, so will the [`zone2sql`](migration.md#zone2sql) import tool when run with the `--dnssec` flag. + +## From existing non-DNSSEC non-PowerDNS setups + +TBD, see [Migration](migration.md). + +## From existing DNSSEC non-PowerDNS setups, pre-signed +Industry standard signed zones can be served natively by PowerDNS, without changes. In such cases, signing happens externally to PowerDNS, possibly via OpenDNSSEC, ldns-sign or dnssec-sign. + +PowerDNS needs to know if a zone should receive DNSSEC processing. To configure, run `pdnssec set-presigned zone`. + +**Warning** Right now, you will also need to configure NSEC(3) settings for pre-signed zones using `pdnssec set-nsec3`. Default is NSEC, in which case no further configuration is necessary. + +## From existing DNSSEC non-PowerDNS setups, live signing +The `pdnssec` tool features the option to import zone keys in the industry standard private key format, version 1.2. To import an existing KSK, use `pdnssec import-zone-key zonename filename KSK`, replace KSK by ZSK for a Zone Signing Key. + +If all keys are imported using this tool, a zone will serve mostly identical records to before, with the important change that the RRSIG inception dates will be different. + +**Note**: Within PowerDNS, the 'algorithm' for RSASHA1 keys is modulated based on the NSEC3 setting. So if an algorithm=7 key is imported in a zone with no configured NSEC3, it will appear as algorithm 5! + +# Records, Keys, signatures, hashes within PowerDNSSEC in online signing mode +Within PowerDNSSEC live signing, keys are stored separately from the zone records. Zone data are only combined with signatures and keys when requests come in over the internet. + +Each zone can have a number of keys associated with it, with varying key lengths. Typically 1 or at most 2 of these keys are employed as actual Zone Signing Keys (ZSKs). During normal operations, this means that only 1 ZSK is 'active', and the other is passive. + +Should it be desired to 'roll over' to a new key, both keys can temporarily be active (and used for signing), and after a while the old key can be inactivated. Subsequently it can be removed. + +As elucidated above, there are several ways in which DNSSEC can deny the existence of a record, and this setting too is stored away from zone records, and lives with the DNSSEC keying material. + +In order to facilitate interoperability with existing technologies, PowerDNSSEC keys can be imported and exported in industry standard formats. + +Keys and hashes are configured using the 'pdnssec' tool, which is described next. + +## (Hashed) Denial of Existence + +PowerDNS supports unhashed secure denial of existence using NSEC records. These are generated with the help of the (database) backend, which needs to be able to supply the 'previous' and 'next' records in canonical ordering. + +The Generic SQL Backends have fields that allow them to supply these relative record names. + +In addition, hashed secure denial of existence is supported using NSEC3 records, in two modes, one with help from the database, the other with the help of some additional calculations. + +NSEC3 in 'broad' or 'inclusive' mode works with the aid of the backend, where the backend should be able to supply the previous and next domain names in hashed order. + +NSEC3 in 'narrow' mode uses additional hashing calculations to provide hashed secure denial of existence 'on the fly', without further involving the database. + +## Signatures +In PowerDNS live signing mode, signatures, as served through RRSIG records, are calculated on the fly, and heavily cached. All CPU cores are used for the calculation. + +RRSIGs have a validity period, in PowerDNS by default this period starts at most a week in the past, and continues at least a week into the future. + +Precisely speaking, the time period used is always from the start of the previous Thursday until the Thursday two weeks later. This two-week interval jumps with one-week increments every Thursday. + +**Note**: Why Thursday? POSIX-based operating systems count the time since GMT midnight January 1st of 1970, which was a Thursday. PowerDNS inception/expiration times are generated based on an integral number of weeks having passed since the start of the 'epoch'. + +# `pdnssec` +`pdnssec` is a powerful command that is the operator-friendly gateway into PowerDNSSEC configuration. Behind the scenes, `pdnssec` manipulates a PowerDNS backend database, which also means that for many databases, `pdnssec` can be run remotely, and can configure key material on different servers. + +The following pdnssec commands are available: + +## `activate-zone-key ZONE KEY-ID` +Activate a key with id KEY-ID within a zone called ZONE. + +## `add-zone-key ZONE [ksk|zsk] [bits] [rsasha1|rsasha256|rsasha512|gost|ecdsa256|ecdsa384]` +Create a new key for zone ZONE, and make it a KSK or a ZSK, with the specified algorithm. + +## `check-zone ZONE` +Check a zone for DNSSEC correctness. Main goals is to check if the auth flag is set correctly. + +## `check-all-zones` +Check all zones for DNSSEC correctness. Added in 3.1. + +## `deactivate-zone-key ZONE KEY-ID` +Deactivate a key with id KEY-ID within a zone called ZONE. + +## `export-zone-dnskey ZONE KEY-ID` +Export to standard output DNSKEY and DS of key with key id KEY-ID within zone called ZONE. + +## `export-zone-key ZONE KEY-ID` +Export to standard output full (private) key with key id KEY-ID within zone called ZONE. The format used is compatible with BIND and NSD/LDNS. + +## `hash-zone-record ZONE RECORDNAME` +This convenience command hashes the name 'recordname' according to the NSEC3 settings of ZONE. Refuses to hash for zones with no NSEC3 settings. + +## `import-zone-key ZONE filename [ksk|zsk]` +Import from 'filename' a full (private) key for zone called ZONE. The format used is compatible with BIND and NSD/LDNS. KSK or ZSK specifies the flags this key should have on import. + +## `import-zone-key-pem ZONE filename algorithm [ksk|zsk]` +Import from 'filename' a full (private) key in PEM format for zone called ZONE, and assign it an algorithm number. KSK or ZSK specifies the flags this key should have on import. The format used is compatible with 'openssl genrsa', which is also called PEM. + +## `generate-zone-key [ksk|zsk] [algorithm] [bits]` +Generate and display a zone key. Can be used when you need to generate a key for some script backend. Does not store the key. + +## `rectify-zone ZONE [ZONE ..]` +Calculates the 'ordername' and 'auth' fields for a zone called ZONE so they comply with DNSSEC settings. Can be used to fix up migrated data. Can always safely be run, it does no harm. Multiple zones can be supplied. + +## `rectify-all-zones` +Do a rectify-zone for all the zones. Be careful when running this. Only bind and gmysql backends are supported. Added in 3.1. + +## `remove-zone-key ZONE KEY-ID` +Remove a key with id KEY-ID from a zone called ZONE. + +## `secure-zone ZONE` +Configures a zone called ZONE with reasonable DNSSEC settings. You should manually run `rectify-zone` afterwards. + +## `secure-all-zones` +Add keymaterial to all zones. You should manually run `rectify-all-zones` afterwards. The `increase-serial` option increases the SOA serial for new secured zones. + +## `set-nsec3 ZONE 'parameters' [narrow]` +Sets NSEC3 parameters for this zone. A sample command line is: `pdnssec set-nsec3 powerdnssec.org '1 0 1 ab' narrow`. The NSEC3 parameters must be quoted on the command line. + +**Warning**: If running in RSASHA1 mode (algorithm 5 or 7), switching from NSEC to NSEC3 will require a DS update at the parent zone! + +The NSEC3 fields are: 'algorithm flags iterations salt'. For 'algorithm', currently '1' is the only supported value. Setting 'flags' to 1 enables opt-out operation. Only do this if you know you need it. The salt is hexadecimal. + +## `set-presigned ZONE` +Switches zone to presigned operation, utilizing in-zone RRSIGs. + +## `show-zone ZONE` +Shows all DNSSEC related settings of a zone called ZONE. + +## `unset-nsec3 ZONE` +Converts a zone to NSEC operations. + +**Warning**: If running in RSASHA1 mode (algorithm 5 or 7), switching from NSEC to NSEC3 will require a DS update at the parent zone! + +## `unset-presigned ZONE` +Disables presigned operation for ZONE. + +## `import-tsig-key name algorithm key` +Imports a named TSIG key. Use enable/disable-tsig-key to map it to a zone. + +## `generate-tsig-key name algorithm` +Creates and stores a named tsig key. + +## `delete-tsig-key name` +Deletes a named TSIG key. **Warning**: Does not unmap it from zones. + +## `list-tsig-keys` +Shows all TSIG keys from all backends. + +## `activate-tsig-key zone name [master|slave]` +activate TSIG key for a zone. Use master on master server, slave on slave server. + +## `deactivate-tsig-key zone name [master|slave]` +Deactivate TSIG key for a zone. Use master on master server, slave on slave server. + +## `get-meta ZONE [kind kind..]` +Gets one or more meta items for domain ZONE. If no meta keys defined, it retrieves well known meta keys. + +## `set-meta ZONE kind [value value ..]` +Clears or sets meta for domain ZONE. You can provide one or more value(s). + +# DNSSEC advice & precautions +DNSSEC is a major change in the way DNS works. Furthermore, there is a bewildering array of settings that can be configured. + +It is well possible to configure DNSSEC in such a way that your domain will not operate reliably, or even, at all. + +We advise operators to stick to the keying defaults of `pdnssec secure-zone`: RSASHA256 (algorithm 8), 1 Key Signing Key of 2048 bits and 1 active Zone Signing Key of 1024 bits. + +While the 'GOST' and 'ECDSA' algorithms are better choices in theory, not many DNSSEC resolvers can validate answers signed with such keys. Much the same goes for RSASHA512, except that it does not offer better performance either. + +**Note**: GOST may be more widely available in Russia, because it might be mandatory to implement this regional standard there. + +It is possible to operate a zone with different keying algorithms simultaneously, but it has also been observed that this is not reliable. + +Depending on your master/slave setup, you may need to tinker with SOA-EDIT on your master. + +## Packet sizes, fragments, TCP/IP service +DNSSEC answers contain (bulky) keying material and signatures, and are therefore a lot larger than regular DNS answers. Normal DNS responses almost always fit in the 'magical' 512 byte limit previously imposed on DNS. + +In order to support DNSSEC, operators must make sure that their network allows for: + +- >512 byte UDP packets on port 53 +- Fragmented UDP packets +- ICMP packets related to fragmentation +- TCP queries on port 53 +- EDNS0 queries/responses (filtered by some firewalls) + +If any of the conditions outlined above is not met, DNSSEC service will suffer or be completely unavailable. + +In addition, the larger your DNS answers, the more critical the above becomes. It is therefore advised not to provision too many keys, or keys that are unnecessarily large. + +# Operational instructions +In this chapter various DNSSEC transitions are discussed, and how to execute them within PowerDNSSEC. + +## Publishing a DS +To publish a DS to a parent zone, utilize 'pdnssec show-zone' and take the DS from its output, and transfer it securely to your parent zone. + +## ZSK rollover +``` +$ pdnssec activate-zone-key ZONE next-key-id +$ pdnssec deactivate-zone-key ZONE prev-key-id +$ pdnssec remove-zone-key ZONE prev-key-id +``` + +## KSK rollover +``` +pdnssec add-zone-key ZONE ksk +pdnssec show-zone ZONE +``` + +Communicate duplicate DS + +``` +pdnssec activate-zone-key ZONE next-key-id +pdnssec deactivate-zone-key ZONE prev-key-id +pdnssec remove-zone-key ZONE prev-key-id +``` + +## Going insecure +`pdnssec disable-dnssec` + +## NSEC(3) change +This section describes how to change NSEC(3) parameters when they are already set. + +**Warning**: The following instructions might not be correct or complete! +``` +pdnssec set-nsec3 ZONE 'parameters' +pdnssec show-zone ZONE +``` + +Communicate duplicate DS. + +For further details, please see [the `pdnssec`](#pdnssec) documentation. + +# PKCS\#11 support +**Note**: This feature is experimental, and not ready for production. Use at your own risk! +To enable it, compile PowerDNS Authoritative Server using --experimental-pkcs11-support flag. This requires you to have p11-kit libraries and headers. + +Instructions on how to setup SoftHSM to work with the feature after compilation on ubuntu/debian. +- apt-get install softhsm p11-kit +- create directory /etc/pkcs11/modules +- Add file called 'softhsm' there with (on some versions, use softhsm.module) + + ``` + module: /home/cmouse/softhsm/lib/softhsm/libsofthsm.so + managed: yes + ``` + +- Run p11-kit -l to verify it worked (you should see softhsm there) +- Create at least two tokens (ksk and zsk) with (slot-number starts from 0) + + ``` + softhsm --init-token --slot slot-number --label zone-ksk|zone-zsk --pin some-pin --so-pin another-pin + ``` + +- Run p11-kit -l to verify it worked (you should see softhsm there and tokens) +- Assign the keys using + + ``` + pdnssec hsm assign zone rsasha256 ksk|zsk softhsm slot-id pin zone-ksk|zsk + ``` + +- Take note of the generated key id, if it always shows up 1, run pdnssec show-zone zone to retrieve them +- Generate the keys using + + ``` + pdnssec hsm create-key zone key-id + ``` + +- Verify that everything worked with pdnssec show-zone zone, you should see valid data there +- Enjoy using PKCS\#11! + +# Secure transfers +From 3.3.1 and up, PowerDNS support secure DNSSEC transfers as described in [draft-koch-dnsop-dnssec-operator-change-05](https://ietf.org/doc/draft-koch-dnsop-dnssec-operator-change/). If the [`direct-dnskey`](settings.md#direct-dnskey) option is enabled the foreign DNSKEY records stored in the database are added to the keyset and signed with the KSK. Without the direct-dnskey option DNSKEY records in the database are silently ignored. + +# Security +During typical PowerDNSSEC operation, the private part of the signing keys are 'online', which can be compared to operating an HTTPS server, where the certificate is available on the webserver for cryptographic purposes. + +In some settings, having such (private) keying material available online is considered undesirable. In this case, consider running in pre-signed mode. + +# Performance +DNSSEC has a performance impact, mostly measured in terms of additional memory used for the signature caches. In addition, on startup or AXFR-serving, a lot of signing needs to happen. + +Please see [Large Scale DNSSEC Best Current Practices](http://wiki.powerdns.com/trac/wiki/LargeScaleDNSSECBCP) for the most up to date information. + +# Thanks to, acknowledgements +PowerDNSSEC has been made possible by the help & contributions of many people. We would like to thank: + +- Peter Koch (DENIC) +- Olaf Kolkman (NLNetLabs) +- Wouter Wijngaards (NLNetLabs) +- Marco Davids (SIDN) +- Markus Travaille (SIDN) +- Antoin Verschuren (SIDN) +- Olafur Guðmundsson (IETF) +- Dan Kaminsky (Recursion Ventures) +- Roy Arends (Nominet) +- Miek Gieben +- Stephane Bortzmeyer (AFNIC) +- Michael Braunoeder (nic.at) +- Peter van Dijk +- Maik Zumstrull +- Jose Arthur Benetasso Villanova +- Stefan Schmidt (CCC ;-)) +- Roland van Rijswijk (Surfnet) +- Paul Bakker (Brainspark/Fox-IT) +- Mathew Hennessy +- Johannes Kuehrer (Austrian World4You GmbH) +- Marc van de Geijn (bHosted.nl) +- Stefan Arentz +- Martin van Hensbergen (Fox-IT) +- Christoph Meerwald +- Leen Besselink +- Detlef Peeters +- Christof Meerwald +- Jack Lloyd +- Frank Altpeter +- Fredrik Danerklint +- Vasiliy G Tolstov +- Brielle Bruns +- Evan Hunt (ISC) +- Ralf van der Enden +- Jan-Piet Mens +- Justin Clift +- Kees Monshouwer +- Aki Tuomi +- .. this list is far from complete yet .. diff --git a/pdns/docs/markdown/authoritative/fancy-records.md b/pdns/docs/markdown/authoritative/fancy-records.md index e69de29bb..410284282 100644 --- a/pdns/docs/markdown/authoritative/fancy-records.md +++ b/pdns/docs/markdown/authoritative/fancy-records.md @@ -0,0 +1,24 @@ +# Fancy Records +**Warning**: As of PowerDNS Authoritative Server 3.0, fancy records are no longer supported! + +PDNS also supports so called 'fancy' records. A Fancy Record is actually not a DNS record, but it is translated into one. Currently, two fancy records are implemented, but not very useful without additional unreleased software. For completeness, they are listed here. The software will become available later on and is part of the Express and PowerMail suite of programs. + +These records imply extra database lookups which has a performance impact. Therefore fancy records are only queried for if they are enabled with the **fancy-records** command in `pdns.conf`. + +## MBOXFW +This record denotes an email forward. A typical entry looks like this: + +``` + support@yourdomain.com MBOXFW you@yourcompany.com +``` + +When PDNS encounters a request for an MX record for yourdomain.com it will, if fancy records are enabled, also check for the existence of an MBOXFW record ending on '@yourdomain.com', in which case it will hand out a record containing the configured **smtpredirector**. This server should then also be able to access the PDNS database to figure out where mail to support@yourdomain.com should go to. + +## URL +URL records work in much the same way, but for HTTP. A sample record: + +``` + yourdomain.com URL http://somewhere.else.com/yourdomain +``` + +A URL record is converted into an A record containing the IP address configured with the **urlredirector** setting. On that IP address a webserver should live that knows how to redirect yourdomain.com to http://somewhere.else.com/yourdomain. diff --git a/pdns/docs/markdown/authoritative/migration.md b/pdns/docs/markdown/authoritative/migration.md index e69de29bb..ab90082ca 100644 --- a/pdns/docs/markdown/authoritative/migration.md +++ b/pdns/docs/markdown/authoritative/migration.md @@ -0,0 +1,57 @@ +# Migrating to PowerDNS +Before migrating to PowerDNS a few things should be considered. + +PowerDNS does not operate as a 'slave' or 'master' server with all backends. +Only the [Generic SQL](backend-generic-mypgsql.md), [BIND](backend-bind.md) backends have the ability to act as master or slave. + +To migrate, the `zone2sql` tool is provided. + +Additionally, the PowerDNS source comes with a number of diagnostic tools, which can be helpful in verifying proper PowerDNS operation, versus incumbent nameservers. See [Tools to analyse DNS traffic](../tools/analysis.md) for more details. + +# Zone2sql +`zone2sql` parses BIND `named.conf` files and zone files and outputs SQL on standard out, which can then be fed to your database. +It understands the Bind master file extension `$GENERATE` and will also honour `$ORIGIN` and `$TTL`. + +For backends supporting slave operation (currently only the Generic PostgreSQL, Generic MySQL and BIND backend), there is also an option to keep slave zones as slaves, and not convert them to native operation. + +`zone2sql` can generate SQL for the Generic PostgreSQL, Generic MySQL and Oracle backends. The following commands are available: + +## `--bare` +Output in a bare format, suitable for further parsing. The output is formatted as follows: + +``` + domain_id'qname''qtype''content'priottl +``` + +## `--gmysql` +Output in format suitable for the default configuration of the Generic MySQL backend. + +## `--gpgsql` +Output in format suitable for the default configuration of the Generic PostgreSQL backend. + +## `--help` +List options. + +## `--named-conf` +Parse this named.conf to find locations of zones. + +## `--on-error-resume-next` +Ignore missing files during parsing. Dangerous. + +## `--oracle` +Output in format suitable for the default configuration of the Generic Oracle backend. + +## `--slave` +Maintain slave status of zones listed in named.conf as being slaves. The default behaviour is to convert all zones to native operation. + +## `--transactions` +For Oracle and PostgreSQL output, wrap each domain in a transaction for higher speed and integrity. + +## `--verbose` +Be verbose during conversion. + +## `--zone` +Parse only this zone file. Conflicts with `--named-conf` parameter. + +## `--zone-name` +When parsing a single zone without \$ORIGIN statement, set this as the zone name. diff --git a/pdns/docs/markdown/authoritative/modes-of-operation.md b/pdns/docs/markdown/authoritative/modes-of-operation.md index 4cc863c69..8d56b29fa 100644 --- a/pdns/docs/markdown/authoritative/modes-of-operation.md +++ b/pdns/docs/markdown/authoritative/modes-of-operation.md @@ -30,7 +30,6 @@ This instructs PDNS to notify all IP addresses it considers to be slaves of this * `pdns_control notify-host ` This is truly an override and sends a notification to an arbitrary IP address. Can be used in [`also-notify`](settings.md#also-notify) situations or when PDNS has trouble figuring out who to notify - which may happen in contrived configurations. - # Slave operation On launch, PDNS requests from all backends a list of domains which have not been checked recently for changes. This should happen every '**refresh**' seconds, as specified in the SOA record. All domains that are unfresh are then checked for changes over at their master. If the [SOA](../types.md#soa) serial number there is higher, the domain is retrieved and inserted into the database. In any case, after the check the domain is declared 'fresh', and will only be checked again after '**refresh**' seconds have passed. diff --git a/pdns/docs/markdown/authoritative/performance.md b/pdns/docs/markdown/authoritative/performance.md index e69de29bb..7b3e6c778 100644 --- a/pdns/docs/markdown/authoritative/performance.md +++ b/pdns/docs/markdown/authoritative/performance.md @@ -0,0 +1,40 @@ +# Performance and Tuning +## General advice +In general, best performance is achieved on recent Linux 3.x kernels and using MySQL, although many of the largest PowerDNS installations are based on PostgreSQL. FreeBSD also performs very well. + +Database servers can require configuration to achieve decent performance. It is especially worth noting that several vendors ship PostgreSQL with a slow default configuration. + +**Warning**: When deploying (large scale) IPv6, please be aware some Linux distributions leave IPv6 routing cache tables at very small default values. Please check and if necessary raise `sysctl net.ipv6.route.max_size`. + +## Performance related settings +When PowerDNS starts up it creates a number of threads to listen for packets. This is configurable with the [`receiver-threads`](settings.md#receiver-threads) setting which defines how many sockets will be opened by the powerdns process. In versions of linux before kernel 3.9 having too many receiver threads set up resulted in decreased performance due to socket contention between multiple CPUs - the typical sweet spot was 3 or 4. For optimal performance on kernel 3.9 and following with [`reuseport`](settings.md#reuseport) enabled you'll typically want a receiver thread for each core on your box if backend latency/performance is not an issue and you want top performance. + +Different backends will have different characteristics - some will want to have more parallel instances than others. In general, if your backend is latency bound, like most relational databases are, it pays to open more backends. + +This is done with the [`distributor-threads`](settings.md#distributor-threads) setting which says how many distributors will be opened for each receiver thread. Of special importance is the choice between 1 or more backends. In case of only 1 thread, PDNS reverts to unthreaded operation which may be a lot faster, depending on your operating system and architecture. + +Another very important setting is [`cache-ttl`](settings.md#cache-ttl). PDNS caches entire packets it sends out so as to save the time to query backends to assemble all data. The default setting of 20 seconds may be low for high traffic sites, a value of 60 seconds rarely leads to problems. + +Some PDNS operators set cache-ttl to many hours or even days, and use [`pdns_control`](../appendix/pdns-internals.md#pdns_control)` purge` to selectively or globally notify PDNS of changes made in the backend. Also look at the [Query Cache](#query-cache) described in this chapter. It may materially improve your performance. + +To determine if PDNS is unable to keep up with packets, determine the value of the [`qsize-q`](logging.md#counters) variable. This represents the number of packets waiting for database attention. During normal operations the queue should be small. + +Logging truly kills performance as answering a question from the cache is an order of magnitude less work than logging a line about it. Busy sites will prefer to turn [`log-dns-details`](settings.md#log-dns-details) off. + +# Packet Cache +PDNS by default uses the 'Packet Cache' to recognise identical questions and supply them with identical answers, without any further processing. The default time to live is 10 seconds. It has been observed that the utility of the packet cache increases with the load on your nameserver. + +Not all backends may benefit from the packetcache. If your backend is memory based and does not lead to context switches, the packetcache may actually hurt performance. + +The size of the packetcache can be observed with `/etc/init.d/pdns show packetcache-size` + +# Query Cache +Besides entire packets, PDNS can also cache individual backend queries. Each DNS query leads to a number of backend queries, the most obvious additional backend query is the check for a possible CNAME. So, when a query comes in for the 'A' record for 'www.powerdns.com', PDNS must first check for a CNAME for 'www.powerdns.com'. + +The Query Cache caches these backend queries, many of which are quite repetitive. PDNS only caches queries with no answer, or with exactly one. In the future this may be expanded but this lightweight solution is very simple and therefore fast. + +Most gain is made from caching negative entries, ie, queries that have no answer. As these take little memory to store and are typically not a real problem in terms of speed-of-propagation, the default TTL for negative queries is a rather high 60 seconds. + +This only is a problem when first doing a query for a record, adding it, and immediately doing a query for that record again. It may then take up to 60 seconds to appear. Changes to existing records however do not fall under the negative query ttl ([`negquery-cache-ttl`](settings.md#negquery-cache-ttl)), but under the generic [`query-cache-ttl`](settings.md#query-cache-ttl) which defaults to 20 seconds. + +The default values should work fine for many sites. When tuning, keep in mind that the Query Cache mostly saves database access but that the Packet Cache also saves a lot of CPU because 0 internal processing is done when answering a question from the Packet Cache. diff --git a/pdns/docs/markdown/authoritative/recursion.md b/pdns/docs/markdown/authoritative/recursion.md index e69de29bb..ad1b2391f 100644 --- a/pdns/docs/markdown/authoritative/recursion.md +++ b/pdns/docs/markdown/authoritative/recursion.md @@ -0,0 +1,35 @@ +# Recursion with the Authoritative Server +(only available from 1.99.8 and onwards, recursing component available since 2.9.5) + +From 2.9.5 onwards, PowerDNS offers both authoritative nameserving capabilities and a recursive nameserver component. These two halves are normally separate but many users insist on combining both recursion and authoritative service on one IP address. This can be likened to running Apache and Squid both on port 80. + +However, many sites want to do this anyhow and some with good reason. For example, a setup like this allows the creation of fake domains which only exist for local users. Such domains often don't end on ".com" or ".org" but on ".intern" or ".name-of-isp". + +PowerDNS can cooperate with either its own recursor or any other you have available to deliver recursive service on its port. + +By specifying the [`recursor`](settings.md#recursor) option in the configuration file, questions requiring recursive treatment will be handed over to the IP address specified. An example configuration might be `recursor=130.161.180.1`, which designates 130.161.180.1 as the nameserver to handle recursive queries. + +**Warning**:Using `recursor` is NOT RECOMMENDED as it comes with many potentially nasty surprises. + +Take care not to point `recursor` to the PowerDNS Authoritative Server itself, which leads to a very tight packet loop! + +By specifying [`allow-recursion`](settings.md#allow-recursion), recursion can be restricted to netmasks specified. The default is to allow recursion from everywhere. Example: `allow-recursion=192.168.0.0/24, 10.0.0.0/8, 192.0.2.4`. + +## Details +Questions carry a number of flags. One of these is called 'Recursion Desired'. If PDNS is configured to allow recursion, AND such a flag is seen, AND the IP address of the client is allowed to recurse via PDNS, then the packet may be handed to the recursing backend. + +If a Recursion Desired packet arrives and PDNS is configured to allow recursion, but not to the IP address of the client, resolution will proceed as if the RD flag were unset and the answer will indicate that recursion was not available. + +It is also possible to use a resolver living on a different port. To do so, specify a recursor like this: `recursor=192.0.2.1:5300` + +If the backend does not answer a question within a large amount of time, this is logged as 'Recursive query for remote 10.96.0.2 with internal id 0 was not answered by backend within timeout, reusing id'. This may happen when using 'BIND' as a recursor as it is prone to drop queries which it can't answer immediately. + +To make sure that the local authoritative database overrides recursive information, PowerDNS first tries to answer a question from its own database. If that succeeds, the answer packet is sent back immediately without involving the recursor in any way. This means that for questions for which there is no answer, PowerDNS will consult the recursor for an recursive query, even if PowerDNS is authoritative for a domain! This will only cause problems if you 'fake' domains which don't really exist. + +If you want to create such fake domains or override existing domains, please set the `allow-recursion-override` feature (available from 2.9.14 until 2.9.22.6). + +Some packets, like those asking for MX records which are needed for SMTP transport of email, can be subject to 'additional processing'. This means that a recursing nameserver is obliged to try to add A records (IP addresses) for any of the mail servers mentioned in the packet, should it have these addresses available. + +If PowerDNS encounters records needing such processing and finds that it does not have the data in its authoritative database, it will send an opportunistic quick query to the recursing component to see if it perhaps has such data. This question is worded such that the recursing nameserver should return immediately such as not to block the authoritative nameserver. + +This marks a change from pre-2.9.5 behaviour where a packet was handed wholesale to the recursor in case it needed additional processing which could not proceed from the authoritative database. diff --git a/pdns/docs/markdown/authoritative/security.md b/pdns/docs/markdown/authoritative/security.md index e69de29bb..4d2ba7987 100644 --- a/pdns/docs/markdown/authoritative/security.md +++ b/pdns/docs/markdown/authoritative/security.md @@ -0,0 +1,33 @@ +# Security Settings +PDNS has several options to easily allow it to run more securely. Most notable are the [`chroot`](settings.md#chroot), [`setuid`](settings.md#setuid) and [`setgid`](settings.md#setgid) options which can be specified. + +For additional information on PowerDNS security, PowerDNS security incidents and PowerDNS security policy, see [our security policy](../security/index.md). + +## Running as a less privileged identity + +By specifying [`setuid`](settings.md#setuid) and [`setgid`](settings.md#setgid), PDNS changes to this identity shortly after binding to the privileged DNS ports. These options are highly recommended. It is suggested that a separate identity is created for PDNS as the user 'nobody' is in fact quite powerful on most systems. + +Both these parameters can be specified either numerically or as real names. You should set these parameters immediately if they are not set! + +## Jailing the process in a chroot + +The [`chroot`](settings.md#chroot) option secures PDNS to its own directory so that even if it should become compromised and under control of external influences, it will have a hard time affecting the rest of the system. + +Even though this will hamper hackers a lot, chroot jails have been known to be broken. + +**Warning**: When chrooting PDNS, take care that backends will be able to get to their files. Many databases need access to a UNIX domain socket which should live within the chroot. It is often possible to hardlink such a socket into the chroot dir. + +When running with master or slave support, be aware that many operating systems need access to specific libraries (often `/lib/libnss*`) in order to support resolution of domain names! You can also hardlink these. + +In addition, make sure that `/dev/log` is available from within the chroot. Logging will silently fail over time otherwise (on logrotate). + +The default PDNS configuration is best chrooted to `./`, which boils down to the configured location of the controlsocket. + +This is achieved by adding the following to pdns.conf: `chroot=./`, and restarting PDNS. + +# Security Considerations +In general, make sure that the PDNS process is unable to execute commands on your backend database. Most database backends will only need SELECT privilege. Take care to not connect to your database as the 'root' or 'sa' user, and configure the chosen user to have very slight privileges. + +Databases empathically do not need to run on the same machine that runs PDNS! In fact, in benchmarks it has been discovered that having a separate database machine actually improves performance. + +Separation will enhance your database security highly. Recommended. diff --git a/pdns/docs/markdown/authoritative/settings.md b/pdns/docs/markdown/authoritative/settings.md index 80aa17024..144e92519 100644 --- a/pdns/docs/markdown/authoritative/settings.md +++ b/pdns/docs/markdown/authoritative/settings.md @@ -190,7 +190,12 @@ Allow this many incoming TCP DNS connections simultaneously. Default directory for modules. See ["Modules and Backends"](#XXX). ## `negquery-cache-ttl` -Seconds to store queries with no answer in the Query Cache. See ["Query Cache"](#XXX). +| | | +|:-|:-| +|Type|Integer| +|Default|60| + +Seconds to store queries with no answer in the Query Cache. See ["Query Cache"](performance.md#query-cache). ## `no-config` Do not attempt to read the configuration file. @@ -214,13 +219,18 @@ Only send AXFR NOTIFY to these IP addresses or netmasks. The default is to notif Boolean, do out of zone additional processing. This means that if a malicious user adds a '.com' zone to your server, it is not used for other domains and will not contaminate answers. Do not enable this setting if you run a public DNS service with untrusted users. Off by default. ## `pipebackend-abi-version` -ABI version to use for the pipe backend. See ["PipeBackend protocol"](#XXX). +ABI version to use for the pipe backend. See ["PipeBackend protocol"](backend-pipe.md#pipebackend-protocol). ## `prevent-self-notification` Boolean, available as of 3.3. PowerDNS Authoritative Server attempts to not send out notifications to itself in master mode. In very complicated situations we could guess wrong and not notify a server that should be notified. In that case, set prevent-self-notification to "no". ## `query-cache-ttl` -Seconds to store queries with an answer in the Query Cache. See ["Query Cache"](#XXX). +| | | +|:-|:-| +|Type|Integer| +|Default|20| + +Seconds to store queries with an answer in the Query Cache. See ["Query Cache"](performance.md#query-cache). ## `query-local-address` The IP address to use as a source address for sending queries. Useful if you have multiple IPs and pdns is not bound to the IP address your operating system uses by default for outgoing packets. diff --git a/pdns/docs/markdown/authoritative/virtual.md b/pdns/docs/markdown/authoritative/virtual.md index e69de29bb..0b61040d3 100644 --- a/pdns/docs/markdown/authoritative/virtual.md +++ b/pdns/docs/markdown/authoritative/virtual.md @@ -0,0 +1,8 @@ +# Virtual Hosting +It may be advantageous to run multiple separate PDNS installations on a single host, for example to make sure that different customers cannot affect each others zones. PDNS fully supports running multiple instances on one host. + +To generate additional PDNS instances, copy the init.d script `pdns` to `pdns-name`, where `name` is the name of your virtual configuration. Must not contain a - as this will confuse the script. + +When you launch PDNS via this renamed script, it will seek configuration instructions not in `pdns.conf` but in `pdns-name.conf`, allowing for separate specification of parameters. + +**Warninge**: Be aware however that the init.d `force-stop` will kill all PDNS instances! -- 2.49.0