Commit d515cb64 authored by Marek Vavruša's avatar Marek Vavruša

doc: updated documentation and examples

parent d86e6f7e
...@@ -3,50 +3,85 @@ ...@@ -3,50 +3,85 @@
Knot DNS Resolver daemon Knot DNS Resolver daemon
************************ ************************
Requirements The server is in the `daemon` directory, it works out of the box without any configuration.
============
* libuv_ 1.0+ (a multi-platform support library with a focus on asynchronous I/O) .. code-block:: bash
* Lua_ 5.1+ (embeddable scripting language, LuaJIT_ is preferred)
Running $ kresd -h # Get help
======= $ kresd -a ::1
There is a separate resolver library in the `lib` directory, and a server in the `daemon` directory. Enabling DNSSEC
===============
The resolver supports DNSSEC including :rfc:`5011` automated DNSSEC TA updates and :rfc:`7646` negative trust anchors.
To enable it, you need to provide at least _one_ trust anchor. This step is not automatic, as you're supposed to obtain
the trust anchor `using a secure channel <http://jpmens.net/2015/01/21/opendnssec-rfc-5011-bind-and-unbound/>`_.
From there, the Knot DNS Resolver can perform automatic updates for you.
1. Check the current TA published on `IANA website <https://data.iana.org/root-anchors/root-anchors.xml>`_
2. Fetch current keys, verify
3. Deploy them
.. code-block:: bash .. code-block:: bash
$ kresd -h $ kdig DNSKEY . @a.root-servers.net +noall +answer | grep 257 > root.keys
$ ldns-key2ds -n root.keys
... verify that digest matches TA published by IANA ...
$ kresd -k root.keys
You've just enabled DNSSEC!
Interacting with the daemon CLI interface
--------------------------- =============
The daemon features a CLI interface if launched interactively, type ``help`` to see the list of available commands. The daemon features a CLI interface, type ``help`` to see the list of available commands.
You can load modules this way and use their properties to get information about statistics and such.
.. code-block:: bash .. code-block:: bash
$ kresd /var/run/knot-resolver $ kresd /var/run/knot-resolver
[system] started in interactive mode, type 'help()' [system] started in interactive mode, type 'help()'
> cache.count() > cache.count()
53 53
.. role:: lua(code) .. role:: lua(code)
:language: lua :language: lua
Running in forked mode Verbose output
---------------------- --------------
If the debug logging is compiled in, you can turn on verbose tracing of server operation with the ``-v`` option.
You can also toggle it on runtime with ``verbose(true|false)`` command.
.. code-block:: bash
$ kresd -v
Scaling out
===========
The server can clone itself into multiple processes upon startup, this enables you to scale it on multiple cores. The server can clone itself into multiple processes upon startup, this enables you to scale it on multiple cores.
Multiple processes can serve different addresses, but still share the same working directory and cache.
You can add start and stop processes on runtime based on the load.
.. code-block:: bash .. code-block:: bash
$ kresd -f 2 rundir > kresd.log $ kresd -f 4 rundir > kresd.log &
$ kresd -f 2 rundir > kresd_2.log & # Extra instances
$ pstree $$ -g
bash(3533)─┬─kresd(19212)─┬─kresd(19212)
│ ├─kresd(19212)
│ └─kresd(19212)
├─kresd(19399)───kresd(19399)
└─pstree(19411)
$ kill 19399 # Kill group 2, former will continue to run
bash(3533)─┬─kresd(19212)─┬─kresd(19212)
│ ├─kresd(19212)
│ └─kresd(19212)
└─pstree(19460)
.. note:: On recent Linux supporting ``SO_REUSEPORT`` (since 3.9, backported to RHEL 2.6.32) it is also able to bind to the same endpoint and distribute the load between the forked processes. If the kernel doesn't support it, you can still fork multiple processes on different ports, and do load balancing externally (on firewall or with `dnsdist <http://dnsdist.org/>`_). .. note:: On recent Linux supporting ``SO_REUSEPORT`` (since 3.9, backported to RHEL 2.6.32) it is also able to bind to the same endpoint and distribute the load between the forked processes. If the kernel doesn't support it, you can still fork multiple processes on different ports, and do load balancing externally (on firewall or with `dnsdist <http://dnsdist.org/>`_).
Notice the absence of an interactive CLI. You can attach to the the consoles for each process, they are in ``rundir/tty/PID``.
Notice it isn't interactive, but you can attach to the the consoles for each process, they are in ``rundir/tty/PID``.
.. code-block:: bash .. code-block:: bash
...@@ -59,16 +94,6 @@ of running processes, and you can test the process for liveliness by connecting ...@@ -59,16 +94,6 @@ of running processes, and you can test the process for liveliness by connecting
.. warning:: This is very basic way to orchestrate multi-core deployments and doesn't scale in multi-node clusters. Keep an eye on the prepared ``hive`` module that is going to automate everything from service discovery to deployment and consistent configuration. .. warning:: This is very basic way to orchestrate multi-core deployments and doesn't scale in multi-node clusters. Keep an eye on the prepared ``hive`` module that is going to automate everything from service discovery to deployment and consistent configuration.
Verbose output
--------------
If the debug logging is compiled in, you can turn on verbose tracing of server operation with the ``-v`` option.
You can also toggle it on runtime with ``verbose(true|false)`` command.
.. code-block:: bash
$ kresd -v
Configuration Configuration
============= =============
...@@ -86,11 +111,8 @@ comfortable in the current working directory. ...@@ -86,11 +111,8 @@ comfortable in the current working directory.
And you're good to go for most use cases! If you want to use modules or configure daemon behavior, read on. And you're good to go for most use cases! If you want to use modules or configure daemon behavior, read on.
There are several choices on how you can configure the daemon, a RPC interface a CLI and a configuration file. There are several choices on how you can configure the daemon, a RPC interface, a CLI, and a configuration file.
Fortunately all share common syntax and are transparent to each other, e.g. changes made during the runtime are kept Fortunately all share common syntax and are transparent to each other.
in the redo log and are immediately visible.
.. warning:: Redo log is not yet implemented, changes are visible during the process lifetime only.
Configuration example Configuration example
--------------------- ---------------------
...@@ -99,9 +121,9 @@ Configuration example ...@@ -99,9 +121,9 @@ Configuration example
-- 10MB cache -- 10MB cache
cache.size = 10*MB cache.size = 10*MB
-- load some modules -- load some modules
modules = { 'hints', 'cachectl' } modules = { 'policy', 'cachectl' }
-- interfaces -- interfaces
net = { '127.0.0.1' } net = { '127.0.0.1', '::1' }
Configuration syntax Configuration syntax
-------------------- --------------------
...@@ -347,24 +369,6 @@ For when listening on ``localhost`` just doesn't cut it. ...@@ -347,24 +369,6 @@ For when listening on ``localhost`` just doesn't cut it.
Trust anchors and DNSSEC Trust anchors and DNSSEC
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
The resolver supports DNSSEC including :rfc:`5011` automated DNSSEC TA updates and :rfc:`7646` negative trust anchors.
To enable it, you need to provide at least _one_ trust anchor. This step is not automatic, as you're supposed to obtain
the trust anchor using a secure channel. From there, the Knot DNS Resolver can perform automatic updates for you if you
run in managed mode.
The recommended way is as follows:
1. Check the current TA published on `IANA website <https://data.iana.org/root-anchors/root-anchors.xml>`_
2. Fetch current keys, verify and use
.. code-block:: bash
$ kdig dnskey . @a.root-servers.net +noall +answer | grep 257 > root.keys
$ ldns-key2ds -n root.keys
... verify that digest matches TA published by IANA ...
$ kresd -k root.keys
You've just enabled DNSSEC, congratulations!
.. function:: trust_anchors.config(keyfile) .. function:: trust_anchors.config(keyfile)
:param string keyfile: File containing DNSKEY records, should be writeable. :param string keyfile: File containing DNSKEY records, should be writeable.
...@@ -378,18 +382,6 @@ You've just enabled DNSSEC, congratulations! ...@@ -378,18 +382,6 @@ You've just enabled DNSSEC, congratulations!
> trust_anchors.config('root.keys') > trust_anchors.config('root.keys')
[trust_anchors] key: 19036 state: Valid [trust_anchors] key: 19036 state: Valid
.. function:: trust_anchors.add(rr_string)
:param string rr_string: DS/DNSKEY records in presentation format (e.g. `. 3600 IN DS 19036 8 2 49AAC11...`)
Inserts DS/DNSKEY record(s) into current keyset. These will not be managed or updated.
Example output:
.. code-block:: lua
> trust_anchors.add('. 3600 IN DS 19036 8 2 49AAC11...')
.. function:: trust_anchors.set_insecure(nta_set) .. function:: trust_anchors.set_insecure(nta_set)
:param table nta_list: List of domain names (text format) representing NTAs. :param table nta_list: List of domain names (text format) representing NTAs.
...@@ -408,6 +400,18 @@ You've just enabled DNSSEC, congratulations! ...@@ -408,6 +400,18 @@ You've just enabled DNSSEC, congratulations!
[1] => bad.boy [1] => bad.boy
[2] => example.com [2] => example.com
.. function:: trust_anchors.add(rr_string)
:param string rr_string: DS/DNSKEY records in presentation format (e.g. `. 3600 IN DS 19036 8 2 49AAC11...`)
Inserts DS/DNSKEY record(s) into current keyset. These will not be managed or updated.
Example output:
.. code-block:: lua
> trust_anchors.add('. 3600 IN DS 19036 8 2 49AAC11...')
Modules configuration Modules configuration
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
......
...@@ -30,7 +30,7 @@ The following is a list of software required to build Knot DNS Resolver from sou ...@@ -30,7 +30,7 @@ The following is a list of software required to build Knot DNS Resolver from sou
"`GNU Make`_ 3.80+", "*all*", "*(build only)*" "`GNU Make`_ 3.80+", "*all*", "*(build only)*"
"`pkg-config`_", "*all*", "*(build only)* [#]_" "`pkg-config`_", "*all*", "*(build only)* [#]_"
"C compiler", "*all*", "*(build only)* [#]_" "C compiler", "*all*", "*(build only)* [#]_"
"libknot_ 2.0+", "*all*", "Knot DNS library." "libknot_ 2.0+", "*all*", "Knot DNS library (requires autotools, GnuTLS and Jansson)."
"LuaJIT_ 2.0+", "``daemon``", "Embedded scripting language (Lua_ 5.1+ with limitations)." "LuaJIT_ 2.0+", "``daemon``", "Embedded scripting language (Lua_ 5.1+ with limitations)."
"libuv_ 1.0+", "``daemon``", "Multiplatform I/O and services." "libuv_ 1.0+", "``daemon``", "Multiplatform I/O and services."
...@@ -43,7 +43,6 @@ There are also *optional* packages that enable specific functionality in Knot DN ...@@ -43,7 +43,6 @@ There are also *optional* packages that enable specific functionality in Knot DN
"hiredis_", "``modules/redis``", "To build redis backend module." "hiredis_", "``modules/redis``", "To build redis backend module."
"cmocka_", "``unit tests``", "Unit testing framework." "cmocka_", "``unit tests``", "Unit testing framework."
"Python_", "``integration tests``", "For test scripts." "Python_", "``integration tests``", "For test scripts."
"GCCGO_", "``modules/go``", "For building Go modules, see modules documentation."
"Doxygen_", "``documentation``", "Generating API documentation." "Doxygen_", "``documentation``", "Generating API documentation."
"Sphinx_", "``documentation``", "Building this HTML/PDF documentation." "Sphinx_", "``documentation``", "Building this HTML/PDF documentation."
"breathe_", "``documentation``", "Exposing Doxygen API doc to Sphinx." "breathe_", "``documentation``", "Exposing Doxygen API doc to Sphinx."
......
...@@ -13,6 +13,7 @@ Modular architecture of the library keeps the core tiny and efficient, and provi ...@@ -13,6 +13,7 @@ Modular architecture of the library keeps the core tiny and efficient, and provi
lib lib
daemon daemon
modules modules
modules_api
Indices and tables Indices and tables
......
.. include:: ../modules/README.rst
.. _modules-implemented: .. _modules-implemented:
Implemented modules *************************
=================== Knot DNS Resolver modules
*************************
.. contents:: .. contents::
:depth: 1 :depth: 1
...@@ -18,4 +17,4 @@ Implemented modules ...@@ -18,4 +17,4 @@ Implemented modules
.. include:: ../modules/kmemcached/README.rst .. include:: ../modules/kmemcached/README.rst
.. include:: ../modules/redis/README.rst .. include:: ../modules/redis/README.rst
.. include:: ../modules/ketcd/README.rst .. include:: ../modules/ketcd/README.rst
.. include:: ../modules/cachectl/README.rst .. include:: ../modules/cachectl/README.rst
\ No newline at end of file
.. include:: ../modules/README.rst
\ No newline at end of file
**************************** .. _modules-api:
Knot DNS Resolver extensions
****************************
Writing extensions *********************
================== Modules API reference
*********************
.. contents:: .. contents::
:depth: 2 :depth: 1
:local: :local:
Supported languages Supported languages
------------------- ===================
Currently modules written in C and Lua are supported. Currently modules written in C and Lua are supported.
There is also a rudimentary support for writing modules in Go |---| There is also a rudimentary support for writing modules in Go |---|
...@@ -19,7 +18,7 @@ There is also a rudimentary support for writing modules in Go |---| ...@@ -19,7 +18,7 @@ There is also a rudimentary support for writing modules in Go |---|
(3) no coroutines and no garbage collecting thread, as the Go code is called from C threads. (3) no coroutines and no garbage collecting thread, as the Go code is called from C threads.
The anatomy of an extension The anatomy of an extension
--------------------------- ===========================
A module is a shared object or script defining specific functions, here's an overview. A module is a shared object or script defining specific functions, here's an overview.
...@@ -45,61 +44,8 @@ This doesn't apply for Go, as it for now always implements `main` and requires c ...@@ -45,61 +44,8 @@ This doesn't apply for Go, as it for now always implements `main` and requires c
If the module exports a layer implementation, it is automatically discovered by :c:func:`kr_resolver` on resolution init and plugged in. The order in which the modules are registered corresponds to the call order of layers. If the module exports a layer implementation, it is automatically discovered by :c:func:`kr_resolver` on resolution init and plugged in. The order in which the modules are registered corresponds to the call order of layers.
Writing a module in C
---------------------
As almost all the functions are optional, the minimal module looks like this:
.. code-block:: c
#include "lib/module.h"
/* Convenience macro to declare module API. */
KR_MODULE_EXPORT(mymodule);
Let's define an observer thread for the module as well. It's going to be stub for the sake of brevity,
but you can for example create a condition, and notify the thread from query processing by declaring
module layer (see the :ref:`Writing layers <lib-layers>`).
.. code-block:: c
static void* observe(void *arg)
{
/* ... do some observing ... */
}
int mymodule_init(struct kr_module *module)
{
/* Create a thread and start it in the background. */
pthread_t thr_id;
int ret = pthread_create(&thr_id, NULL, &observe, NULL);
if (ret != 0) {
return kr_error(errno);
}
/* Keep it in the thread */
module->data = thr_id;
return kr_ok();
}
int mymodule_deinit(struct kr_module *module)
{
/* ... signalize cancellation ... */
void *res = NULL;
pthread_t thr_id = (pthread_t) module->data;
int ret = pthread_join(thr_id, res);
if (ret != 0) {
return kr_error(errno);
}
return kr_ok();
}
This example shows how a module can run in the background, this enables you to, for example, observe
and publish data about query resolution.
Writing a module in Lua Writing a module in Lua
----------------------- =======================
The probably most convenient way of writing modules is Lua since you can use already installed modules The probably most convenient way of writing modules is Lua since you can use already installed modules
from system and have first-class access to the scripting engine. You can also tap to all the events, that from system and have first-class access to the scripting engine. You can also tap to all the events, that
...@@ -179,8 +125,61 @@ Since the modules are like any other Lua modules, you can interact with them thr ...@@ -179,8 +125,61 @@ Since the modules are like any other Lua modules, you can interact with them thr
.. tip:: The module can be placed anywhere in the Lua search path, in the working directory or in the MODULESDIR. .. tip:: The module can be placed anywhere in the Lua search path, in the working directory or in the MODULESDIR.
Writing a module in C
=====================
As almost all the functions are optional, the minimal module looks like this:
.. code-block:: c
#include "lib/module.h"
/* Convenience macro to declare module API. */
KR_MODULE_EXPORT(mymodule);
Let's define an observer thread for the module as well. It's going to be stub for the sake of brevity,
but you can for example create a condition, and notify the thread from query processing by declaring
module layer (see the :ref:`Writing layers <lib-layers>`).
.. code-block:: c
static void* observe(void *arg)
{
/* ... do some observing ... */
}
int mymodule_init(struct kr_module *module)
{
/* Create a thread and start it in the background. */
pthread_t thr_id;
int ret = pthread_create(&thr_id, NULL, &observe, NULL);
if (ret != 0) {
return kr_error(errno);
}
/* Keep it in the thread */
module->data = thr_id;
return kr_ok();
}
int mymodule_deinit(struct kr_module *module)
{
/* ... signalize cancellation ... */
void *res = NULL;
pthread_t thr_id = (pthread_t) module->data;
int ret = pthread_join(thr_id, res);
if (ret != 0) {
return kr_error(errno);
}
return kr_ok();
}
This example shows how a module can run in the background, this enables you to, for example, observe
and publish data about query resolution.
Writing a module in Go Writing a module in Go
---------------------- ======================
.. note:: At the moment only a limited subset of Go is supported. The reason is that the Go functions must run inside the goroutines, and *presume* the garbage collector and scheduler are running in the background. `GCCGO`_ compiler can build dynamic libraries, and also allow us to bootstrap basic Go runtime, including a trampoline to call Go functions. The problem with the ``layer()`` and callbacks is that they're called from C threads, that Go runtime has no knowledge of. Thus neither garbage collection or spawning routines can work. The solution could be to register C threads to Go runtime, or have each module to run inside its world loop and use IPC instead of callbacks |---| alas neither is implemented at the moment, but may be in the future. .. note:: At the moment only a limited subset of Go is supported. The reason is that the Go functions must run inside the goroutines, and *presume* the garbage collector and scheduler are running in the background. `GCCGO`_ compiler can build dynamic libraries, and also allow us to bootstrap basic Go runtime, including a trampoline to call Go functions. The problem with the ``layer()`` and callbacks is that they're called from C threads, that Go runtime has no knowledge of. Thus neither garbage collection or spawning routines can work. The solution could be to register C threads to Go runtime, or have each module to run inside its world loop and use IPC instead of callbacks |---| alas neither is implemented at the moment, but may be in the future.
...@@ -253,14 +252,14 @@ Now we can add the implementations for the ``Begin`` and ``Finish`` functions, a ...@@ -253,14 +252,14 @@ Now we can add the implementations for the ``Begin`` and ``Finish`` functions, a
See the CGO_ for more information about type conversions and interoperability between the C/Go. See the CGO_ for more information about type conversions and interoperability between the C/Go.
Configuring modules Configuring modules
------------------- ===================
There is a callback ``X_config()`` that you can implement, see hints module. There is a callback ``X_config()`` that you can implement, see hints module.
.. _mod-properties: .. _mod-properties:
Exposing C/Go module properties Exposing C/Go module properties
------------------------------- ===============================
A module can offer NULL-terminated list of *properties*, each property is essentially a callable with free-form JSON input/output. A module can offer NULL-terminated list of *properties*, each property is essentially a callable with free-form JSON input/output.
JSON was chosen as an interchangeable format that doesn't require any schema beforehand, so you can do two things - query the module properties JSON was chosen as an interchangeable format that doesn't require any schema beforehand, so you can do two things - query the module properties
...@@ -309,7 +308,8 @@ Here's an example how a module can expose its property: ...@@ -309,7 +308,8 @@ Here's an example how a module can expose its property:
KR_MODULE_EXPORT(cache) KR_MODULE_EXPORT(cache)
Once you load the module, you can call the module property from the interactive console: Once you load the module, you can call the module property from the interactive console.
*Note* |---| the JSON output will be transparently converted to Lua tables.
.. code-block:: bash .. code-block:: bash
...@@ -318,7 +318,7 @@ Once you load the module, you can call the module property from the interactive ...@@ -318,7 +318,7 @@ Once you load the module, you can call the module property from the interactive
[system] started in interactive mode, type 'help()' [system] started in interactive mode, type 'help()'
> modules.load('cached') > modules.load('cached')
> cached.get_size() > cached.get_size()
{ "size": 53 } [size] => 53
*Note* |---| this relies on function pointers, so the same ``static inline`` trick as for the ``Layer()`` is required for C/Go. *Note* |---| this relies on function pointers, so the same ``static inline`` trick as for the ``Layer()`` is required for C/Go.
...@@ -328,9 +328,6 @@ Special properties ...@@ -328,9 +328,6 @@ Special properties
If the module declares properties ``get`` or ``set``, they can be used in the Lua interpreter as If the module declares properties ``get`` or ``set``, they can be used in the Lua interpreter as
regular tables. regular tables.
.. warning:: This is not yet completely implemented, as the module I/O format may change to map_t a/o
embedded JSON tokenizer.
.. _`not present in Go`: http://blog.golang.org/gos-declaration-syntax .. _`not present in Go`: http://blog.golang.org/gos-declaration-syntax
.. _CGO: http://golang.org/cmd/cgo/ .. _CGO: http://golang.org/cmd/cgo/
.. _GCCGO: https://golang.org/doc/install/gccgo .. _GCCGO: https://golang.org/doc/install/gccgo
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment