Installation
************
-- :ref:`build`
-- `All downloadable packages <https://secure.nic.cz/files/knot-resolver>`_
-
+We recommend using these official upstream repositories with the **latest version** of Knot Resolver.
-.. Warning::
+.. warning::
Packages available in distribution's repositories are often outdated,
especially in **Debian** and **Ubuntu** repositories.
-We recommend using these official upstream repositories with the **latest version** of Knot Resolver.
-
**Debian/Ubuntu**
.. code-block:: bash
- ~$ wget https://secure.nic.cz/files/knot-resolver/knot-resolver-release.deb
- ~$ dpkg -i knot-resolver-release.deb
- ~$ apt update && apt install -y knot-resolver
+ $ wget https://secure.nic.cz/files/knot-resolver/knot-resolver-release.deb
+ $ dpkg -i knot-resolver-release.deb
+ $ apt update
+ $ apt install -y knot-resolver
**CentOS**
.. code-block:: bash
- ~$ yum install -y https://secure.nic.cz/files/knot-resolver/knot-resolver-release.el.rpm
- ~$ yum install -y knot-resolver
+ $ yum install -y https://secure.nic.cz/files/knot-resolver/knot-resolver-release.el.rpm
+ $ yum install -y knot-resolver
**Fedora**
.. code-block:: bash
- ~$ dnf install -y https://secure.nic.cz/files/knot-resolver/knot-resolver-release.fedora.rpm
- ~$ dnf install -y knot-resolver
+ $ dnf install -y https://secure.nic.cz/files/knot-resolver/knot-resolver-release.fedora.rpm
+ $ dnf install -y knot-resolver
**OpenSUSE Leap / Tumbleweed**
**Arch Linux**
`Knot-resolver <https://aur.archlinux.org/packages/knot-resolver/>`_
-package is maintained in **AUR**. It can be installed by using AUR helper,
-for instance, ``yay``
+package for Arch Linux is maintained in AUR_.
-.. code-block:: bash
- ~$ yay -S knot-resolver
+*****************
+Run Knot Resolver
+*****************
+After installation, Knot Resolver's default configuration should work for loopback
+queries. This allows you to test that installation and service setup works before
+managing configuration.
-*************
-Configuration
-*************
-.. contents::
- :depth: 1
- :local:
-
-**Detailed configuration of daemon and modules.**
+Single instance
+===============
-- :ref:`Daemon configuration <daemon>`
-- :ref:`Modules configuration <modules>`
+If you're using our packages, the simplest way to run **single instance** of
+Knot Resolver is to use provided Knot Resolver's ``systemd`` integration.
-.. note::
+.. note:: The instance of Knot Resolver is a single process incapable of multithreading.
- The configuration syntax is **Lua** language.
+For help run ``man kresd.systemd``
-**Startup configuration**
+.. code-block:: bash
-To set startup configuration, paste required configuration to ``/etc/knot-resolver/kresd.conf``
-configuration file or run Knot Resolver with ``-c`` parameter to set path to configuration file.
+ $ systemctl start kresd@1.service
-**Interactive / Dynamic configuration**
+See logs and status of running instance with ``systemctl status kresd@1.service`` command.
-Every Knot Resolver instance has its own *unix domain socket*.
-For instance, you start Knot Resolver using systemd
+.. warning::
-.. code-block:: bash
+ ``kresd@*.service`` is not enabled by default, thus Knot Resolver won't start automatically after reboot.
+ To start and enable service in one command use ``systemctl enable --now kresd@1.service``
- ~$ systemctl start kresd@1.service
+Multiple instances
+==================
-Then the related unix domain socket will be available on ``/run/knot-resolver/control@1``
+Knot Resolver can run in multiple independent processes, all sharing the same interface socket and cache.
-Connection to the socket can be made by ``socat`` or ``netcat`` through command line
+Because single running instance of Knot Resolver is incapable of multithreading, to use up of all resources,
+for instance, of 4 CPUs system, the best way is to run four instances at a time.
.. code-block:: bash
- ~$ socat - /run/knot-resolver/control@1
- ~$ nc -U /run/knot-resolver/control@1
-
-When successfully connected to a socket, the command line should change to something like ``>``.
-Then you can interact with Knot Resolver to list configuration or set a new one.
+ $ systemctl start kresd@1.service
+ $ systemctl start kresd@2.service
+ $ systemctl start kresd@3.service
+ $ systemctl start kresd@4.service
-There are some useful commands.
+or simpler way
.. code-block:: bash
- > help() # shows help
- > net.interfaces() # lists available interfaces
- > net.list() # lists running network services
+ ~$ systemctl start kresd@{1..4}.service
-==================
-Bind to interfaces
-==================
-Knot Resolver can listen on multiple interfaces that are defined in configuration.
+*************
+Configuration
+*************
-.. code-block:: lua
+.. contents::
+ :depth: 1
+ :local:
- net = {'192.168.1.1','fc00::1:1'}
+.. note::
+
+ The configuration syntax is **Lua** language.
+ Please pay close attention to brackets especially in more complex configurations like :func:`policy.add` and :func:`view:addr`.
+ If you are not familiar with Lua you can read `Learn Lua in 15 minutes`_ for a syntax overview.
-Default port is ``53``. Port can be specified by separating it by ``@`` from ip address. For example ``'127.0.0.1@5353'``.
+Detailed configuration of daemon and implemented modules:
+- :ref:`Daemon configuration <daemon>`
+- :ref:`Modules configuration <modules-implemented>`
-Available interfaces can be listed
+Easiest way to configure Knot Resolver is to paste your configuration to
+``/etc/knot-resolver/kresd.conf`` configuration file loaded on resolver's startup.
+You can easily save configuration files and switch between them.
+All configuration files of following examples and more are stored in `/etc/config`_ directory.
-.. code-block:: bash
+Bind to interfaces
+==================
- > net.interfaces()
- [eth1] => {
- [addr] => {
- [1] => 192.168.1.1
- [2] => fc00::1:1
- [4] => fe80::1:1
- }
- }
- [lo] => {
- [addr] => {
- [1] => 127.0.0.1
- [2] => ::1
- }
- }
-
-``net.eth1.addr[1]`` refers to ``192.168.1.1`` and ``net.eth1.addr[2]`` refers to ``fc00::1:1``
+Knot Resolver can listen on multiple interfaces that are defined in
+configuration by :func:`net.listen()` function.
+It also makes possible to configure ports for ``tls``, ``doh``, ``webmgmt``.
.. code-block:: lua
- net = {net.eth1.addr[1],net.eth1.addr[2]}
+ -- examples
+ net.listen('192.168.1.1')
+ net.listen('fc00::1:1')
+ net.listen(net.eth0, 853, { kind = 'tls' })
.. warning::
overlap, and clients would probably refuse such a response.
-=================
Internal Resolver
=================
-How to configure Knot Resolver to resolve internal-only domain.
+How to configure Knot Resolver to resolve internal-only domains.
Forward internal-only domain
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For instance, ``company.example`` is the internal-only domain which is not available from the public Internet.
-To resolve internal-only domain, e.g. ``company.exmaple`` a query policy to forward query has to be added.
+To resolve internal-only domain, e.g. ``company.example`` a query policy to forward query has to be added.
The followind example will add query policy that will trigger ``FORWARD`` action based on suffix of a domain.
This configuration will forward everything below ``company.example`` domain to ``192.168.1.2`` IP address, port ``443``.
.. code-block:: lua
- -- policy module is required for query policy configuration
- modules = { 'policy' }
+ -- define internal only domains
+ internalDomains = policy.todnames({'company.example', 'internal.example'})
- -- forward all queries below 'company.example' to '192.168.1.2@443'
- policy.add(policy.suffix(policy.FORWARD('192.168.1.2@443'), {todname('company.example')}))
-
-
-Example ``kresd.conf``
-^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: lua
-
- -- bind to interfaces
- net = {'192.168.1.1','fc00::1:1'}
-
- -- load policy module
- modules = { 'policy' }
-
- -- forward all queries below suffix 'company.example' to '192.168.1.2@443'
- policy.add(policy.suffix(policy.FORWARD('192.168.1.2@443'), {todname('company.example')}))
+ -- forward all queries below 'internalDomains' to '192.168.1.2@443'
+ policy.add(policy.suffix(policy.FORWARD({'192.168.1.2@443'}), internalDomains))
.. _personalresolver:
-====================================
+
Personal privacy-preserving Resolver
====================================
-TLS server configuration
-^^^^^^^^^^^^^^^^^^^^^^^^
-.. Warning::
-
- 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 can be done by using function ``net.tls()``.
-
-.. code-block:: lua
-
- net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
-
-Calling this function without parameters prints configured TLS paths.
-
Forwarding over TLS protocol (DNS-over-TLS)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-More examples on :ref:`tls-examples`.
+Forwarding over TLS protocol protects queries send out by resolver.
+It is done by :func:`policy.TLS_FORWARD()` function which provides methods for authentication.
+There is a list of `DNS Privacy Test Servers`_ supporting DNS-over-TLS to test your configuration.
CA+hostname authentication
``````````````````````````
-- forward all queries over TLS to the specified server
policy.add(policy.all(
policy.TLS_FORWARD({
- {'2001:DB8::d0c', hostname='res.example.com', ca_file='/etc/knot-resolver/tlsca.crt'}
+ {'2001:DB8::d0c', hostname='res.example.com'}
})
))
+The system-wide CA storage is used, which should cover most of use cases.
+More on :func:`policy.TLS_FORWARD()`
+
+
Key-pinned authentication
``````````````````````````
Instead of CAs, you can specify hashes of accepted certificates in ``pin_sha256``.
})
))
-Moving cache to tmpfs
-^^^^^^^^^^^^^^^^^^^^^
-Moving cache to temporary file storage.
-Data is stored in volatile memory instead of a persistent storage device.
-On reboot, everything stored in *tmpfs* will be lost.
+Non-persistent cache
+^^^^^^^^^^^^^^^^^^^^
+
+Knot Resolver's cache contains data clients queried for.
+By default the cache is saved on persistent storage device
+it means content in cache is persisted during power-off and reboot.
+
+If you are concerned about attackers who are able to get access to your
+computer system in power-off state and your storage device is not secured by
+encryption you can move the cache to **tmpfs**, temporary file storage.
+The cache content will be saved in memory and lost on power-off or reboot.
+In most of the Unix-like systems ``/tmp``, ``/var/lock`` and ``/var/run`` are commonly *tmpfs*.
+Directory for resolver can be configured by ``systemd-tmpfiles`` to be automatically created on boot.
+
+Copy Knot Resolver's ``tmpfiles.d`` configuration to ``/etc/tmpfiles.d``.
+
+.. code-block:: bash
+
+ $ cp /usr/lib/tmpfiles.d/knot-resolver.conf /etc/tmpfiles.d/knot-resolver.conf
+
+Add directory rules to ``knot-resolver.conf``.
+
+.. code-block:: bash
+
+ $ echo 'd /tmp/knot-resolver 0750 knot-resolver knot-resolver - -' | sudo tee -a /etc/tmpfiles.d/knot-resolver.conf
+
+The file should look like this
-For example, in most of the Unix-like systems ``/tmp``, ``/var/lock`` and ``/var/run`` are commonly *tmpfs*.
-You can check file system type by ``df -T /tmp`` command.
+.. code-block:: bash
+
+ $ cat /etc/tmpfiles.d/knot-resolver.conf
+ # tmpfiles.d(5) directories for knot-resolver (kresd)
+ # Type Path Mode UID GID Age Argument
+ d /run/knot-resolver 0750 root root - -
+ d /var/cache/knot-resolver 0750 knot-resolver knot-resolver - -
+ d /tmp/knot-resolver 0750 knot-resolver knot-resolver - -
-Move cache storage to ``/tmp/knot-resolver``
+You can reboot system to check if directory was created and then cache can be moved to ``/tmp/knot-resolver``
.. code-block:: lua
cache.storage = 'lmdb:///tmp/knot-resolver'
-Check cache storage
-.. code-block:: bash
+TLS server configuration
+^^^^^^^^^^^^^^^^^^^^^^^^
- > cache.current_storage
- lmdb:///tmp/knot-resolver
+This allows clients to send queries to your resolver
+using DNS-over-TLS. It does not protect queries send out by your resolver.
+To protect queries send out by your resolver DNS forwarding over
+DNS-over-TLS needs to be configured.
-Example ``kresd.conf``
-^^^^^^^^^^^^^^^^^^^^^^
+Enable tls on listening interfaces.
.. code-block:: lua
- -- bind to interfaces
- net = {'192.168.1.1','fc00::1:1'}
+ net.listen('192.168.1.1', 853, { kind = 'tls' })
+ net.listen('fc00::1:1', 853, { kind = 'tls' })
- -- configure TLS server
- net.tls(net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem"))
- -- Move cache to '/tmp/knot-resolver' tmpfs
- cache.storage = 'lmdb:///tmp/knot-resolver'
+.. Warning::
- -- load policy module
- modules = { 'policy' }
+ 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 can be done by using function :func:`net.tls()`.
- -- forward over TLS
- policy.add(policy.all(
- policy.TLS_FORWARD({
- {'2001:DB8::d0c', hostname='res.example.com', ca_file='/etc/knot-resolver/tlsca.crt'},
- {'192.0.2.1', pin_sha256={'YQ=='}
- })
- ))
+.. code-block:: lua
- -- forwarding to multiple targets
- policy.add(policy.slice(
- policy.slice_randomize_psl(),
- policy.TLS_FORWARD({{'192.0.2.1', hostname='res.example.com'}}),
- -- multiple servers can be specified for a single slice
- -- the one with lowest round-trip time will be used
- policy.TLS_FORWARD({
- {'193.17.47.1', hostname='odvr.nic.cz'},
- {'185.43.135.1', hostname='odvr.nic.cz'},
- })
- ))
+ net.tls("/etc/knot-resolver/server-cert.pem", "/etc/knot-resolver/server-key.pem")
.. _ispresolver:
-============
ISP Resolver
============
Limiting client access
^^^^^^^^^^^^^^^^^^^^^^
-More on :ref:`mod-view`
The current implementation is best understood as three separate rule chains:
vanilla :func:`policy.add()`, :func:`view:tsig()` and :func:`view:addr`.
modules = { 'view' }
- -- Block local IPv4 clients (ACL like)
+ -- block local IPv4 clients (ACL like)
view:addr('127.0.0.1', policy.all(policy.DENY))
- -- Drop queries with suffix match for remote client
+ -- brop queries with suffix match for remote client
view:addr('10.0.0.0/8', policy.suffix(policy.TC, policy.todnames({'example.com'})))
- -- Whitelist queries identified by TSIG key
+ -- whitelist queries identified by TSIG key
view:tsig('\5mykey', policy.all(policy.PASS))
policy.add(policy.rpz(policy.DENY, 'blacklist.rpz'))
-Hand-made
-`````````
-Hand-made Blacklist
-
-.. code-block:: lua
-
- --
-
Max cache size
^^^^^^^^^^^^^^
Maximal cache size can be larger than available RAM,
cache.size = 4 * GB
-Statistics
-^^^^^^^^^^
+.. Statistics
+ ^^^^^^^^^^
-Worker is a service over event loop that tracks and schedules outstanding queries,
-you can see the statistics or schedule new queries.
+ Worker is a service over event loop that tracks and schedules outstanding queries,
+ you can see the statistics or schedule new queries.
-.. code-block:: lua
+ .. code-block:: lua
- -- return table of worker statistics
- > worker.stats()
+ -- return table of worker statistics
+ > worker.stats()
- -- return table of low-level cache statistics
- > cache.stats()
+ -- return table of low-level cache statistics
+ > cache.stats()
-``worker.stats() cache.stats()`` commands can be executed synchronously over all forks.
-Results are returned as a table ordered as forks.
-Expression inserted to ``map ''`` can be any valid expression in Lua.
+ ``worker.stats() cache.stats()`` commands can be executed synchronously over all forks.
+ Results are returned as a table ordered as forks.
+ Expression inserted to ``map ''`` can be any valid expression in Lua.
-.. code-block:: lua
+ .. code-block:: lua
- > map 'worker.stats()'
+ > map 'worker.stats()'
-:ref:`mod-stats` gathers various counters from the query resolution and server internals,
-and offers them as a key-value storage :func:`stats.list()`.
+ :ref:`mod-stats` gathers various counters from the query resolution and server internals,
+ and offers them as a key-value storage :func:`stats.list()`.
-.. code-block:: lua
+ .. code-block:: lua
- -- Statistics collector is a module
- > modules.load('stats')
+ -- statistics collector is a module
+ > modules.load('stats')
- -- Enumerate metrics
- > stats.list()
+ -- enumerate metrics
+ > stats.list()
Monitoring/logging
.. code-block:: lua
-- load module for statistics
- modules.load('stats')
+ modules = { 'stats' }
-- log statistics every second
local stat_id = event.recurrent(1 * second, function(evid)
-- stop printing statistics after first minute
event.after(1 * minute, function(evid)
- event.cancel(stat_id)
+ event.cancel(stat_id)
end)
If you need to persist state between events, encapsulate even handle in closure
.. code-block:: lua
- modules.load('stats')
-
- -- make a closure, encapsulating counter
- function speed_monitor()
- local previous = stats.list()
- -- monitoring function
- return function(evid)
- local now = stats.list()
- local total_increment = now['answer.total'] - previous['answer.total']
- local slow_increment = now['answer.slow'] - previous['answer.slow']
- if slow_increment / total_increment > 0.05 then
- log('WARNING! More than 5 %% of queries was slow!')
- end
- previous = now -- store current value in closure
- end
- end
-
- -- speed monitor every minute
- local monitor_id = event.recurrent(1 * minute, speed_monitor())
-
-
-Example ``kresd.conf``
-^^^^^^^^^^^^^^^^^^^^^^
-
-.. code-block:: lua
-
- -- bind to interfaces
- net = {'192.168.1.1','fc00::1:1'}
-
- -- set max cache size
- cache.size = 4 * GB
-
- -- modules
- modules = {
- 'view',
- 'stats'
- }
-
- -- log statistics every second
- local stat_id = event.recurrent(1 * second, function(evid)
- log(table_print(stats.list()))
- end)
-
- -- stop printing statistics after first minute
- event.after(1 * minute, function(evid)
- event.cancel(stat_id)
- end)
+ -- load module for statistics
+ modules = { 'stats' }
-- make a closure, encapsulating counter
function speed_monitor()
-- speed monitor every minute
local monitor_id = event.recurrent(1 * minute, speed_monitor())
- -- Apply RPZ for all clients, default rule is DENY
- policy.add(policy.rpz(policy.DENY, 'blacklist.rpz'))
-
- -- Block local IPv4 clients (ACL like)
- view:addr('127.0.0.1', policy.all(policy.DENY))
-
- -- Drop queries with suffix match for remote client
- view:addr('10.0.0.0/8', policy.suffix(policy.TC, policy.todnames({'example.com'})))
-
- -- Force all clients from 192.168.2.0/24 to TCP
- view:addr('192.168.2.0/24', policy.all(policy.TC))
-
- -- Whitelist queries identified by TSIG key
- view:tsig('\5mykey', policy.all(policy.PASS))
-
-
-**********
-How to Run
-**********
-
-===============
-Single instance
-===============
-
-If you're using our packages, the simplest way to run **single instance** of Knot Resolver is to use provided Knot Resolver's ``systemd`` integration.
-
-For help run ``man kresd.systemd``
-
-.. code-block:: bash
-
- ~$ systemctl start kresd@1.service
-
-See logs and status of running instance with ``systemctl status kresd@1.service`` command.
-
-.. Note:: The instance of Knot Resolver is single process incapable of multithreading.
-
-==================
-Multiple instances
-==================
-
-Knot Resolver can run in multiple independent processes, all sharing the same interface socket and cache.
-
-Because single running instance of Knot Resolver is incapable of multithreading, to use up of all resources, for instance, of 4 CPUs system, the best way is to run four instances at a time.
-
-.. code-block:: bash
-
- ~$ systemctl start kresd@1.service
- ~$ systemctl start kresd@2.service
- ~$ systemctl start kresd@3.service
- ~$ systemctl start kresd@4.service
-
-or simpler way
-
-.. code-block:: bash
-
- ~$ systemctl start kresd@{1..4}.service
-
.. _SNI: https://en.wikipedia.org/wiki/Server_Name_Indication
-.. _closures: https://www.lua.org/pil/6.1.html
\ No newline at end of file
+.. _closures: https://www.lua.org/pil/6.1.html
+.. _AUR: https://wiki.archlinux.org/index.php/Arch_User_Repository
+.. _`Learn Lua in 15 minutes`: http://tylerneylon.com/a/learn-lua/
+.. _`DNS Privacy Test Servers`: https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers
+.. _`/etc/config`: https://github.com/CZ-NIC/knot-resolver/tree/master/etc/config
\ No newline at end of file