.. SPDX-License-Identifier: GPL-3.0-or-later

.. _config-local-data:

Local Data and RPZ
==================

Local overrides for DNS data may be defined in the :option:`local-data <local-data:>` configuration tree.
It provides various input formats described in following subsections.

.. code-block:: yaml

   # Some typical use cases:
   local-data:
     addresses:
       a1.example.com: 2001:db8::1
       a2.example.org: [ 192.0.2.2, 192.0.2.3, 2001:db8::4 ]
     addresses-files:
       - /etc/hosts
     records: |
       www.google.com.  CNAME  forcesafesearch.google.com.
     rpz:
       - file: /tmp/blocklist.rpz


.. option:: local-data:

   .. option:: ttl: <time ms|s|m|h|d>

      Optional, this allows to write the new TTL value for records generated by the local-data.

   .. option:: nodata: true|false

      :default: true

      Enabling NODATA synthesis, false if disabling.
      If set to true (the default), an empty answer will be synthesised for matching name but mismatching type (e.g. AAAA query when only A hint exists).

   Records
   -------

   The typical use case is to define some name-address pairs, which also generate corresponding
   `reverse PTR records <https://en.wikipedia.org/wiki/Reverse_DNS_lookup>`_.


   .. option:: addresses: <dict[hostname, address]>

      Optional, direct addition of hostname and IP address pairs.

   .. option:: addresses-files: <list of paths>

      Optional, direct addition of hostname and IP address pairs from files in ``/etc/hosts`` like format.

   .. code-block:: yaml

      local-data:
        addresses:
          a1.example.com: 2001:db8::1
          a2.example.com: 2001:db8::2
        addresses-files:
          - /etc/hosts
        # some options
        ttl: 5m
        nodata: false # don't force empty answer for missing record types on mentioned names

   .. option:: records: <zonefile format string>

      Optional, direct addition of records in DNS zonefile format.
      The zonefile syntax is more flexible, e.g. it can define any type of records.

   .. code-block:: yaml

      local-data:
        records: |
          www.google.com.  CNAME  forcesafesearch.google.com.
          example.com  TXT  "an example text record"
          34.example.com  AAAA  2001:db8::3
          34.example.com  AAAA  2001:db8::4

   Response Policy Zones (RPZ)
   ---------------------------

   `RPZ <https://dnsrpz.info>`_ files are another way of adding rules.

   .. option:: rpz: <list>

      .. option:: file: <path>

         Path to a RPZ zonefile.

      .. option:: tags: <list of tags>

         Optional, restrict when this RPZ applies.  See :ref:`config-policy-new-tags`.

   .. code-block:: yaml

      local-data:
        rpz:
          - file: /tmp/adult.rpz
            tags: [ adult ]
            # security blocklist applied for everyone
          - file: /tmp/security.rpz

   So far, RPZ support is limited to the most common features:

   * just files which are *not* automatically reloaded when changed
   * rules with ``rpz-*`` labels are ignored, e.g. ``.rpz-client-ip``
   * ``CNAME *.some.thing`` does not expand the wildcard

   Advanced rules
   --------------

   .. option:: rules: <list>

      This allows defining more complex sets of rules for records and subtrees.
      For example, it allows blocking whole subtrees.

      .. option:: name: <domain name or list>

         Optional, hostname(s)/subtree(s) to which the rule applies.

      .. option:: address: <address or list>

         Optional, IP address(es) to pair with hostname(s).

         .. code-block:: yaml

            local-data:
              rules:
                # hostname and IP address pair
                - name: a3.example.com
                  address: 2001:db8::3
                  tags: [example]
                  ttl: 10m

      .. option:: subtree: empty|nxdomain|redirect

         Optional, type of this subtree:

          - ``empty`` is an empty zone with just SOA and NS at the top
          - ``nxdomain`` replies ``NXDOMAIN`` everywhere, though in some cases that looks slightly weird
          - ``redirect`` answers with local-data records from the top of the zone, inside the whole virtual subtree

         .. code-block:: yaml

            local-data:
              rules:
                - name: [ evil.example.org, malware.example.net ]
                  subtree: empty
                  tags: [ malware ]
                - name: a5.example
                  subtree: redirect
                  address: 2001:db8::5

      .. option:: file: <path or list>

         Optional, direct addition of hostname and IP address pairs from files in ``/etc/hosts`` like format.

         .. code-block:: yaml

            local-data:
              rules:
                - file: custom.hosts
                  tags: [ malware ]
                  ttl: 20m
                  nodata: false

      .. option:: records: <zonefile format string>

         Optional, direct addition of records in DNS zonefile format.
         The zonefile syntax is more flexible, e.g. it can define any type of records.

         .. code-block:: yaml

            local-data:
              rules:
                - records: |
                    www.google.com.  CNAME  forcesafesearch.google.com.
                  tags: [ adult ]

      .. option:: tags: <list of tags>

         Optional, restrict when this rule applies.  See :ref:`config-policy-new-tags`.

      .. option:: ttl: <time s|m|h|d>

         Optional, TTL of answers from this rule.  Uses ``/local-data/ttl`` if unspecified.

      .. option:: nodata: true|false

         Optional, enabling NODATA synthesis, false if disabling. Uses ``/local-data/nodata`` if unspecified.
         If set to true, an empty answer will be synthesised for matching name but mismatching type (e.g. AAAA query when only A hint exists).

   .. future
      .. option:: addresses: <list of addresses>

         Optional, subtree addresses.

      One of, :option:`roots <roots: <list of hostnames>>`, :option:`roots-file <roots-file: <path>>` or :option:`roots-url <roots-url: <url>>` must be configured.

      .. option:: roots: <list of hostnames>

         Subtree roots.

      .. option:: roots-file: <path>

         Subtree roots from given file.

      .. option:: roots-url: <url>

         Subtree roots from given URL.

      .. option:: refresh: <time ms|s|m|h|d>

         Refresh time to update data from :option:`roots-file <roots-file: <path>>` or :option:`roots-url <roots-url: <url>>`.
