A backend that wants to act as a 'superslave' for a master should
implement the following method:
-::
+.. code-block:: cpp
- class DNSBackend
+ class DNSBackend
{
virtual bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
};
domains table. The following SQL does the job:
.. literalinclude:: ../../modules/gmysqlbackend/enable-foreign-keys.mysql.sql
+ :language: SQL
Using MySQL replication
-----------------------
This is the schema for 4.2. For 4.1, please find `the 4.1 schema on GitHub <https://github.com/PowerDNS/pdns/blob/rel/auth-4.1.x/modules/godbcbackend/schema.mssql.sql>`_.
.. literalinclude:: ../../modules/godbcbackend/schema.mssql.sql
+ :language: SQL
Load this into the database as follows:
Add the options required to your ``pdns.conf``:
-::
+.. code-block:: ini
launch=godbc
godbc-datasource=pdns1
Below, you will find the schema for 4.2. If you are using 4.1 or earlier, please find `the 4.1 schema on GitHub <https://github.com/PowerDNS/pdns/blob/rel/auth-4.1.x/modules/goraclebackend/schema.goracle.sql>`_.
.. literalinclude:: ../../modules/goraclebackend/schema.goracle.sql
+ :language: SQL
This schema contains all elements needed for master, slave and
superslave operation.
This is the 4.2 schema. Please find `the 4.1 schema on GitHub <https://github.com/PowerDNS/pdns/blob/rel/auth-4.1.x/modules/gpgsqlbackend/schema.pgsql.sql>`_.
.. literalinclude:: ../../modules/gpgsqlbackend/schema.pgsql.sql
+ :language: SQL
within one minute (this is determined by the
:ref:`setting-slave-cycle-interval`
setting). There is no need to inform PowerDNS that a new domain was
-added. Typical output is:
-
-.. code-block:: SQL
-
- 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 example.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 'example.com'
- Apr 09 13:35:30 AXFR done for 'example.com'
- Apr 09 13:35:30 [gPgSQLBackend] Closing connection
+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 example.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 'example.com'
+ Apr 09 13:35:30 AXFR done for 'example.com'
+ Apr 09 13:35:30 [gPgSQLBackend] Closing connection
From now on, PowerDNS is authoritative for the 'example.com' zone and
will respond accordingly for queries within that zone.
------------------------
The last thing you need to do is telling PowerDNS to use the SQLite
-backend.
+backend in pdns.conf:
-::
+.. code-block:: ini
- # in pdns.conf
launch=gsqlite3
gsqlite3-database=<path to your SQLite database>
to the database was made.
Compiling the SQLite backend
------------------------------
+----------------------------
Before you can begin compiling PowerDNS with the SQLite backend you need
to have the SQLite utility and library installed on your system. You can
To launch the ldap backend:
-::
+.. code-block:: ini
launch=ldap
``named.conf`` (usually located in /etc) as input and writes the dns
record entries in ldif format to stdout:
-::
+.. code-block:: shell
zone2ldap
--basedn=YOUR_BASE_DN \
Alternatively zone2ldap can be used to convert only single zone files
instead all zones:
-::
+.. code-block:: shell
zone2ldap
--basedn=YOUR_BASE_DN \
the "associatedDomain" and "dc" attributes. The utility is executed on
the command line by:
-::
+.. code-block:: shell
./bind2pdns-ldap
--host=HOSTNAME_OR_IP \
which can be imported into the LDAP tree. The bash script except below
automates this:
-::
+.. code-block:: shell
DNSSERVER=127.0.0.1
DOMAINS="example.com 10.10.in-addr.arpa"
This will yield the following result:
-::
+.. code-block:: shell
- $dig any www.test.com @127.0.0.1 -p5300 +multiline
+ $ dig any www.test.com @127.0.0.1 -p5300 +multiline
; <<>> DiG 9.7.3 <<>> any www.test.com @127.0.0.1 -p5300 +multiline
;; global options: +cmd
;; Got answer:
.. _setting-lua-f_lookup:
-``lua-f_lookup = mynewfunction``
+.. code-block:: ini
+
+ lua-f_lookup = mynewfunction
will call the function ``mynewfunction`` for the lookup-routine.
First make your error function then you put this in ``pdns.conf``:
-``lua-f_exec_error = YOUR_METHOD``
+.. code-block:: ini
+
+ lua-f_exec_error = YOUR_METHOD
DNSSEC
------
(including the trailing slash or backslash, depending on your operating
system) and opendbx-database to the name of the file.
-.. code-block:: SQL
+.. code-block:: ini
opendbx-host-read = /path/to/file/
opendbx-host-write = /path/to/file/
SQLite Schema
~~~~~~~~~~~~~
-::
+.. code-block:: SQL
CREATE TABLE "domains" (
"id" INTEGER NOT NULL PRIMARY KEY,
SQLite3 Schema
~~~~~~~~~~~~~~
-::
+.. code-block:: SQL
CREATE TABLE "domains" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
the database file and doesn't support the default statement for starting
transactions. Please add the following lines to your pdns.conf:
-::
+.. code-block:: ini
opendbx-database = /var/lib/firebird2/data/powerdns.gdb
opendbx-sql-transactbegin = SET TRANSACTION
(key size exceeds implementation restriction for index
"pdns\_unq\_domains\_name") when creating the tables.
-::
+.. code-block:: SQL
CREATE TABLE "domains" (
"id" INTEGER NOT NULL,
default statement for starting transactions. Please add the following
lines to your pdns.conf:
-::
+.. code-block:: ini
opendbx-host-read = MSSQL2k
opendbx-host-write = MSSQL2k
opendbx-sql-transactbegin = BEGIN TRANSACTION
-::
+.. code-block:: SQL
SET quoted_identifier ON;
doesn't support the default statement for starting transactions. Please
add the following lines to your pdns.conf:
-::
+.. code-block:: ini
opendbx-host-read = SYBASE
opendbx-host-write = SYBASE
opendbx-sql-transactbegin = BEGIN TRANSACTION
-::
+.. code-block:: SQL
SET quoted_identifier ON;
Uses a different syntax for transactions and requires the following
additional line in your pdns.conf:
-::
+.. code-block:: ini
opendbx-sql-transactbegin = SET TRANSACTION NAME 'AXFR'
-::
+.. code-block:: SQL
CREATE TABLE "domains" (
"id" INTEGER NOT NULL,
Looking for records based on owner name and type. Default:
-::
+.. code-block:: SQL
SELECT fqdn, ttl, type, content, zone_id, last_change, auth
FROM Records
Looking for records from one zone based on owner name and type. Default:
-::
+.. code-block:: SQL
SELECT fqdn, ttl, type, content, zone_id, last_change, auth
FROM Records
Looking for records based on owner name. Default:
-::
+.. code-block:: SQL
SELECT fqdn, ttl, type, content, zone_id, last_change, auth
FROM Records
Looking for records from one zone based on owner name. Default:
-::
+.. code-block:: SQL
SELECT fqdn, ttl, type, content, zone_id, last_change, auth
FROM Records
Looking for all records from one zone. Default:
-::
+.. code-block:: SQL
SELECT fqdn, ttl, type, content, zone_id, last_change, auth
FROM Records
Fetch the content of the metadata entries of type ':kind' for the zone
called ':name', in their original order. Default:
-::
+.. code-block:: SQL
SELECT md.meta_content
FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id
You can skip this if you do not plan to manage zones with the
``pdnsutil`` tool. Default:
-::
+.. code-block:: SQL
DELETE FROM ZoneMetadata md
WHERE zone_id = (SELECT id FROM Zones z WHERE z.name = lower(:name))
Create a metadata entry. You can skip this if you do not plan to manage
zones with the ``pdnsutil`` tool. Default:
-::
+.. code-block:: SQL
INSERT INTO ZoneMetadata (zone_id, meta_type, meta_ind, meta_content)
VALUES (
Retrieved the TSIG key specified by ':name'. Default:
-::
+.. code-block:: SQL
SELECT algorithm, secret
FROM TSIGKeys
Retrieve the DNSSEC signing keys for a zone. Default:
-::
+.. code-block:: SQL
SELECT k.id, k.flags, k.active, k.keydata
FROM ZoneDNSKeys k JOIN Zones z ON z.id = k.zone_id
Delete a DNSSEC signing key. You can skip this if you do not plan to
manage zones with the ``pdnsutil`` tool. Default:
-::
+.. code-block:: SQL
DELETE FROM ZoneDNSKeys WHERE id = :keyid
Add a DNSSEC signing key. You can skip this if you do not plan to manage
zones with the ``pdnsutil`` tool. Default:
-::
+.. code-block:: SQL
- INSERT INTO ZoneDNSKeys (id, zone_id, flags, active, keydata) "
+ INSERT INTO ZoneDNSKeys (id, zone_id, flags, active, keydata)
VALUES (
zonednskeys_id_seq.NEXTVAL,
(SELECT id FROM Zones WHERE name = lower(:name)),
Enable or disable a DNSSEC signing key. You can skip this if you do not
plan to manage zones with the **pdnsutil** tool. Default:
-::
+.. code-block:: SQL
UPDATE ZoneDNSKeys SET active = :active WHERE id = :keyid
Default:
-::
+.. code-block:: SQL
BEGIN
get_canonical_prev_next(:zoneid, :name, :prev, :next);
successor in NSEC3 zone ordering into ``:prev`` and ``:next``, and the
FQDN of the predecessor into ``:unhashed``. Default:
-::
+.. code-block:: SQL
BEGIN
get_hashed_prev_next(:zoneid, :hash, :unhashed, :prev, :next);
Get some basic information about the named zone before doing
master/slave things. Default:
-::
+.. code-block:: SQL
SELECT id, name, type, last_check, serial, notified_serial
FROM Zones
transfer. This happens inside a transaction, so if the transfer fails,
the old zone content will still be there. Default:
-::
+.. code-block:: SQL
DELETE FROM Records WHERE zone_id = :zoneid
happens inside the same transaction as delete-zone, so we will not end
up with a partially transferred zone. Default:
-::
+.. code-block:: SQL
INSERT INTO Records (id, fqdn, zone_id, ttl, type, content)
VALUES (records_id_seq.NEXTVAL, lower(:name), :zoneid, :ttl, :type, :content)
generally do any post-processing your schema requires. The do-nothing
default:
-::
+.. code-block:: SQL
DECLARE
zone_id INTEGER := :zoneid;
Return multiple rows, identical except for the master address, for zones
with more than one master. Default:
-::
+.. code-block:: SQL
SELECT z.id, z.name, z.last_check, z.serial, zm.master
FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id
Set the last check timestamp after a successful check. Default:
-::
+.. code-block:: SQL
UPDATE Zones SET last_check = :lastcheck WHERE id = :zoneid
Return a list of zones that need to have ``NOTIFY`` packets sent out.
Default:
-::
+.. code-block:: SQL
SELECT id, name, serial, notified_serial
FROM Zones
Set the last notified serial after packets have been sent. Default:
-::
+.. code-block:: SQL
UPDATE Zones SET notified_serial = :serial WHERE id = :zoneid
nameservers in the NS records, when sending ``NOTIFY`` packets for the
named zone. Default:
-::
+.. code-block:: SQL
SELECT an.hostaddr
FROM Zones z JOIN ZoneAlsoNotify an ON z.id = an.zone_id
Return a list of masters for the zone specified by id. Default:
-::
+.. code-block:: SQL
SELECT master
FROM Zonemasters
Return a row if the specified host is a registered master for the named
zone. Default:
-::
+.. code-block:: SQL
SELECT zm.master
FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id
If a supernotification should be accepted from ':ip', for the master
nameserver ':ns', return a label for this supermaster. Default:
-::
+.. code-block:: SQL
SELECT name
FROM Supermasters
A supernotification has just been accepted, and we need to create an
entry for the new zone. Default:
-::
+.. code-block:: SQL
INSERT INTO Zones (id, name, type)
VALUES (zones_id_seq.NEXTVAL, lower(:zone), 'SLAVE')
We need to register the first master server for the newly created zone.
Default:
-::
+.. code-block:: SQL
INSERT INTO Zonemasters (zone_id, master)
VALUES (:zoneid, :ip)
The only configuration options for backend are remote-connection-string
and remote-dnssec.
-::
+.. code-block:: ini
remote-connection-string=<type>:<param>=<value>,<param>=<value>...
parameters: path, timeout (default 2000ms)
-::
+.. code-block:: ini
remote-connection-string=unix:path=/path/to/socket
parameters: command,timeout (default 2000ms)
-::
+.. code-block:: ini
remote-connection-string=pipe:command=/path/to/executable,timeout=2000
parameters: url, url-suffix, post, post_json, timeout (default 2000ms)
-::
+.. code-block:: ini
remote-connection-string=http:url=http://localhost:63636/dns,url-suffix=.php
parameters: endpoint, timeout (default 2000ms)
-::
+.. code-block:: ini
remote-connection-string=zeromq:endpoint=ipc:///tmp/tmp.sock
Query:
-::
+.. code-block:: json
{"method":"initialize", "parameters":{"command":"/path/to/something", "timeout":"2000", "something":"else"}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"lookup", "parameters":{"qtype":"ANY", "qname":"www.example.com.", "remote":"192.0.2.24", "local":"192.0.2.1", "real-remote":"192.0.2.24", "zone-id":-1}}
Response:
-::
+.. code-block:: json
{"result":[{"qtype":"A", "qname":"www.example.com", "content":"203.0.113.2", "ttl": 60}]}
Query:
-::
+.. code-block:: json
{"method":"list", "parameters":{"zonename":"example.com.","domain_id":-1}}
Response (split into lines for ease of reading)
-::
+.. code-block:: json
{"result":[
{"qtype":"SOA", "qname":"example.com", "content":"dns1.icann.org. hostmaster.icann.org. 2012081600 7200 3600 1209600 3600", "ttl": 3600},
Query:
-::
+.. code-block:: json
{"method":"getbeforeandafternamesabsolute", "params":{"id":0,"qname":"www.example.com"}}
Response:
-::
+.. code-block:: json
- {”result":{"before":"ns1","after":""}}
+ {"result":{"before":"ns1","after":""}}
Example HTTP/RPC
''''''''''''''''
Response:
-::
+.. code-block:: json
- {”result":{"before":"ns1","after":""}}
+ {"result":{"before":"ns1","after":""}}
``getAllDomainMetadata``
~~~~~~~~~~~~~~~~~~~~~~~~
Query:
-::
+.. code-block:: json
{"method":"getalldomainmetadata", "parameters":{"name":"example.com"}}
Response:
-::
+.. code-block:: json
{"result":{"PRESIGNED":["0"]}}
Query:
-::
+.. code-block:: json
{"method":"getdomainmetadata", "parameters":{"name":"example.com.","kind":"PRESIGNED"}}
Response:
-::
+.. code-block:: json
{"result":["0"]}
Query:
-::
+.. code-block:: json
{"method":"setdomainmetadata","parameters":{"name":"example.com","kind":"PRESIGNED","value":["YES"]}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"getdomainkeys","parameters":{"name":"example.com."}}
Response:
-::
+.. code-block:: json
{"result":[{"id":1,"flags":256,"active":true,"content":"Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Query:
-::
+.. code-block:: json
{"method":"adddomainkey", "parameters":{"key":{"id":1,"flags":256,"active":true,"content":"Private-key-format: v1.2
Algorithm: 8 (RSASHA256)
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
- {"method":"removedomainkey","parameters":"{"name":"example.com","id":1}}
+ {"method":"removedomainkey","parameters":{"name":"example.com","id":1}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"activatedomainkey","parameters":{"name":"example.com","id":1}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"deactivatedomainkey","parameters":{"name":"example.com","id":1}}
Response:
-::
+.. code-block:: json
{"result": true}
Query:
-::
+.. code-block:: json
{"method":"gettsigkey","parameters":{"name":"example.com."}}
Response:
-::
+.. code-block:: json
- {"result":{"algorithm":"hmac-md5","content:"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="}}
+ {"result":{"algorithm":"hmac-md5","content":"kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="}}
Example HTTP/RPC
''''''''''''''''
Query:
-::
+.. code-block:: json
{"method":"getdomaininfo","parameters":{"name":"example.com"}}
Response:
-::
+.. code-block:: json
- {"result":{id:1,"zone":"example.com","kind":"NATIVE","serial":2002010100}}
+ {"result":{"id":1,"zone":"example.com","kind":"NATIVE","serial":2002010100}}
Example HTTP/RPC
''''''''''''''''
Query:
-::
+.. code-block:: json
{"method":"setnotified","parameters":{"id":1,"serial":2002010100}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"isMaster","parameters":{"name":"example.com","ip":"198.51.100.0.1"}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"superMasterBackend","parameters":{"ip":"198.51.100.0.1","domain":"example.com","nsset":[{"qtype":"NS","qname":"example.com","qclass":1,"content":"ns1.example.com","ttl":300,"auth":true},{"qtype":"NS","qname":"example.com","qclass":1,"content":"ns2.example.com","ttl":300,"auth":true}]}}
Response:
-::
+.. code-block:: json
{"result":true}
Alternative response:
-::
+.. code-block:: json
{"result":{"account":"my account","nameserver":"ns2.example.com"}}
Query:
-::
+.. code-block:: json
{"method":"createSlaveDomain","parameters":{"ip":"198.51.100.0.1","domain":"pirate.example.net"}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"replaceRRSet","parameters":{"domain_id":2,"qname":"replace.example.com","qtype":"A","trxid":1370416133,"rrset":[{"qtype":"A","qname":"replace.example.com","qclass":1,"content":"1.1.1.1","ttl":300,"auth":true}]}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"feedRecord","parameters":{"rr":{"qtype":"A","qname":"replace.example.com","qclass":1,"content":"127.0.0.1","ttl":300,"auth":true},"trxid":1370416133}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"feedEnts","parameters":{"domain_id":2,"trxid":1370416133,"nonterm":["_sip._udp","_udp"]}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"feedEnts3","parameters":{"domain_id":2,"domain":"example.com","times":1,"salt":"9642","narrow":false,"trxid":1370416356,"nonterm":["_sip._udp","_udp"]}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"startTransaction","parameters":{"trxid":1234,"domain_id":1,"domain":"example.com"}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"commitTransaction","parameters":{"trxid":1234}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"abortTransaction","parameters":{"trxid":1234}}
Response:
-::
+.. code-block:: json
{"result":true}
Query:
-::
+.. code-block:: json
{"method":"calculateSOASerial","parameters":{"domain":"unit.test","sd":{"qname":"unit.test","nameserver":"ns.unit.test","hostmaster":"hostmaster.unit.test","ttl":300,"serial":1,"refresh":2,"retry":3,"expire":4,"default_ttl":5,"domain_id":-1,"scopeMask":0}}}
Response:
-::
+.. code-block:: json
{"result":2013060501}
Query:
-::
+.. code-block:: json
{"method":"directBackendCmd","parameters":{"query":"PING"}}
Response:
-::
+.. code-block:: json
{"result":"PONG"}
Query:
-::
+.. code-block:: json
{"method": "getAllDomains", "parameters": {"include_disabled": true}}
Response:
-::
+.. code-block:: json
{"result":[{"id":1,"zone":"unit.test.","masters":["10.0.0.1"],"notified_serial":2,"serial":2,"last_check":1464693331,"kind":"native"}]}
Query:
-::
+.. code-block:: json
{"method":"searchRecords","parameters":{"pattern":"www.example*","maxResults":100}}
Response:
-::
+.. code-block:: json
{"result":[{"qtype":"A", "qname":"www.example.com", "content":"203.0.113.2", "ttl": 60}]}
Query:
-::
+.. code-block:: json
{"method": "getUpdatedMasters", "parameters": {}}
Response:
-::
+.. code-block:: json
{"result":[{"id":1,"zone":"unit.test.","masters":["10.0.0.1"],"notified_serial":2,"serial":2,"last_check":1464693331,"kind":"master"}]}
Query:
-::
+.. code-block:: json
{
"method": "lookup",
Reply:
-::
+.. code-block:: json
{
"result":
Reply:
-::
+.. code-block:: json
{
"result":
If however our slaves would ignore us, as some are prone to do, we can
send some additional notifications
-::
+.. code-block:: shell
$ sudo pdns_control notify example.org
Added to queue
Conversely, if PowerDNS needs to be reminded to retrieve a zone from a
master, a command is provided
-::
+.. code-block:: shell
$ sudo pdns_control retrieve forfun.net
Added retrieval request for 'forfun.net' from master 212.187.98.67
As an example, securing an existing zone can be as simple as:
-::
+.. code-block:: shell
$ pdnsutil secure-zone powerdnssec.org
To deliver a correctly signed zone with the :ref:`dnssec-pdnsutil-dnssec-defaults`, invoke:
-::
+.. code-block:: shell
pdnsutil secure-zone ZONE
To view the DS records for this zone (to transfer to the parent zone),
run
-::
+.. code-block:: shell
pdnsutil show-zone ZONE
For a more traditional setup with a KSK and a ZSK, use the following
sequence of commands:
-::
+.. code-block:: shell
pdnsutil add-zone-key ZONE ksk 2048 active rsasha256
pdnsutil add-zone-key ZONE zsk 1024 active rsasha256
industry standard private key format, version 1.2. To import an existing
KSK, use
-::
+.. code-block:: shell
pdnsutil import-zone-key ZONE FILENAME ksk
Going insecure
--------------
-::
+.. code-block:: shell
pdnsutil disable-dnssec ZONE
As stated earlier, PowerDNS uses NSEC by default. If you want to use
NSEC3 instead, issue:
-::
+.. code-block:: shell
pdnsutil set-nsec3 ZONE [PARAMETERS]
e.g.
-::
+.. code-block:: shell
pdnsutil set-nsec3 example.net '1 0 1 ab'
To convert a zone from NSEC3 to NSEC operations, run:
-::
+.. code-block:: shell
pdnsutil unset-nsec3 ZONE
update. If you have GSS-TSIG enabled, you can use Kerberos principals
here. An example, using :program:`pdnsutil` to create the key:
-::
+.. code-block:: shell
- pdnsutil generate-tsig-key test hmac-md5
+ $ pdnsutil generate-tsig-key test hmac-md5
Create new TSIG key test hmac-md5 kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=
-
+
+::
+
sql> insert into tsigkeys (name, algorithm, secret) values ('test', 'hmac-md5', 'kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=');
sql> select id from domains where name='example.org';
5
sql> insert into domainmetadata (domain_id, kind, content) values (5, 'TSIG-ALLOW-DNSUPDATE', 'test');
-An example of how to use a TSIG key with the :program:`nsupdate` command:
-
-::
+An example of how to use a TSIG key with the :program:`nsupdate` command::
nsupdate <<!
server <ip> <port>
We're going to use a TSIG key for security. We're going to generate a
key using the following command:
-::
+.. code-block:: shell
dnssec-keygen -a hmac-md5 -b 128 -n USER dhcpdupdate
This generates two files (Kdhcpdupdate.*.key and
Kdhcpdupdate.*.private). You're interested in the .key file:
-::
+.. code-block:: shell
# ls -l Kdhcp*
-rw------- 1 root root 53 Aug 26 19:29 Kdhcpdupdate.+157+20493.key
Enabled DNS update (:rfc:`2136`) support functionality in PowerDNS by adding
the following to the PowerDNS configuration file (pdns.conf).
-::
+.. code-block:: ini
dnsupdate=yes
allow-dnsupdate-from=
there is also resolve(qname, qtype) which returns array of records.
Example:
-::
+.. code-block:: lua
resolve("www.google.com", pdns.A)
Simple example script:
-.. code:: lua
+.. code-block:: lua
--- This script is not suitable for production use
Example:
-::
+.. code-block:: shell
pdnsutil set-meta powerdns.org ALLOW-AXFR-FROM AUTO-NS 2001:db8::/48
::
- select id from domains where name='example.com';
+ sql> select id from domains where name='example.com';
7
- insert into domainmetadata (domain_id, kind, content) values (7,'ALLOW-AXFR-FROM','AUTO-NS');
- insert into domainmetadata (domain_id, kind, content) values (7,'ALLOW-AXFR-FROM','2001:db8::/48');
+ sql> insert into domainmetadata (domain_id, kind, content) values (7,'ALLOW-AXFR-FROM','AUTO-NS');
+ sql> insert into domainmetadata (domain_id, kind, content) values (7,'ALLOW-AXFR-FROM','2001:db8::/48');
To disallow all IP's, except those explicitly allowed by domainmetadata
records, add ``allow-axfr-ips=`` to ``pdns.conf``.
multiple times). The nameserver may have contain an optional port
number. e.g.:
-::
+.. code-block:: shell
pdnsutil set-meta powerdns.org ALSO-NOTIFY 192.0.2.1:5300
pdnsutil set-meta powerdns.org ALLOW-AXFR-FROM 2001:db8:53::1
Or in SQL:
-::
+.. code-block:: SQL
insert into domainmetadata (domain_id, kind, content) values (7,'ALSO-NOTIFY','192.0.2.1:5300');
insert into domainmetadata (domain_id, kind, content) values (7,'ALLOW-AXFR-FROM','2001:db8:53::1');
setting to an existing resolver and enable
:ref:`setting-expand-alias`:
-::
+.. code-block:: ini
resolver=[::1]:5300
expand-alias=yes
following lines, adjusted for your local setup (specifically, you may
not want to use the 'root' user):
-::
+.. code-block:: ini
launch=gmysql
gmysql-host=127.0.0.1
following commands:
.. literalinclude:: ../../modules/gmysqlbackend/schema.mysql.sql
+ :language: SQL
Now we have a database and an empty table. PowerDNS should now be able
to launch in monitor mode and display no errors:
In a different shell, a sample query sent to the server should now
return quickly without data:
-::
+.. code-block:: shell
$ dig +short www.example.com @127.0.0.1
$
If we now requery our database, ``www.example.com`` should be present:
-::
+.. code-block:: shell
$ dig +short www.example.com @127.0.0.1
192.0.2.10
To start the rollover, add an **active** new KSK to the zone
(example.net in this case):
-::
+.. code-block:: shell
pdnsutil add-zone-key example.net ksk active
rollover is now in the "New KSK" stage. Retrieve the DS record(s) for
the new KSK:
-::
+.. code-block:: shell
pdnsutil show-zone example.net
The key-id for the old KSK is shown in the output of
``pdnsutil show-zone example.net``.
-::
+.. code-block:: shell
pdnsutil remove-zone-key example.net KEY-ID
To make the authoritative server listen on the local loopback address
and port 5300 change the following in ``pdns.conf``:
-::
+.. code-block:: ini
local-ipv6=
local-address=127.0.0.1
``recursor.conf``. The domains should be forwarded to 127.0.0.1:5300
(the new address and port of the Authoritative Server):
-::
+.. code-block:: ini
forward-zones=private.example.com=127.0.0.1:5300
forward-zones+=another.example.com=127.0.0.1:5300
To make the authoritative server listen on the local loopback address
and port 5300 change the following in ``pdns.conf``:
-::
+.. code-block:: ini
local-ipv6=
local-address=127.0.0.1
different port than the Authoritative Server. Set the following in
``recursor.conf``:
-::
+.. code-block:: ini
local-address=127.0.0.1
local-port=5301
``recursor.conf``. The domains should be forwarded to 127.0.0.1:5300
(the new address and port of the Authoritative Server):
-::
+.. code-block:: ini
forward-zones=private.example.com=127.0.0.1:5300
forward-zones+=another.example.com=127.0.0.1:5300
``pdns-myinstance.conf`` exists in the configuration directory, the
following command will start the service:
-::
+.. code-block:: shell
systemctl start pdns@myinstance.service
Similarly you can enable it at boot:
-::
+.. code-block:: shell
systemctl enable pdns@myinstance.service
you can skip this step), we add an ECDSA 256 bit key (algorithm 13)
here:
-::
+.. code-block:: shell
pdnsutil add-zone-key example.net zsk inactive ecdsa256
To change the RRSIGs on your records, the new key must be made active.
Note: you can get the key-ids with ``pdnsutil show-zone example.net``:
-::
+.. code-block:: shell
pdnsutil activate-zone-key example.net new-key-id
pdnsutil deactivate-zone-key example.net previous-key-id
The last step is to remove the old key from the completely:
-::
+.. code-block:: shell
pdnsutil remove-zone-key example.net previous-key-id
PowerDNS Authoritative Server is available through the
`apt <https://packages.debian.org/pdns-server>`__ system.
-::
+.. code-block:: shell
# apt-get install pdns-server
packages <https://packages.debian.org/pdns-backend>`__, install the
required backend as follows:
-::
+.. code-block:: shell
# apt-get install pdns-backend-$backend
Add either to your list of repositories and install PowerDNS by issuing:
-::
+.. code-block:: shell
# yum install pdns
The different backends can be installed using
-::
+.. code-block:: shell
# yum install pdns-backend-$backend
For the package:
-::
+.. code-block:: shell
# pkg install dns/powerdns
To have your system build the port:
-::
+.. code-block:: shell
cd /usr/ports/dns/powerdns/ && make install clean
PowerDNS Authoritative Server is available through Homebrew:
-::
+.. code-block:: shell
$ brew install pdns
the 'domains' table with the IP of your current master. On your current
master, make sure that this master allows AXFRs to this new slave.
-::
+.. code-block:: SQL
INSERT INTO domains (name,type,master) VALUES ('example.net', 'SLAVE', '198.51.100.101');
this server is the new :ref:`master <master-operation>`, change the type of
domain in the database:
-::
+.. code-block:: SQL
UPDATE domains set type='MASTER' where type='SLAVE';
Or, if you want to use :ref:`native <native-operation>`:
-::
+.. code-block:: SQL
UPDATE domains set type='NATIVE' where type='SLAVE';
An example call to ``zone2sql`` could be:
-::
+.. code-block:: shell
zone2sql --named-conf=/path/to/named.conf --gmysql | mysql -u pdns -p pdns-db
want has an ``id`` of 3, the following SQL statement will enable the Lua
script ``my.lua`` for that domain:
-::
+.. code-block:: SQL
INSERT INTO domainmetadata (domain_id, kind, content) VALUES (3, "LUA-AXFR-SCRIPT", "/lua/my.lua");
Consider the following simple example:
-::
+.. code-block:: lua
function axfrfilter(remoteip, zone, record)
'responses' sent to the PowerDNS Authoritative Server 'question' address
can be blocked by issuing:
-::
+.. code-block:: shell
iptables -I INPUT -p udp --dst $AUTHIP --dport 53 \! -f -m u32 --u32 "0>>22&0x3C@8>>15&0x01=1" -j DROP
For those running custom PowerDNS versions, just applying this patch may
be easier:
-::
+.. code-block:: diff
--- pdns/common_startup.cc (revision 2326)
+++ pdns/common_startup.cc (working copy)
In its most simple form, supply all backends that need to be launched.
e.g.
-::
+.. code-block:: ini
launch=bind,gmysql,remote
different configuration, you can specify a name for later
instantiations. e.g.:
-::
+.. code-block:: ini
launch=gmysql,gmysql:server2
Otherwise there will be error trying to resolve address.
For example, slaves support both IPv4 and IPv6, but PowerDNS master have only IPv4,
- so allow only IPv4 with ``only-notify``::
+ so allow only IPv4 with ``only-notify``:
+
+ .. code-block:: ini
only-notify=0.0.0.0/0
$ dig -t axfr powerdnssec.org @127.0.0.1 -y 'test:kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys='
Another of importing and activating TSIG keys into the database is using
-:doc:`pdnsutil <manpages/pdnsutil.1>`::
+:doc:`pdnsutil <manpages/pdnsutil.1>`:
+
+.. code-block:: shell
pdnsutil import-tsig-key test hmac-md5 'kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys='
pdnsutil activate-tsig-key powerdnssec.org test master
previous section.
For the Generic SQL backends, configuring the use of TSIG for AXFR
-requests could be achieved as follows:
-
-::
+requests could be achieved as follows::
insert into tsigkeys (name, algorithm, secret) values ('test', 'hmac-md5', 'kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=');
select id from domains where name='powerdnssec.org';
This can also be done using
:doc:`/manpages/pdnsutil.1`:
-::
+.. code-block:: shell
pdnsutil import-tsig-key test hmac-md5 'kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys='
pdnsutil activate-tsig-key powerdnssec.org test slave
the previous section.
In the interest of interoperability, the configuration above is (not
-quite) similar to the following BIND statements:
-
-::
+quite) similar to the following BIND statements::
key test. {
algorithm hmac-md5;