1 Dynamic DNS Update (RFC2136)
2 ============================
4 Starting with the PowerDNS Authoritative Server 3.4.0, DNS update
5 support is available. There are a number of items NOT supported:
7 - There is no support for GSS\*TSIG and SIG (TSIG is supported);
8 - WKS records are specifically mentioned in the RFC, we don't
9 specifically care about WKS records;
10 - Anything we forgot....
12 The implementation requires the backend to support a number of new
13 operations. Currently, the following backends have been modified to
16 - :doc:`gmysql <backends/generic-mysql>`
17 - :doc:`gpgsql <backends/generic-postgresql>`
18 - :doc:`gsqlite3 <backends/generic-sqlite3>`
19 - :doc:`goracle <backends/generic-oracle>`
20 - :doc:`godbc <backends/generic-odbc>`
22 .. _dnsupdate-configuration-options:
27 There are two configuration parameters that can be used within the
28 powerdns configuration file.
33 A setting to enable/disable DNS update support completely. The default
34 is no, which means that DNS updates are ignored by PowerDNS (no message
35 is logged about this!). Change the setting to ``dnsupdate=yes`` to
36 enable DNS update support. Default is ``no``.
38 ``allow-dnsupdate-from``
39 ~~~~~~~~~~~~~~~~~~~~~~~~
41 A list of IP ranges that are allowed to perform updates on any domain.
42 The default is ``127.0.0.0/8``, which means that all loopback addresses are accepted.
43 Multiple entries can be used on this line
44 (``allow-dnsupdate-from=198.51.100.0/8 203.0.113.2/32``). The option can
45 be left empty to disallow everything, this then should be used in
46 combination with the ``ALLOW-DNSUPDATE-FROM`` :doc:`domain metadata <domainmetadata>` setting per
47 zone. Setting a range here and in ``ALLOW-DNSUPDATE-FROM`` enables updates
48 from either address range.
53 Tell PowerDNS to forward to the master server if the zone is configured
54 as slave. Masters are determined by the masters field in the domains
55 table. The default behaviour is enabled (yes), which means that it will
56 try to forward. In the processing of the update packet, the
57 ``allow-dnsupdate-from`` and ``TSIG-ALLOW-DNSUPDATE`` are processed
58 first, so those permissions apply before the ``forward-dnsupdate`` is
59 used. It will try all masters that you have configured until one is
62 .. _dnsupdate-lua-dnsupdate-policy-script:
64 ``lua-dnsupdate-policy-script``
65 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67 Use this Lua script containing function ``updatepolicy`` to validate
68 each update. This will ``TURN OFF`` all other
69 authorization methods, and you are expected to take care of everything
70 yourself. See :ref:`dnsupdate-update-policy` for details and
73 The semantics are that first a dynamic update has to be allowed either
74 by the global :ref:`setting-allow-dnsupdate-from` setting, or by a per-zone
75 ``ALLOW-DNSUPDATE-FROM`` metadata setting.
77 Secondly, if a zone has a ``TSIG-ALLOW-DNSUPDATE`` metadata setting, that
80 So to only allow dynamic DNS updates to a zone based on TSIG key, and
81 regardless of IP address, set :ref:`setting-allow-dnsupdate-from` to empty, set
82 ``ALLOW-DNSUPDATE-FROM`` to "0.0.0.0/0" and "::/0" and set the
83 ``TSIG-ALLOW-DNSUPDATE`` to the proper key name.
85 Further information can be found :ref:`below <dnsupdate-how-it-works>`.
87 .. _dnsupdate-metadata:
92 For permissions, a number of per zone settings are available via the
93 :doc:`domain metadata <domainmetadata>`.
95 .. _metadata-allow-dnsupdate-from:
100 This setting has the same function as described in the configuration
101 options (See :ref:`above <dnsupdate-configuration-options>`). Only one item is
102 allowed per row, but multiple rows can be added. An example:
106 sql> select id from domains where name='example.org';
108 sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘ALLOW-DNSUPDATE-FROM’,’198.51.100.0/8’);
109 sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘ALLOW-DNSUPDATE-FROM’,’203.0.113.2/32’);
111 This will allow 198.51.100.0/8 and 203.0.113.2/32 to send DNS update
112 messages for the example.org domain.
114 .. _metadata-tsig-allow-dnsupdate:
119 This setting allows you to set the TSIG key required to do an DNS
120 update. If you have GSS-TSIG enabled, you can use Kerberos principals
121 here. An example, using :program:`pdnsutil` to create the key:
123 .. code-block:: shell
125 $ pdnsutil generate-tsig-key test hmac-md5
126 Create new TSIG key test hmac-md5 kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=
130 sql> insert into tsigkeys (name, algorithm, secret) values ('test', 'hmac-md5', 'kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=');
131 sql> select id from domains where name='example.org';
133 sql> insert into domainmetadata (domain_id, kind, content) values (5, 'TSIG-ALLOW-DNSUPDATE', 'test');
135 An example of how to use a TSIG key with the :program:`nsupdate` command::
140 update add test1.example.org 3600 A 203.0.113.1
141 key test kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=
145 If a TSIG key is set for the domain, it is required to be used for the
146 update. The TSIG is an alternative means of securing updates, instead of using the
147 ``ALLOW-DNSUPDATE-FROM`` setting. If a TSIG key is set, and if ``ALLOW-DNSUPDATE-FROM`` is set,
148 the IP(-range) of the updater still needs to be allowed via ``ALLOW-DNSUPDATE-FROM``.
150 .. _metadata-forward-dnsupdate:
155 See :ref:`Configuration options <dnsupdate-configuration-options>` for what it does,
160 sql> select id from domains where name='example.org';
162 sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘FORWARD-DNSUPDATE’,’’);
164 There is no content, the existence of the entry enables the forwarding.
165 This domain-specific setting is only useful when the configuration
166 option :ref:`setting-forward-dnsupdate` is set to 'no', as that will disable it
167 globally. Using the domainmetadata setting than allows you to enable it
170 .. _metadata-notify-dnsupdate:
175 Send a notification to all slave servers after every update. This will
176 speed up the propagation of changes and is very useful for acme
181 sql> select id from domains where name='example.org';
183 sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘NOTIFY-DNSUPDATE’,’1’);
185 .. _metadata-soa-edit-dnsupdate:
190 This configures how the soa serial should be updated. See
191 :ref:`below <dnsupdate-soa-serial-updates>`.
193 .. _dnsupdate-soa-serial-updates:
198 After every update, the soa serial is updated as this is required by
199 section 3.7 of :rfc:`2136`. The behaviour is configurable via domainmetadata
200 with the ``SOA-EDIT-DNSUPDATE`` option. It has a number of options listed
201 below. If no behaviour is specified, DEFAULT is used.
203 :rfc:`2136, Section 3.6 <2136#section-3.6>` defines some specific behaviour for updates of SOA
204 records. Whenever the SOA record is updated via the update message, the
205 logic to change the SOA is not executed.
208 Powerdns will always use :ref:`metadata-soa-edit` when serving SOA
209 records, thus a query for the SOA record of the recently update domain,
210 might have an unexpected result due to a SOA-EDIT setting.
216 sql> select id from domains where name='example.org';
218 sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘SOA-EDIT-DNSUPDATE’,’INCREASE’);
220 This will make the SOA Serial increase by one, for every successful
223 SOA-EDIT-DNSUPDATE settings
224 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
226 These are the settings available for **SOA-EDIT-DNSUPDATE**.
228 - DEFAULT: Generate a soa serial of YYYYMMDD01. If the current serial
229 is lower than the generated serial, use the generated serial. If the
230 current serial is higher or equal to the generated serial, increase
231 the current serial by 1.
232 - INCREASE: Increase the current serial by 1.
233 - EPOCH: Change the serial to the number of seconds since the EPOCH,
235 - SOA-EDIT: Change the serial to whatever SOA-EDIT would provide. See
236 :doc:`Domain metadata <domainmetadata>`
237 - SOA-EDIT-INCREASE: Change the serial to whatever SOA-EDIT would
238 provide. If what SOA-EDIT provides is lower than the current serial,
239 increase the current serial by 1.
241 DNS update How-to: Setup dyndns/rfc2136 with dhcpd
242 --------------------------------------------------
244 DNS update is often used with DHCP to automatically provide a hostname
245 whenever a new IP-address is assigned by the DHCP server. This section
246 describes how you can setup PowerDNS to receive DNS updates from ISC's
247 dhcpd (version 4.1.1-P1).
252 We're going to use a TSIG key for security. We're going to generate a
253 key using the following command:
255 .. code-block:: shell
257 dnssec-keygen -a hmac-md5 -b 128 -n USER dhcpdupdate
259 This generates two files (Kdhcpdupdate.*.key and
260 Kdhcpdupdate.*.private). You're interested in the .key file:
262 .. code-block:: shell
265 -rw------- 1 root root 53 Aug 26 19:29 Kdhcpdupdate.+157+20493.key
266 -rw------- 1 root root 165 Aug 26 19:29 Kdhcpdupdate.+157+20493.private
268 # cat Kdhcpdupdate.+157+20493.key
269 dhcpdupdate. IN KEY 0 3 157 FYhvwsW1ZtFZqWzsMpqhbg==
271 The important bits are the name of the key (**dhcpdupdate**) and the
272 hash of the key (**FYhvwsW1ZtFZqWzsMpqhbg==**
274 Using the details from the key you've just generated. Add the following
281 secret "FYhvwsW1ZtFZqWzsMpqhbg==";
284 You must also tell dhcpd that you want dynamic dns to work, add the
290 ddns-update-style interim;
291 update-static-leases on;
295 1. Enable Dynamic DNS
296 2. Which style it must use (interim)
297 3. Update static leases as well
299 For more information on this, consult the dhcpd.conf manual.
301 Per subnet, you also have to tell **dhcpd** which (reverse-)domain it
302 should update and on which master domain server it is running.
306 ddns-domainname "example.org";
307 ddns-rev-domainname "in-addr.arpa.";
314 zone 1.168.192.in-addr.arpa. {
319 This tells **dhcpd** a number of things:
321 1. Which domain to use (**ddns-domainname "example.org";**)
322 2. Which reverse-domain to use (**dnssec-rev-domainname
324 3. For the zones, where the primary master is located (**primary
326 4. Which TSIG key to use (**key dhcpdupdate;**). We defined the key
329 This concludes the changes that are needed to the **dhcpd**
335 A number of small changes are needed to powerdns to make it accept
336 dynamic updates from **dhcpd**.
338 Enabled DNS update (:rfc:`2136`) support functionality in PowerDNS by adding
339 the following to the PowerDNS configuration file (pdns.conf).
344 allow-dnsupdate-from=
346 This tells PowerDNS to:
348 1. Enable DNS update support(:ref:`setting-dnsupdate`)
349 2. Allow updates from NO ip-address (":ref:`setting-allow-dnsupdate-from`\ =")
351 We just told powerdns (via the configuration file) that we accept
352 updates from nobody via the :ref:`setting-allow-dnsupdate-from`
353 parameter. That's not very useful, so we're going to give permissions
354 per zone (including the appropriate reverse zone), via the
355 domainmetadata table.
359 sql> select id from domains where name='example.org';
361 sql> insert into domainmetadata(domain_id, kind, content) values(5, 'ALLOW-DNSUPDATE-FROM','127.0.0.1');
362 sql> select id from domains where name='1.168.192.in-addr.arpa';
364 sql> insert into domainmetadata(domain_id, kind, content) values(6, 'ALLOW-DNSUPDATE-FROM','127.0.0.1');
366 This gives the ip '127.0.0.1' access to send update messages. Make sure
367 you use the ip address of the machine that runs **dhcpd**.
369 Another thing we want to do, is add TSIG security. This can only be done
370 via the domainmetadata table:
374 sql> insert into tsigkeys (name, algorithm, secret) values ('dhcpdupdate', 'hmac-md5', 'FYhvwsW1ZtFZqWzsMpqhbg==');
375 sql> select id from domains where name='example.org';
377 sql> insert into domainmetadata (domain_id, kind, content) values (5, 'TSIG-ALLOW-DNSUPDATE', 'dhcpdupdate');
378 sql> select id from domains where name='1.168.192.in-addr.arpa';
380 sql> insert into domainmetadata (domain_id, kind, content) values (6, 'TSIG-ALLOW-DNSUPDATE', 'dhcpdupdate');
384 1. Add the 'dhcpdupdate' key to our PowerDNSinstallation
385 2. Associate the domains with the given TSIG key
387 Restart PowerDNS and you should be ready to go!
389 .. _dnsupdate-how-it-works:
394 This is a short description of how DNS update messages are processed by
397 1. The DNS update message is received. If it is TSIG signed, the TSIG
398 is validated against the tsigkeys table. If it is not valid, Refused
399 is returned to the requestor.
400 2. A check is performed on the zone to see if it is a valid zone.
401 ServFail is returned when not valid.
402 3. The **dnsupdate** setting is checked. Refused is returned when the
404 4. If update policy Lua script is provided then skip up to 7.
405 5. If the **ALLOW-DNSUPDATE-FROM** has a value (from both
406 domainmetadata and the configuration file), a check on the value is
407 performed. If the requestor (sender of the update message) does not
408 match the values in **ALLOW-DNSUPDATE-FROM**, Refused is returned.
409 6. If the message is TSIG signed, the TSIG keyname is compared with the
410 TSIG keyname in domainmetadata. If they do not match, a Refused is
411 send. The TSIG-ALLOW-DNSUPDATE domainmetadata setting is used to
412 find which key belongs to the domain.
413 7. The backends are queried to find the backend for the given domain.
414 8. If the domain is a slave domain, the **forward-dnsupdate** option
415 and domainmetadata settings are checked. If forwarding to a master
416 is enabled, the message is forward to the master. If that fails, the
417 next master is tried until all masters are tried. If all masters
418 fail, ServFail is returned. If a master succeeds, the result from
419 that master is returned.
420 9. A check is performed to make sure all updates/prerequisites are for
421 the given zone. NotZone is returned if this is not the case.
422 10. The transaction with the backend is started.
423 11. The prerequisite checks are performed (section 3.2 of :rfc:`2136 <2136#section-3.2>`). If a
424 check fails, the corresponding RCode is returned. No further
425 processing will happen.
426 12. Per record in the update message, a the prescan checks are
427 performed. If the prescan fails, the corresponding RCode is
428 returned. If the prescan for the record is correct, the actual
429 update/delete/modify of the record is performed. If the update fails
430 (for whatever reason), ServFail is returned. After changes to the
431 records have been applied, the ordername and auth flag are set to
432 make sure DNSSEC remains working. The cache for that record is
434 13. If there are records updated and the SOA record was not modified,
435 the SOA serial is updated. See :ref:`dnsupdate-soa-serial-updates`. The cache for this record is
437 14. The transaction with the backend is committed. If this fails,
438 ServFail is returned.
439 15. NoError is returned.
441 .. _dnsupdate-update-policy:
446 .. versionadded:: 4.1.0
448 You can define a Lua script to handle DNS UPDATE message
449 authorization. The Lua script is to contain at least function called
450 ``updatepolicy`` which accepts one parameter. This parameter is an
451 object, containing all the information for the request. To permit
452 change, return true, otherwise return false. The script is called for
453 each record at a time and you can approve or reject any or all.
455 The object has following methods available:
457 - ``DNSName getQName()`` - name to update
458 - ``DNSName getZonename()`` - zone name
459 - ``int getQType()`` - record type, it can be 255(ANY) for delete.
460 - ``ComboAddress getLocal()`` - local socket address
461 - ``ComboAddress getRemote()`` - remote socket address
462 - ``Netmask getRealRemote()`` - real remote address (or netmask if EDNS Subnet is used)
463 - ``DNSName getTsigName()`` - TSIG **key** name (you can assume it is validated here)
464 - ``string getPeerPrincipal()`` - Return peer principal name (``user@DOMAIN``,
465 ``service/machine.name@DOMAIN``, ``host/MACHINE$@DOMAIN``)
467 There are many same things available as in recursor Lua scripts, but
468 there is also ``resolve(qname, qtype)`` which returns array of records.
473 resolve("www.google.com", pdns.A)
475 You can use this to perform DNS lookups. If your resolver cannot find
476 your local records, then this will not find them either. In other words,
477 resolve does not perform local lookup.
479 Simple example script:
483 --- This script is not suitable for production use
485 function strpos (haystack, needle, offset)
486 local pattern = string.format("(%s)", needle)
487 local i = string.find (haystack, pattern, (offset or 0))
488 return (i ~= nil and i or false)
491 function updatepolicy(input)
492 princ = input:getPeerPrincipal()
499 if princ == "admin@DOMAIN" or input:getRemote():toString() == "192.168.1.1"
504 if (input:getQType() == pdns.A or input:getQType() == pdns.AAAA) and princ:sub(5,5) == '/' and strpos(princ, "@", 0) ~= false
506 i = strpos(princ, "@", 0)
507 if princ:sub(i) ~= "@DOMAIN"
511 hostname = princ:sub(6, i-1)
512 if input:getQName():toString() == hostname .. "." or input:getQName():toString() == hostname .. "." .. input:getZoneName():toString()