mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-26 11:32:01 -05:00
844 lines
32 KiB
ReStructuredText
844 lines
32 KiB
ReStructuredText
..
|
|
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
See the COPYRIGHT file distributed with this work for additional
|
|
information regarding copyright ownership.
|
|
|
|
.. Advanced:
|
|
|
|
Advanced DNS Features
|
|
=====================
|
|
|
|
.. _notify:
|
|
|
|
Notify
|
|
------
|
|
|
|
DNS NOTIFY is a mechanism that allows primary servers to notify their
|
|
secondary servers of changes to a zone's data. In response to a ``NOTIFY``
|
|
from a primary server, the secondary checks to see that its version of
|
|
the zone is the current version and, if not, initiates a zone transfer.
|
|
|
|
For more information about DNS ``NOTIFY``, see the description of the
|
|
``notify`` option in :ref:`boolean_options` and the
|
|
description of the zone option ``also-notify`` in :ref:`zone_transfers`.
|
|
The ``NOTIFY`` protocol is specified in :rfc:`1996`.
|
|
|
|
.. note::
|
|
|
|
As a secondary zone can also be a primary to other secondaries, ``named``, by
|
|
default, sends ``NOTIFY`` messages for every zone it loads.
|
|
Specifying ``notify primary-only;`` causes ``named`` to only send
|
|
``NOTIFY`` for primary zones that it loads.
|
|
|
|
.. _dynamic_update:
|
|
|
|
Dynamic Update
|
|
--------------
|
|
|
|
Dynamic update is a method for adding, replacing, or deleting records in
|
|
a primary server by sending it a special form of DNS messages. The format
|
|
and meaning of these messages is specified in :rfc:`2136`.
|
|
|
|
Dynamic update is enabled by including an ``allow-update`` or an
|
|
``update-policy`` clause in the ``zone`` statement.
|
|
|
|
If the zone's ``update-policy`` is set to ``local``, updates to the zone
|
|
are permitted for the key ``local-ddns``, which is generated by
|
|
``named`` at startup. See :ref:`dynamic_update_policies` for more details.
|
|
|
|
Dynamic updates using Kerberos-signed requests can be made using the
|
|
TKEY/GSS protocol, either by setting the ``tkey-gssapi-keytab`` option
|
|
or by setting both the ``tkey-gssapi-credential`` and
|
|
``tkey-domain`` options. Once enabled, Kerberos-signed requests are
|
|
matched against the update policies for the zone, using the Kerberos
|
|
principal as the signer for the request.
|
|
|
|
Updating of secure zones (zones using DNSSEC) follows :rfc:`3007`: RRSIG,
|
|
NSEC, and NSEC3 records affected by updates are automatically regenerated
|
|
by the server using an online zone key. Update authorization is based on
|
|
transaction signatures and an explicit server policy.
|
|
|
|
.. _journal:
|
|
|
|
The Journal File
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
All changes made to a zone using dynamic update are stored in the zone's
|
|
journal file. This file is automatically created by the server when the
|
|
first dynamic update takes place. The name of the journal file is formed
|
|
by appending the extension ``.jnl`` to the name of the corresponding
|
|
zone file, unless specifically overridden. The journal file is in a
|
|
binary format and should not be edited manually.
|
|
|
|
The server also occasionally writes ("dumps") the complete contents
|
|
of the updated zone to its zone file. This is not done immediately after
|
|
each dynamic update because that would be too slow when a large zone is
|
|
updated frequently. Instead, the dump is delayed by up to 15 minutes,
|
|
allowing additional updates to take place. During the dump process,
|
|
transient files are created with the extensions ``.jnw`` and
|
|
``.jbk``; under ordinary circumstances, these are removed when the
|
|
dump is complete, and can be safely ignored.
|
|
|
|
When a server is restarted after a shutdown or crash, it replays the
|
|
journal file to incorporate into the zone any updates that took place
|
|
after the last zone dump.
|
|
|
|
Changes that result from incoming incremental zone transfers are also
|
|
journaled in a similar way.
|
|
|
|
The zone files of dynamic zones cannot normally be edited by hand
|
|
because they are not guaranteed to contain the most recent dynamic
|
|
changes; those are only in the journal file. The only way to ensure
|
|
that the zone file of a dynamic zone is up-to-date is to run
|
|
``rndc stop``.
|
|
|
|
To make changes to a dynamic zone manually, follow these steps:
|
|
first, disable dynamic updates to the zone using
|
|
``rndc freeze zone``. This updates the zone file with the
|
|
changes stored in its ``.jnl`` file. Then, edit the zone file. Finally, run
|
|
``rndc thaw zone`` to reload the changed zone and re-enable dynamic
|
|
updates.
|
|
|
|
``rndc sync zone`` updates the zone file with changes from the
|
|
journal file without stopping dynamic updates; this may be useful for
|
|
viewing the current zone state. To remove the ``.jnl`` file after
|
|
updating the zone file, use ``rndc sync -clean``.
|
|
|
|
.. _incremental_zone_transfers:
|
|
|
|
Incremental Zone Transfers (IXFR)
|
|
---------------------------------
|
|
|
|
The incremental zone transfer (IXFR) protocol is a way for secondary servers
|
|
to transfer only changed data, instead of having to transfer an entire
|
|
zone. The IXFR protocol is specified in :rfc:`1995`. See :ref:`proposed_standards`.
|
|
|
|
When acting as a primary server, BIND 9 supports IXFR for those zones where the
|
|
necessary change history information is available. These include primary
|
|
zones maintained by dynamic update and secondary zones whose data was
|
|
obtained by IXFR. For manually maintained primary zones, and for secondary
|
|
zones obtained by performing a full zone transfer (AXFR), IXFR is
|
|
supported only if the option ``ixfr-from-differences`` is set to
|
|
``yes``.
|
|
|
|
When acting as a secondary server, BIND 9 attempts to use IXFR unless it is
|
|
explicitly disabled. For more information about disabling IXFR, see the
|
|
description of the ``request-ixfr`` clause of the ``server`` statement.
|
|
|
|
When a secondary server receives a zone via AXFR, it creates a new copy of the
|
|
zone database and then swaps it into place; during the loading process, queries
|
|
continue to be served from the old database with no interference. When receiving
|
|
a zone via IXFR, however, changes are applied to the running zone, which may
|
|
degrade query performance during the transfer. If a server receiving an IXFR
|
|
request determines that the response size would be similar in size to an AXFR
|
|
response, it may wish to send AXFR instead. The threshold at which this
|
|
determination is made can be configured using the
|
|
``max-ixfr-ratio`` option.
|
|
|
|
.. _split_dns:
|
|
|
|
Split DNS
|
|
---------
|
|
|
|
Setting up different views of the DNS space to internal
|
|
and external resolvers is usually referred to as a *split DNS* setup.
|
|
There are several reasons an organization might want to set up its DNS
|
|
this way.
|
|
|
|
One common reason to use split DNS is to hide
|
|
"internal" DNS information from "external" clients on the Internet.
|
|
There is some debate as to whether this is actually useful.
|
|
Internal DNS information leaks out in many ways (via email headers, for
|
|
example) and most savvy "attackers" can find the information they need
|
|
using other means. However, since listing addresses of internal servers
|
|
that external clients cannot possibly reach can result in connection
|
|
delays and other annoyances, an organization may choose to use split
|
|
DNS to present a consistent view of itself to the outside world.
|
|
|
|
Another common reason for setting up a split DNS system is to allow
|
|
internal networks that are behind filters or in :rfc:`1918` space (reserved
|
|
IP space, as documented in :rfc:`1918`) to resolve DNS on the Internet.
|
|
Split DNS can also be used to allow mail from outside back into the
|
|
internal network.
|
|
|
|
.. _split_dns_sample:
|
|
|
|
Example Split DNS Setup
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Let's say a company named *Example, Inc.* (``example.com``) has several
|
|
corporate sites that have an internal network with reserved Internet
|
|
Protocol (IP) space and an external demilitarized zone (DMZ), or
|
|
"outside" section of a network, that is available to the public.
|
|
|
|
Example, Inc. wants its internal clients to be able to resolve
|
|
external hostnames and to exchange mail with people on the outside. The
|
|
company also wants its internal resolvers to have access to certain
|
|
internal-only zones that are not available at all outside of the
|
|
internal network.
|
|
|
|
To accomplish this, the company sets up two sets of name
|
|
servers. One set is on the inside network (in the reserved IP
|
|
space) and the other set is on bastion hosts, which are "proxy"
|
|
hosts in the DMZ that can talk to both sides of its network.
|
|
|
|
The internal servers are configured to forward all queries, except
|
|
queries for ``site1.internal``, ``site2.internal``,
|
|
``site1.example.com``, and ``site2.example.com``, to the servers in the
|
|
DMZ. These internal servers have complete sets of information for
|
|
``site1.example.com``, ``site2.example.com``, ``site1.internal``, and
|
|
``site2.internal``.
|
|
|
|
To protect the ``site1.internal`` and ``site2.internal`` domains, the
|
|
internal name servers must be configured to disallow all queries to
|
|
these domains from any external hosts, including the bastion hosts.
|
|
|
|
The external servers, which are on the bastion hosts, are configured
|
|
to serve the "public" version of the ``site1.example.com`` and ``site2.example.com``
|
|
zones. This could include things such as the host records for public
|
|
servers (``www.example.com`` and ``ftp.example.com``) and mail exchange
|
|
(MX) records (``a.mx.example.com`` and ``b.mx.example.com``).
|
|
|
|
In addition, the public ``site1.example.com`` and ``site2.example.com`` zones should
|
|
have special MX records that contain wildcard (``*``) records pointing to
|
|
the bastion hosts. This is needed because external mail servers
|
|
have no other way of determining how to deliver mail to those internal
|
|
hosts. With the wildcard records, the mail is delivered to the
|
|
bastion host, which can then forward it on to internal hosts.
|
|
|
|
Here's an example of a wildcard MX record:
|
|
|
|
::
|
|
|
|
* IN MX 10 external1.example.com.
|
|
|
|
Now that they accept mail on behalf of anything in the internal network,
|
|
the bastion hosts need to know how to deliver mail to internal
|
|
hosts. The resolvers on the bastion
|
|
hosts need to be configured to point to the internal name servers
|
|
for DNS resolution.
|
|
|
|
Queries for internal hostnames are answered by the internal servers,
|
|
and queries for external hostnames are forwarded back out to the DNS
|
|
servers on the bastion hosts.
|
|
|
|
For all of this to work properly, internal clients need to be
|
|
configured to query *only* the internal name servers for DNS queries.
|
|
This could also be enforced via selective filtering on the network.
|
|
|
|
If everything has been set properly, Example, Inc.'s internal clients
|
|
are now able to:
|
|
|
|
- Look up any hostnames in the ``site1.example.com`` and ``site2.example.com``
|
|
zones.
|
|
|
|
- Look up any hostnames in the ``site1.internal`` and
|
|
``site2.internal`` domains.
|
|
|
|
- Look up any hostnames on the Internet.
|
|
|
|
- Exchange mail with both internal and external users.
|
|
|
|
Hosts on the Internet are able to:
|
|
|
|
- Look up any hostnames in the ``site1.example.com`` and ``site2.example.com``
|
|
zones.
|
|
|
|
- Exchange mail with anyone in the ``site1.example.com`` and ``site2.example.com``
|
|
zones.
|
|
|
|
Here is an example configuration for the setup just described above.
|
|
Note that this is only configuration information; for information on how
|
|
to configure the zone files, see :ref:`sample_configuration`.
|
|
|
|
Internal DNS server config:
|
|
|
|
::
|
|
|
|
|
|
acl internals { 172.16.72.0/24; 192.168.1.0/24; };
|
|
|
|
acl externals { bastion-ips-go-here; };
|
|
|
|
options {
|
|
...
|
|
...
|
|
forward only;
|
|
// forward to external servers
|
|
forwarders {
|
|
bastion-ips-go-here;
|
|
};
|
|
// sample allow-transfer (no one)
|
|
allow-transfer { none; };
|
|
// restrict query access
|
|
allow-query { internals; externals; };
|
|
// restrict recursion
|
|
allow-recursion { internals; };
|
|
...
|
|
...
|
|
};
|
|
|
|
// sample primary zone
|
|
zone "site1.example.com" {
|
|
type primary;
|
|
file "m/site1.example.com";
|
|
// do normal iterative resolution (do not forward)
|
|
forwarders { };
|
|
allow-query { internals; externals; };
|
|
allow-transfer { internals; };
|
|
};
|
|
|
|
// sample secondary zone
|
|
zone "site2.example.com" {
|
|
type secondary;
|
|
file "s/site2.example.com";
|
|
primaries { 172.16.72.3; };
|
|
forwarders { };
|
|
allow-query { internals; externals; };
|
|
allow-transfer { internals; };
|
|
};
|
|
|
|
zone "site1.internal" {
|
|
type primary;
|
|
file "m/site1.internal";
|
|
forwarders { };
|
|
allow-query { internals; };
|
|
allow-transfer { internals; }
|
|
};
|
|
|
|
zone "site2.internal" {
|
|
type secondary;
|
|
file "s/site2.internal";
|
|
primaries { 172.16.72.3; };
|
|
forwarders { };
|
|
allow-query { internals };
|
|
allow-transfer { internals; }
|
|
};
|
|
|
|
External (bastion host) DNS server configuration:
|
|
|
|
::
|
|
|
|
acl internals { 172.16.72.0/24; 192.168.1.0/24; };
|
|
|
|
acl externals { bastion-ips-go-here; };
|
|
|
|
options {
|
|
...
|
|
...
|
|
// sample allow-transfer (no one)
|
|
allow-transfer { none; };
|
|
// default query access
|
|
allow-query { any; };
|
|
// restrict cache access
|
|
allow-query-cache { internals; externals; };
|
|
// restrict recursion
|
|
allow-recursion { internals; externals; };
|
|
...
|
|
...
|
|
};
|
|
|
|
// sample secondary zone
|
|
zone "site1.example.com" {
|
|
type primary;
|
|
file "m/site1.foo.com";
|
|
allow-transfer { internals; externals; };
|
|
};
|
|
|
|
zone "site2.example.com" {
|
|
type secondary;
|
|
file "s/site2.foo.com";
|
|
masters { another_bastion_host_maybe; };
|
|
allow-transfer { internals; externals; }
|
|
};
|
|
|
|
In the ``resolv.conf`` (or equivalent) on the bastion host(s):
|
|
|
|
::
|
|
|
|
search ...
|
|
nameserver 172.16.72.2
|
|
nameserver 172.16.72.3
|
|
nameserver 172.16.72.4
|
|
|
|
.. _tsig:
|
|
|
|
TSIG
|
|
----
|
|
|
|
TSIG (Transaction SIGnatures) is a mechanism for authenticating DNS
|
|
messages, originally specified in :rfc:`2845`. It allows DNS messages to be
|
|
cryptographically signed using a shared secret. TSIG can be used in any
|
|
DNS transaction, as a way to restrict access to certain server functions
|
|
(e.g., recursive queries) to authorized clients when IP-based access
|
|
control is insufficient or needs to be overridden, or as a way to ensure
|
|
message authenticity when it is critical to the integrity of the server,
|
|
such as with dynamic UPDATE messages or zone transfers from a primary to
|
|
a secondary server.
|
|
|
|
This section is a guide to setting up TSIG in BIND. It describes the
|
|
configuration syntax and the process of creating TSIG keys.
|
|
|
|
``named`` supports TSIG for server-to-server communication, and some of
|
|
the tools included with BIND support it for sending messages to
|
|
``named``:
|
|
|
|
* :ref:`man_nsupdate` supports TSIG via the ``-k``, ``-l``, and ``-y`` command-line options, or via the ``key`` command when running interactively.
|
|
* :ref:`man_dig` supports TSIG via the ``-k`` and ``-y`` command-line options.
|
|
|
|
Generating a Shared Key
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
TSIG keys can be generated using the ``tsig-keygen`` command; the output
|
|
of the command is a ``key`` directive suitable for inclusion in
|
|
``named.conf``. The key name, algorithm, and size can be specified by
|
|
command-line parameters; the defaults are "tsig-key", HMAC-SHA256, and
|
|
256 bits, respectively.
|
|
|
|
Any string which is a valid DNS name can be used as a key name. For
|
|
example, a key to be shared between servers called ``host1`` and ``host2``
|
|
could be called "host1-host2.", and this key can be generated using:
|
|
|
|
::
|
|
|
|
$ tsig-keygen host1-host2. > host1-host2.key
|
|
|
|
This key may then be copied to both hosts. The key name and secret must
|
|
be identical on both hosts. (Note: copying a shared secret from one
|
|
server to another is beyond the scope of the DNS. A secure transport
|
|
mechanism should be used: secure FTP, SSL, ssh, telephone, encrypted
|
|
email, etc.)
|
|
|
|
``tsig-keygen`` can also be run as ``ddns-confgen``, in which case its
|
|
output includes additional configuration text for setting up dynamic DNS
|
|
in ``named``. See :ref:`man_ddns-confgen` for details.
|
|
|
|
Loading a New Key
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
For a key shared between servers called ``host1`` and ``host2``, the
|
|
following could be added to each server's ``named.conf`` file:
|
|
|
|
::
|
|
|
|
key "host1-host2." {
|
|
algorithm hmac-sha256;
|
|
secret "DAopyf1mhCbFVZw7pgmNPBoLUq8wEUT7UuPoLENP2HY=";
|
|
};
|
|
|
|
(This is the same key generated above using ``tsig-keygen``.)
|
|
|
|
Since this text contains a secret, it is recommended that either
|
|
``named.conf`` not be world-readable, or that the ``key`` directive be
|
|
stored in a file which is not world-readable and which is included in
|
|
``named.conf`` via the ``include`` directive.
|
|
|
|
Once a key has been added to ``named.conf`` and the server has been
|
|
restarted or reconfigured, the server can recognize the key. If the
|
|
server receives a message signed by the key, it is able to verify
|
|
the signature. If the signature is valid, the response is signed
|
|
using the same key.
|
|
|
|
TSIG keys that are known to a server can be listed using the command
|
|
``rndc tsig-list``.
|
|
|
|
Instructing the Server to Use a Key
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
A server sending a request to another server must be told whether to use
|
|
a key, and if so, which key to use.
|
|
|
|
For example, a key may be specified for each server in the ``primaries``
|
|
statement in the definition of a secondary zone; in this case, all SOA QUERY
|
|
messages, NOTIFY messages, and zone transfer requests (AXFR or IXFR)
|
|
are signed using the specified key. Keys may also be specified in
|
|
the ``also-notify`` statement of a primary or secondary zone, causing NOTIFY
|
|
messages to be signed using the specified key.
|
|
|
|
Keys can also be specified in a ``server`` directive. Adding the
|
|
following on ``host1``, if the IP address of ``host2`` is 10.1.2.3, would
|
|
cause *all* requests from ``host1`` to ``host2``, including normal DNS
|
|
queries, to be signed using the ``host1-host2.`` key:
|
|
|
|
::
|
|
|
|
server 10.1.2.3 {
|
|
keys { host1-host2. ;};
|
|
};
|
|
|
|
Multiple keys may be present in the ``keys`` statement, but only the
|
|
first one is used. As this directive does not contain secrets, it can be
|
|
used in a world-readable file.
|
|
|
|
Requests sent by ``host2`` to ``host1`` would *not* be signed, unless a
|
|
similar ``server`` directive were in ``host2``'s configuration file.
|
|
|
|
When any server sends a TSIG-signed DNS request, it expects the
|
|
response to be signed with the same key. If a response is not signed, or
|
|
if the signature is not valid, the response is rejected.
|
|
|
|
TSIG-Based Access Control
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
TSIG keys may be specified in ACL definitions and ACL directives such as
|
|
``allow-query``, ``allow-transfer``, and ``allow-update``. The above key
|
|
would be denoted in an ACL element as ``key host1-host2.``
|
|
|
|
Here is an example of an ``allow-update`` directive using a TSIG key:
|
|
|
|
::
|
|
|
|
allow-update { !{ !localnets; any; }; key host1-host2. ;};
|
|
|
|
This allows dynamic updates to succeed only if the UPDATE request comes
|
|
from an address in ``localnets``, *and* if it is signed using the
|
|
``host1-host2.`` key.
|
|
|
|
See :ref:`dynamic_update_policies` for a
|
|
discussion of the more flexible ``update-policy`` statement.
|
|
|
|
Errors
|
|
~~~~~~
|
|
|
|
Processing of TSIG-signed messages can result in several errors:
|
|
|
|
- If a TSIG-aware server receives a message signed by an unknown key,
|
|
the response will be unsigned, with the TSIG extended error code set
|
|
to BADKEY.
|
|
- If a TSIG-aware server receives a message from a known key but with
|
|
an invalid signature, the response will be unsigned, with the TSIG
|
|
extended error code set to BADSIG.
|
|
- If a TSIG-aware server receives a message with a time outside of the
|
|
allowed range, the response will be signed but the TSIG extended
|
|
error code set to BADTIME, and the time values will be adjusted so
|
|
that the response can be successfully verified.
|
|
|
|
In all of the above cases, the server returns a response code of
|
|
NOTAUTH (not authenticated).
|
|
|
|
TKEY
|
|
----
|
|
|
|
TKEY (Transaction KEY) is a mechanism for automatically negotiating a
|
|
shared secret between two hosts, originally specified in :rfc:`2930`.
|
|
|
|
There are several TKEY "modes" that specify how a key is to be generated
|
|
or assigned. BIND 9 implements only one of these modes: Diffie-Hellman
|
|
key exchange. Both hosts are required to have a KEY record with
|
|
algorithm DH (though this record is not required to be present in a
|
|
zone).
|
|
|
|
The TKEY process is initiated by a client or server by sending a query
|
|
of type TKEY to a TKEY-aware server. The query must include an
|
|
appropriate KEY record in the additional section, and must be signed
|
|
using either TSIG or SIG(0) with a previously established key. The
|
|
server's response, if successful, contains a TKEY record in its
|
|
answer section. After this transaction, both participants have
|
|
enough information to calculate a shared secret using Diffie-Hellman key
|
|
exchange. The shared secret can then be used to sign subsequent
|
|
transactions between the two servers.
|
|
|
|
TSIG keys known by the server, including TKEY-negotiated keys, can be
|
|
listed using ``rndc tsig-list``.
|
|
|
|
TKEY-negotiated keys can be deleted from a server using
|
|
``rndc tsig-delete``. This can also be done via the TKEY protocol
|
|
itself, by sending an authenticated TKEY query specifying the "key
|
|
deletion" mode.
|
|
|
|
SIG(0)
|
|
------
|
|
|
|
BIND partially supports DNSSEC SIG(0) transaction signatures as
|
|
specified in :rfc:`2535` and :rfc:`2931`. SIG(0) uses public/private keys to
|
|
authenticate messages. Access control is performed in the same manner as with
|
|
TSIG keys; privileges can be granted or denied in ACL directives based
|
|
on the key name.
|
|
|
|
When a SIG(0) signed message is received, it is only verified if
|
|
the key is known and trusted by the server. The server does not attempt
|
|
to recursively fetch or validate the key.
|
|
|
|
SIG(0) signing of multiple-message TCP streams is not supported.
|
|
|
|
The only tool shipped with BIND 9 that generates SIG(0) signed messages
|
|
is ``nsupdate``.
|
|
|
|
.. _DNSSEC:
|
|
|
|
DNSSEC
|
|
------
|
|
|
|
Cryptographic authentication of DNS information is possible through the
|
|
DNS Security ("DNSSEC-bis") extensions, defined in :rfc:`4033`, :rfc:`4034`,
|
|
and :rfc:`4035`. This section describes the creation and use of DNSSEC
|
|
signed zones.
|
|
|
|
In order to set up a DNSSEC secure zone, there are a series of steps
|
|
which must be followed. BIND 9 ships with several tools that are used in
|
|
this process, which are explained in more detail below. In all cases,
|
|
the ``-h`` option prints a full list of parameters. Note that the DNSSEC
|
|
tools require the keyset files to be in the working directory or the
|
|
directory specified by the ``-d`` option.
|
|
|
|
There must also be communication with the administrators of the parent
|
|
and/or child zone to transmit keys. A zone's security status must be
|
|
indicated by the parent zone for a DNSSEC-capable resolver to trust its
|
|
data. This is done through the presence or absence of a ``DS`` record at
|
|
the delegation point.
|
|
|
|
For other servers to trust data in this zone, they must be
|
|
statically configured with either this zone's zone key or the zone key of
|
|
another zone above this one in the DNS tree.
|
|
|
|
.. _generating_dnssec_keys:
|
|
|
|
Generating Keys
|
|
~~~~~~~~~~~~~~~
|
|
|
|
The ``dnssec-keygen`` program is used to generate keys.
|
|
|
|
A secure zone must contain one or more zone keys. The zone keys
|
|
sign all other records in the zone, as well as the zone keys of any
|
|
secure delegated zones. Zone keys must have the same name as the zone, have a
|
|
name type of ``ZONE``, and be usable for authentication. It is
|
|
recommended that zone keys use a cryptographic algorithm designated as
|
|
"mandatory to implement" by the IETF. Currently there are two algorithms,
|
|
RSASHA256 and ECDSAP256SHA256; ECDSAP256SHA256 is recommended for
|
|
current and future deployments.
|
|
|
|
The following command generates a ECDSAP256SHA256 key for the
|
|
``child.example`` zone:
|
|
|
|
``dnssec-keygen -a ECDSAP256SHA256 -n ZONE child.example.``
|
|
|
|
Two output files are produced: ``Kchild.example.+013+12345.key`` and
|
|
``Kchild.example.+013+12345.private`` (where 12345 is an example of a
|
|
key tag). The key filenames contain the key name (``child.example.``),
|
|
the algorithm (5 is RSASHA1, 8 is RSASHA256, 13 is ECDSAP256SHA256, 15 is
|
|
ED25519, etc.), and the key tag (12345 in this case). The private key (in
|
|
the ``.private`` file) is used to generate signatures, and the public
|
|
key (in the ``.key`` file) is used for signature verification.
|
|
|
|
To generate another key with the same properties but with a different
|
|
key tag, repeat the above command.
|
|
|
|
The ``dnssec-keyfromlabel`` program is used to get a key pair from a
|
|
crypto hardware device and build the key files. Its usage is similar to
|
|
``dnssec-keygen``.
|
|
|
|
The public keys should be inserted into the zone file by including the
|
|
``.key`` files using ``$INCLUDE`` statements.
|
|
|
|
.. _dnssec_zone_signing:
|
|
|
|
Signing the Zone
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
The ``dnssec-signzone`` program is used to sign a zone.
|
|
|
|
Any ``keyset`` files corresponding to secure sub-zones should be
|
|
present. The zone signer generates ``NSEC``, ``NSEC3``, and ``RRSIG``
|
|
records for the zone, as well as ``DS`` for the child zones if ``-g``
|
|
is specified. If ``-g`` is not specified, then DS RRsets for the
|
|
secure child zones need to be added manually.
|
|
|
|
By default, all zone keys which have an available private key are used
|
|
to generate signatures. The following command signs the zone, assuming
|
|
it is in a file called ``zone.child.example``:
|
|
|
|
``dnssec-signzone -o child.example zone.child.example``
|
|
|
|
One output file is produced: ``zone.child.example.signed``. This file
|
|
should be referenced by ``named.conf`` as the input file for the zone.
|
|
|
|
``dnssec-signzone`` also produces keyset and dsset files. These are used
|
|
to provide the parent zone administrators with the ``DNSKEYs`` (or their
|
|
corresponding ``DS`` records) that are the secure entry point to the zone.
|
|
|
|
.. _dnssec_config:
|
|
|
|
Configuring Servers for DNSSEC
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
To enable ``named`` to validate answers received from other servers, the
|
|
``dnssec-validation`` option must be set to either ``yes`` or ``auto``.
|
|
|
|
When ``dnssec-validation`` is set to ``auto``, a trust anchor for the
|
|
DNS root zone is automatically used. This trust anchor is provided
|
|
as part of BIND and is kept up to date using :rfc:`5011` key management.
|
|
|
|
When ``dnssec-validation`` is set to ``yes``, DNSSEC validation
|
|
only occurs if at least one trust anchor has been explicitly configured
|
|
in ``named.conf``, using a ``trust-anchors`` statement (or the
|
|
``managed-keys`` and ``trusted-keys`` statements, both deprecated).
|
|
|
|
When ``dnssec-validation`` is set to ``no``, DNSSEC validation does not
|
|
occur.
|
|
|
|
The default is ``auto`` unless BIND is built with
|
|
``configure --disable-auto-validation``, in which case the default is
|
|
``yes``.
|
|
|
|
The keys specified in ``trust-anchors`` are copies of DNSKEY RRs for zones that are
|
|
used to form the first link in the cryptographic chain of trust. Keys configured
|
|
with the keyword ``static-key`` or ``static-ds`` are loaded directly into the
|
|
table of trust anchors, and can only be changed by altering the
|
|
configuration. Keys configured with ``initial-key`` or ``initial-ds`` are used
|
|
to initialize :rfc:`5011` trust anchor maintenance, and are kept up-to-date
|
|
automatically after the first time ``named`` runs.
|
|
|
|
``trust-anchors`` is described in more detail later in this document.
|
|
|
|
BIND 9 does not verify signatures on load, so zone keys
|
|
for authoritative zones do not need to be specified in the configuration
|
|
file.
|
|
|
|
After DNSSEC is established, a typical DNSSEC configuration looks
|
|
something like the following. It has one or more public keys for the
|
|
root, which allows answers from outside the organization to be validated.
|
|
It also has several keys for parts of the namespace that the
|
|
organization controls. These are here to ensure that ``named`` is immune
|
|
to compromised security in the DNSSEC components of parent zones.
|
|
|
|
::
|
|
|
|
trust-anchors {
|
|
/* Root Key */
|
|
"." initial-key 257 3 3 "BNY4wrWM1nCfJ+CXd0rVXyYmobt7sEEfK3clRbGaTwS
|
|
JxrGkxJWoZu6I7PzJu/E9gx4UC1zGAHlXKdE4zYIpRh
|
|
aBKnvcC2U9mZhkdUpd1Vso/HAdjNe8LmMlnzY3zy2Xy
|
|
4klWOADTPzSv9eamj8V18PHGjBLaVtYvk/ln5ZApjYg
|
|
hf+6fElrmLkdaz MQ2OCnACR817DF4BBa7UR/beDHyp
|
|
5iWTXWSi6XmoJLbG9Scqc7l70KDqlvXR3M/lUUVRbke
|
|
g1IPJSidmK3ZyCllh4XSKbje/45SKucHgnwU5jefMtq
|
|
66gKodQj+MiA21AfUVe7u99WzTLzY3qlxDhxYQQ20FQ
|
|
97S+LKUTpQcq27R7AT3/V5hRQxScINqwcz4jYqZD2fQ
|
|
dgxbcDTClU0CRBdiieyLMNzXG3";
|
|
/* Key for our organization's forward zone */
|
|
example.com. static-ds 54135 5 2 "8EF922C97F1D07B23134440F19682E7519ADDAE180E20B1B1EC52E7F58B2831D"
|
|
|
|
/* Key for our reverse zone. */
|
|
2.0.192.IN-ADDRPA.NET. static-key 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwc
|
|
xOdNax071L18QqZnQQQAVVr+i
|
|
LhGTnNGp3HoWQLUIzKrJVZ3zg
|
|
gy3WwNT6kZo6c0tszYqbtvchm
|
|
gQC8CzKojM/W16i6MG/eafGU3
|
|
siaOdS0yOI6BgPsw+YZdzlYMa
|
|
IJGf4M4dyoKIhzdZyQ2bYQrjy
|
|
Q4LB0lC7aOnsMyYKHHYeRvPxj
|
|
IQXmdqgOJGq+vsevG06zW+1xg
|
|
YJh9rCIfnm1GX/KMgxLPG2vXT
|
|
D/RnLX+D3T3UL7HJYHJhAZD5L
|
|
59VvjSPsZJHeDCUyWYrvPZesZ
|
|
DIRvhDD52SKvbheeTJUm6Ehkz
|
|
ytNN2SN96QRk8j/iI8ib";
|
|
};
|
|
|
|
options {
|
|
...
|
|
dnssec-validation yes;
|
|
};
|
|
|
|
..
|
|
|
|
.. note::
|
|
|
|
None of the keys listed in this example are valid. In particular, the
|
|
root key is not valid.
|
|
|
|
When DNSSEC validation is enabled and properly configured, the resolver
|
|
rejects any answers from signed, secure zones which fail to
|
|
validate, and returns SERVFAIL to the client.
|
|
|
|
Responses may fail to validate for any of several reasons, including
|
|
missing, expired, or invalid signatures, a key which does not match the
|
|
DS RRset in the parent zone, or an insecure response from a zone which,
|
|
according to its parent, should have been secure.
|
|
|
|
.. note::
|
|
|
|
When the validator receives a response from an unsigned zone that has
|
|
a signed parent, it must confirm with the parent that the zone was
|
|
intentionally left unsigned. It does this by verifying, via signed
|
|
and validated NSEC/NSEC3 records, that the parent zone contains no DS
|
|
records for the child.
|
|
|
|
If the validator *can* prove that the zone is insecure, then the
|
|
response is accepted. However, if it cannot, the validator must assume an
|
|
insecure response to be a forgery; it rejects the response and logs
|
|
an error.
|
|
|
|
The logged error reads "insecurity proof failed" and "got insecure
|
|
response; parent indicates it should be secure."
|
|
|
|
|
|
.. include:: dnssec.rst
|
|
.. include:: managed-keys.rst
|
|
.. include:: pkcs11.rst
|
|
.. include:: dlz.rst
|
|
.. include:: dyndb.rst
|
|
.. include:: catz.rst
|
|
|
|
.. _ipv6:
|
|
|
|
IPv6 Support in BIND 9
|
|
----------------------
|
|
|
|
BIND 9 fully supports all currently defined forms of IPv6 name-to-address
|
|
and address-to-name lookups. It also uses IPv6 addresses to
|
|
make queries when running on an IPv6-capable system.
|
|
|
|
For forward lookups, BIND 9 supports only AAAA records. :rfc:`3363`
|
|
deprecated the use of A6 records, and client-side support for A6 records
|
|
was accordingly removed from BIND 9. However, authoritative BIND 9 name
|
|
servers still load zone files containing A6 records correctly, answer
|
|
queries for A6 records, and accept zone transfer for a zone containing
|
|
A6 records.
|
|
|
|
For IPv6 reverse lookups, BIND 9 supports the traditional "nibble"
|
|
format used in the ``ip6.arpa`` domain, as well as the older, deprecated
|
|
``ip6.int`` domain. Older versions of BIND 9 supported the "binary label"
|
|
(also known as "bitstring") format, but support of binary labels has
|
|
been completely removed per :rfc:`3363`. Many applications in BIND 9 do not
|
|
understand the binary label format at all anymore, and return an
|
|
error if one is given. In particular, an authoritative BIND 9 name server will
|
|
not load a zone file containing binary labels.
|
|
|
|
For an overview of the format and structure of IPv6 addresses, see
|
|
:ref:`ipv6addresses`.
|
|
|
|
Address Lookups Using AAAA Records
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The IPv6 AAAA record is a parallel to the IPv4 A record, and, unlike the
|
|
deprecated A6 record, specifies the entire IPv6 address in a single
|
|
record. For example:
|
|
|
|
::
|
|
|
|
$ORIGIN example.com.
|
|
host 3600 IN AAAA 2001:db8::1
|
|
|
|
Use of IPv4-in-IPv6 mapped addresses is not recommended. If a host has
|
|
an IPv4 address, use an A record, not a AAAA, with
|
|
``::ffff:192.168.42.1`` as the address.
|
|
|
|
Address-to-Name Lookups Using Nibble Format
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
When looking up an address in nibble format, the address components are
|
|
simply reversed, just as in IPv4, and ``ip6.arpa.`` is appended to the
|
|
resulting name. For example, the following would provide reverse name
|
|
lookup for a host with address ``2001:db8::1``:
|
|
|
|
::
|
|
|
|
$ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
|
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 14400 IN PTR (
|
|
host.example.com. )
|