.. _network-configuration:
-Network
-=======
+Server addresses
+-----------------
Modern Linux distributions use so-called *Systemd socket activation*, which
effectively means that IP addresses and ports to listen on are configured
Following commands are useful in special situations and can be usef with and without systemd socket activation:
-.. envvar:: net.ipv6 = true|false
-
- :return: boolean (default: true)
-
- Enable/disable using IPv6 for contacting upstream nameservers.
-
-.. envvar:: net.ipv4 = true|false
-
- :return: boolean (default: true)
-
- Enable/disable using IPv4 for contacting upstream nameservers.
-
.. function:: net.list()
:return: Table of bound interfaces.
.. tip:: You can use ``net.<iface>`` as a shortcut for specific interface, e.g. ``net.eth0``
-.. function:: net.bufsize([udp_bufsize])
-
- Get/set maximum EDNS payload size advertised in DNS packets. Default is 4096 bytes and the default will be lowered to value around 1220 bytes in future, once `DNS Flag Day 2020 <https://dnsflagday.net/>`_ becomes effective.
-
- Minimal value allowed by standard :rfc:`6891` is 512 bytes, which is equal to DNS packet size without Extension Mechanisms for DNS. Value 1220 bytes is minimum size required in DNSSEC standard :rfc:`4035`.
-
- Example output:
-
- .. code-block:: lua
-
- > net.bufsize(4096)
- nil
- > net.bufsize()
- 4096
-
.. function:: net.tcp_pipeline([len])
Get/set per-client TCP pipeline limit, i.e. the number of outstanding queries that a single client connection can make in parallel. Default is 100.
.. warning:: Please note that too large limit may have negative impact on performance and can lead to increased number of SERVFAIL answers.
-.. function:: net.outgoing_v4([string address])
-
- Get/set the IPv4 address used to perform queries. There is also ``net.outgoing_v6`` for IPv6.
- The default is ``nil``, which lets the OS choose any address.
+Client
+------
+Following settings affect client part of the resolver, i.e. communication between the resolver itself and other DNS servers.
+.. envvar:: net.ipv4 = true|false
-.. _tls-server-config:
-
-TLS server
-==========
-DNS-over-TLS server (:rfc:`7858`) is enabled by default on loopback interface port 853.
-Information how to configure listening on specific IP addresses is in previous sections
-:ref:`network-configuration`.
+ :return: boolean (default: true)
-By default a self-signed certificate is generated. For serious deployments
-it is strongly recommended to configure your own TLS certificates signed
-by a trusted CA. This is done using function :c:func:`net.tls()`.
+ Enable/disable using IPv4 for contacting upstream nameservers.
-.. function:: net.tls([cert_path], [key_path])
+.. function:: net.outgoing_v4([string address])
- Get/set path to a server TLS certificate and private key for DNS/TLS.
+ Get/set the IPv4 address used to perform queries.
+ The default is ``nil``, which lets the OS choose any address.
- Example output:
+.. envvar:: net.ipv6 = true|false
- .. code-block:: lua
+ :return: boolean (default: true)
- > net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
- > net.tls() -- print configured paths
- ("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
+ Enable/disable using IPv6 for contacting upstream nameservers.
-.. function:: net.tls_padding([true | false])
+.. function:: net.outgoing_v6([string address])
- Get/set EDNS(0) padding of answers to queries that arrive over TLS
- transport. If set to `true` (the default), it will use a sensible
- default padding scheme, as implemented by libknot if available at
- compile time. If set to a numeric value >= 2 it will pad the
- answers to nearest *padding* boundary, e.g. if set to `64`, the
- answer will have size of a multiple of 64 (64, 128, 192, ...). If
- set to `false` (or a number < 2), it will disable padding entirely.
+ Get/set the IPv6 address used to perform queries.
+ The default is ``nil``, which lets the OS choose any address.
-.. function:: net.tls_sticket_secret([string with pre-shared secret])
+DNS protocol
+------------
+Following settings change low-level details of DNS protocol implementation.
+Default values should not be changed except for very special cases.
- Set secret for TLS session resumption via tickets, by :rfc:`5077`.
+.. function:: net.bufsize([udp_bufsize])
- The server-side key is rotated roughly once per hour.
- By default or if called without secret, the key is random.
- That is good for long-term forward secrecy, but multiple kresd instances
- won't be able to resume each other's sessions.
+ Get/set maximum EDNS payload size advertised in DNS packets. Default is 4096 bytes and the default will be lowered to value around 1220 bytes in future, once `DNS Flag Day 2020 <https://dnsflagday.net/>`_ becomes effective.
- If you provide the same secret to multiple instances, they will be able to resume
- each other's sessions *without* any further communication between them.
- This synchronization works only among instances having the same endianess
- and time_t structure and size (`sizeof(time_t)`).
+ Minimal value allowed by standard :rfc:`6891` is 512 bytes, which is equal to DNS packet size without Extension Mechanisms for DNS. Value 1220 bytes is minimum size required in DNSSEC standard :rfc:`4035`.
- **For good security** the secret must have enough entropy to be hard to guess,
- and it should still be occasionally rotated manually and securely forgotten,
- to reduce the scope of privacy leak in case the
- `secret leaks eventually <https://en.wikipedia.org/wiki/Forward_secrecy>`_.
+ Example output:
- .. warning:: **Setting the secret is probably too risky with TLS <= 1.2**.
- GnuTLS stable release supports TLS 1.3 since 3.6.3 (summer 2018).
- Therefore setting the secrets should be considered experimental for now
- and might not be available on your system.
+ .. code-block:: lua
-.. function:: net.tls_sticket_secret_file([string with path to a file containing pre-shared secret])
+ > net.bufsize(4096)
+ nil
+ > net.bufsize()
+ 4096
- The same as :func:`net.tls_sticket_secret`,
- except the secret is read from a (binary) file.
+.. include:: ../modules/workarounds/README.rst
--- /dev/null
+.. _tls-server-config:
+
+DNS-over-TLS server (DoT)
+-------------------------
+DNS-over-TLS server (:rfc:`7858`) is enabled by default on loopback interface port 853.
+Information how to configure listening on specific IP addresses is in previous sections
+:ref:`network-configuration`.
+
+By default a self-signed certificate is generated. For serious deployments
+it is strongly recommended to configure your own TLS certificates signed
+by a trusted CA. This is done using function :c:func:`net.tls()`.
+
+.. function:: net.tls([cert_path], [key_path])
+
+ Get/set path to a server TLS certificate and private key for DNS/TLS.
+
+ Example output:
+
+ .. code-block:: lua
+
+ > net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
+ > net.tls() -- print configured paths
+ ("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
+
+.. function:: net.tls_padding([true | false])
+
+ Get/set EDNS(0) padding of answers to queries that arrive over TLS
+ transport. If set to `true` (the default), it will use a sensible
+ default padding scheme, as implemented by libknot if available at
+ compile time. If set to a numeric value >= 2 it will pad the
+ answers to nearest *padding* boundary, e.g. if set to `64`, the
+ answer will have size of a multiple of 64 (64, 128, 192, ...). If
+ set to `false` (or a number < 2), it will disable padding entirely.
+
+.. function:: net.tls_sticket_secret([string with pre-shared secret])
+
+ Set secret for TLS session resumption via tickets, by :rfc:`5077`.
+
+ The server-side key is rotated roughly once per hour.
+ By default or if called without secret, the key is random.
+ That is good for long-term forward secrecy, but multiple kresd instances
+ won't be able to resume each other's sessions.
+
+ If you provide the same secret to multiple instances, they will be able to resume
+ each other's sessions *without* any further communication between them.
+ This synchronization works only among instances having the same endianess
+ and time_t structure and size (`sizeof(time_t)`).
+
+ **For good security** the secret must have enough entropy to be hard to guess,
+ and it should still be occasionally rotated manually and securely forgotten,
+ to reduce the scope of privacy leak in case the
+ `secret leaks eventually <https://en.wikipedia.org/wiki/Forward_secrecy>`_.
+
+ .. warning:: **Setting the secret is probably too risky with TLS <= 1.2**.
+ GnuTLS stable release supports TLS 1.3 since 3.6.3 (summer 2018).
+ Therefore setting the secrets should be considered experimental for now
+ and might not be available on your system.
+
+.. function:: net.tls_sticket_secret_file([string with path to a file containing pre-shared secret])
+
+ The same as :func:`net.tls_sticket_secret`,
+ except the secret is read from a (binary) file.
Now you know what configuration file to modify, how to read examples and what modules are so you are ready for a real configuration work!
.. include:: ../daemon/README.rst
-.. include:: ../daemon/bindings/net.rst
.. include:: ../daemon/lua/trust_anchors.rst
+Networking and protocols
+========================
+.. include:: ../daemon/bindings/net.rst
+.. include:: ../daemon/bindings/net_tlssrv.rst
+.. include:: ../modules/http/README.rst
+.. include:: ../modules/http/README.doh.rst
Logging, monitoring, diagnostics
================================
:local:
.. include:: ../modules/nsid/README.rst
+
+.. include:: ../modules/stats/README.rst
+.. .. subchapter of stats module
.. include:: ../modules/graphite/README.rst
+.. .. subchapter of stats module
+.. include:: ../modules/http/prometheus.rst
+
.. include:: ../modules/dnstap/README.rst
.. include:: ../modules/watchdog/README.rst
.. include:: ../modules/bogus_log/README.rst
+.. include:: ../modules/http/trace.rst
.. include:: ../modules/ta_sentinel/README.rst
.. include:: ../modules/ta_signal_query/README.rst
.. include:: ../modules/detect_time_skew/README.rst
:local:
.. include:: ../modules/hints/README.rst
-.. include:: ../modules/stats/README.rst
.. include:: ../modules/policy/README.rst
.. include:: ../modules/view/README.rst
.. include:: ../modules/daf/README.rst
.. include:: ../modules/rfc7706.rst
.. include:: ../modules/prefill/README.rst
.. include:: ../modules/serve_stale/README.rst
-.. include:: ../modules/workarounds/README.rst
.. include:: ../modules/edns_keepalive/README.rst
-
-TODO: Other
-===========
-.. include:: ../modules/http/README.rst
-.. include:: ../modules/http/README.doh.rst
-
Experimental features
=====================
.. include:: ../modules/experimental_dot_auth/README.rst
.. _mod-graphite:
Graphite/InfluxDB/Metronome
----------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``graphite`` sends statistics over the Graphite_ protocol to either Graphite_, Metronome_, InfluxDB_ or any compatible storage. This allows powerful visualization over metrics collected by Knot Resolver.
.. tip:: The Graphite server is challenging to get up and running, InfluxDB_ combined with Grafana_ are much easier, and provide richer set of options and available front-ends. Metronome_ by PowerDNS alternatively provides a mini-graphite server for much simpler setups.
-Example configuration
-^^^^^^^^^^^^^^^^^^^^^
+Example configuration:
Only the ``host`` parameter is mandatory.
}
}
-Dependencies
-^^^^^^^^^^^^
+Dependencies:
* `lua cqueues <https://25thandclement.com/~william/projects/cqueues.html>`_ package.
.. _mod-http-tls:
-Configuring TLS
-^^^^^^^^^^^^^^^
+HTTPS (TLS for HTTP)
+^^^^^^^^^^^^^^^^^^^^
By default, the web interface starts HTTPS/2 on specified port using an ephemeral
TLS certificate that is valid for 90 days and is automatically renewed. It is of
"``/trace/:name/:type``", "Tracking", ":ref:`Trace resolution <mod-http-trace>` of a DNS query and return the verbose logs."
"``/doh``", "DNS-over-HTTP", ":rfc:`8484` endpoint, see :ref:`mod-http-doh`."
-Prometheus metrics endpoint
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The module exposes ``/metrics`` endpoint that serves internal metrics in Prometheus_ text format.
-You can use it out of the box:
-
-.. code-block:: bash
-
- $ curl -k https://localhost:8453/metrics | tail
- # TYPE latency histogram
- latency_bucket{le=10} 2.000000
- latency_bucket{le=50} 2.000000
- latency_bucket{le=100} 2.000000
- latency_bucket{le=250} 2.000000
- latency_bucket{le=500} 2.000000
- latency_bucket{le=1000} 2.000000
- latency_bucket{le=1500} 2.000000
- latency_bucket{le=+Inf} 2.000000
- latency_count 2.000000
- latency_sum 11.000000
-
-You can namespace the metrics in configuration, using `http.prometheus.namespace` attribute:
-
-.. code-block:: lua
-
- modules.load('http')
- -- Set Prometheus namespace
- http.prometheus.namespace = 'resolver_'
-
-You can also add custom metrics or rewrite existing metrics before they are returned to Prometheus client.
-
-.. code-block:: lua
-
- modules.load('http')
- -- Add an arbitrary metric to Prometheus
- http.prometheus.finalize = function (metrics)
- table.insert(metrics, 'build_info{version="1.2.3"} 1')
- end
-
-.. _mod-http-trace:
-
-Tracing requests
-^^^^^^^^^^^^^^^^
-
-With the ``/trace`` endpoint you can trace various aspects of the request execution.
-The basic mode allows you to resolve a query and trace verbose logs (and messages received):
-
-.. code-block:: bash
-
- $ curl https://localhost:8453/trace/e.root-servers.net
- [ 8138] [iter] 'e.root-servers.net.' type 'A' created outbound query, parent id 0
- [ 8138] [ rc ] => rank: 020, lowest 020, e.root-servers.net. A
- [ 8138] [ rc ] => satisfied from cache
- [ 8138] [iter] <= answer received:
- ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 8138
- ;; Flags: qr aa QUERY: 1; ANSWER: 0; AUTHORITY: 0; ADDITIONAL: 0
-
- ;; QUESTION SECTION
- e.root-servers.net. A
-
- ;; ANSWER SECTION
- e.root-servers.net. 3556353 A 192.203.230.10
-
- [ 8138] [iter] <= rcode: NOERROR
- [ 8138] [resl] finished: 4, queries: 1, mempool: 81952 B
-
-
.. _mod-http-custom-endpoint:
How to expose custom services over HTTP
$ luarocks install http
-* `mmdblua <https://github.com/daurnimator/mmdblua>`_ available in LuaRocks
+* (*optional*) `mmdblua <https://github.com/daurnimator/mmdblua>`_ available in LuaRocks
.. code-block:: bash
--- /dev/null
+.. _mod-http-prometheus:
+
+Prometheus metrics endpoint
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The `HTTP module <mod-http>`_ exposes ``/metrics`` endpoint that serves metrics
+from :ref:`mod-stats` in Prometheus_ text format.
+You can use it as soon as HTTP module is configured:
+
+.. code-block:: bash
+
+ $ curl -k https://localhost:8453/metrics | tail
+ # TYPE latency histogram
+ latency_bucket{le=10} 2.000000
+ latency_bucket{le=50} 2.000000
+ latency_bucket{le=100} 2.000000
+ latency_bucket{le=250} 2.000000
+ latency_bucket{le=500} 2.000000
+ latency_bucket{le=1000} 2.000000
+ latency_bucket{le=1500} 2.000000
+ latency_bucket{le=+Inf} 2.000000
+ latency_count 2.000000
+ latency_sum 11.000000
+
+You can namespace the metrics in configuration, using `http.prometheus.namespace` attribute:
+
+.. code-block:: lua
+
+ modules.load('http')
+ -- Set Prometheus namespace
+ http.prometheus.namespace = 'resolver_'
+
+You can also add custom metrics or rewrite existing metrics before they are returned to Prometheus client.
+
+.. code-block:: lua
+
+ modules.load('http')
+ -- Add an arbitrary metric to Prometheus
+ http.prometheus.finalize = function (metrics)
+ table.insert(metrics, 'build_info{version="1.2.3"} 1')
+ end
+
--- /dev/null
+.. _mod-http-trace:
+
+Tracing requests
+----------------
+
+The `HTTP module <mod-http>`_ provides ``/trace`` endpoint which allows to trace various
+aspects of the request execution. The basic mode allows you to resolve a query
+and trace verbose logs (and messages received):
+
+.. code-block:: bash
+
+ $ curl https://localhost:8453/trace/e.root-servers.net
+ [ 8138] [iter] 'e.root-servers.net.' type 'A' created outbound query, parent id 0
+ [ 8138] [ rc ] => rank: 020, lowest 020, e.root-servers.net. A
+ [ 8138] [ rc ] => satisfied from cache
+ [ 8138] [iter] <= answer received:
+ ;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 8138
+ ;; Flags: qr aa QUERY: 1; ANSWER: 0; AUTHORITY: 0; ADDITIONAL: 0
+
+ ;; QUESTION SECTION
+ e.root-servers.net. A
+
+ ;; ANSWER SECTION
+ e.root-servers.net. 3556353 A 192.203.230.10
+
+ [ 8138] [iter] <= rcode: NOERROR
+ [ 8138] [resl] finished: 4, queries: 1, mempool: 81952 B
+
+See chapter about `HTTP module <mod-http>`_ for further instructions how to load HTTP module.
Statistics collector
--------------------
-This modules gathers various counters from the query resolution and server internals,
-and offers them as a key-value storage. Any module may update the metrics or simply hook
-in new ones.
-
-.. code-block:: none
-
- modules.load('stats')
-
- -- Enumerate metrics
- > stats.list()
- [answer.cached] => 486178
- [iterator.tcp] => 490
- [answer.noerror] => 507367
- [answer.total] => 618631
- [iterator.udp] => 102408
- [query.concurrent] => 149
-
- -- Query metrics by prefix
- > stats.list('iter')
- [iterator.udp] => 105104
- [iterator.tcp] => 490
-
- -- Set custom metrics from modules
- > stats['filter.match'] = 5
- > stats['filter.match']
- 5
-
- -- Fetch most common queries
- > stats.frequent()
- [1] => {
- [type] => 2
- [count] => 4
- [name] => cz.
- }
-
- -- Fetch most common queries (sorted by frequency)
- > table.sort(stats.frequent(), function (a, b) return a.count > b.count end)
-
- -- Show recently contacted authoritative servers
- > stats.upstreams()
- [2a01:618:404::1] => {
- [1] => 26 -- RTT
- }
- [128.241.220.33] => {
- [1] => 31 - RTT
- }
-
-Properties
-^^^^^^^^^^
-
-.. function:: stats.get(key)
-
- :param string key: i.e. ``"answer.total"``
- :return: ``number``
-
-Return nominal value of given metric.
-
-.. function:: stats.set(key, val)
-
- :param string key: i.e. ``"answer.total"``
- :param number val: i.e. ``5``
-
-Set nominal value of given metric.
-
-.. function:: stats.list([prefix])
-
- :param string prefix: optional metric prefix, i.e. ``"answer"`` shows only metrics beginning with "answer"
-
-Outputs collected metrics as a JSON dictionary.
-
-.. function:: stats.upstreams()
-
-Outputs a list of recent upstreams and their RTT. It is sorted by time and stored in a ring buffer of
-a fixed size. This means it's not aggregated and readable by multiple consumers, but also that
-you may lose entries if you don't read quickly enough. The default ring size is 512 entries, and may be overriden on compile time by ``-DUPSTREAMS_COUNT=X``.
-
-.. function:: stats.frequent()
-
-Outputs list of most frequent iterative queries as a JSON array. The queries are sampled probabilistically,
-and include subrequests. The list maximum size is 5000 entries, make diffs if you want to track it over time.
-
-.. function:: stats.clear_frequent()
-
-Clear the list of most frequent iterative queries.
+Module ``stats`` gathers various counters from the query resolution
+and server internals, and offers them as a key-value storage.
+These metrics can be either exported to :ref:`mod-graphite`,
+exposed as :ref:`mod-http-prometheus`, or processed using user-provided script
+as described in chapter :ref:`async-events`.
.. _mod-stats-list:
+-----------------------------------------------------------------+
| **Global request counters** |
+------------------+----------------------------------------------+
-| request.total | total number of DNS requests from clients |
+| request.total | total number of DNS requests |
| | (including internal client requests) |
+------------------+----------------------------------------------+
| request.internal | internal requests generated by Knot Resolver |
+-----------------+----------------------------------+
| query.dnssec | queries with DNSSEC DO=1 |
+-----------------+----------------------------------+
+
+Example:
+
+.. code-block:: none
+
+ modules.load('stats')
+
+ -- Enumerate metrics
+ > stats.list()
+ [answer.cached] => 486178
+ [iterator.tcp] => 490
+ [answer.noerror] => 507367
+ [answer.total] => 618631
+ [iterator.udp] => 102408
+ [query.concurrent] => 149
+
+ -- Query metrics by prefix
+ > stats.list('iter')
+ [iterator.udp] => 105104
+ [iterator.tcp] => 490
+
+ -- Fetch most common queries
+ > stats.frequent()
+ [1] => {
+ [type] => 2
+ [count] => 4
+ [name] => cz.
+ }
+
+ -- Fetch most common queries (sorted by frequency)
+ > table.sort(stats.frequent(), function (a, b) return a.count > b.count end)
+
+ -- Show recently contacted authoritative servers
+ > stats.upstreams()
+ [2a01:618:404::1] => {
+ [1] => 26 -- RTT
+ }
+ [128.241.220.33] => {
+ [1] => 31 - RTT
+ }
+
+ -- Set custom metrics from modules
+ > stats['filter.match'] = 5
+ > stats['filter.match']
+ 5
+
+Module reference
+^^^^^^^^^^^^^^^^
+
+.. function:: stats.get(key)
+
+ :param string key: i.e. ``"answer.total"``
+ :return: ``number``
+
+Return nominal value of given metric.
+
+.. function:: stats.set(key, val)
+
+ :param string key: i.e. ``"answer.total"``
+ :param number val: i.e. ``5``
+
+Set nominal value of given metric.
+
+.. function:: stats.list([prefix])
+
+ :param string prefix: optional metric prefix, i.e. ``"answer"`` shows only metrics beginning with "answer"
+
+Outputs collected metrics as a JSON dictionary.
+
+.. function:: stats.upstreams()
+
+Outputs a list of recent upstreams and their RTT. It is sorted by time and stored in a ring buffer of
+a fixed size. This means it's not aggregated and readable by multiple consumers, but also that
+you may lose entries if you don't read quickly enough. The default ring size is 512 entries, and may be overriden on compile time by ``-DUPSTREAMS_COUNT=X``.
+
+.. function:: stats.frequent()
+
+Outputs list of most frequent iterative queries as a JSON array. The queries are sampled probabilistically,
+and include subrequests. The list maximum size is 5000 entries, make diffs if you want to track it over time.
+
+.. function:: stats.clear_frequent()
+
+Clear the list of most frequent iterative queries.
+
+
.. _mod-workarounds:
-Workarounds
------------
+Module `workarounds` resolver behavior on specific broken sub-domains.
+Currently it mainly disables case randomization.
-A simple module that alters resolver behavior on specific broken sub-domains.
-Currently it mainly disables case randomization on them.
-
-Running
-^^^^^^^
.. code-block:: lua
- modules = { 'workarounds < iterate' }
+ modules.load('workarounds < iterate')