DNS-over-TLS server (DoT)

DoT encrypts DNS traffic with Transport Security Layer protocol and thus protects DNS traffic from certain types of attacks.


It is important to understand limits of encrypting only DNS traffic. Relevant security analysis can be found in article Simran Patil and Nikita Borisov. 2019. What can you learn from an IP? See slides or the article itself.

DNS-over-TLS server (RFC 7858) is enabled by default on localhost. Information how to configure listening on specific IP addresses is in previous sections: net.listen().

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 net.tls().

net.tls([cert_path][, key_path])

Get/set path to a server TLS certificate and private key for DNS/TLS.

Example output:

> 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")
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.

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.


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.

net.tls_sticket_secret_file([string with path to a file containing pre-shared secret])

The same as net.tls_sticket_secret(), except the secret is read from a (binary) file.