Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
BIND
BIND
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 633
    • Issues 633
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 104
    • Merge Requests 104
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • ISC Open Source Projects
  • BINDBIND
  • Wiki
    • Doh
  • DOH and DoT Design

Last edited by Evan Hunt Dec 08, 2020
Page history

DOH and DoT Design

BIND9 DoH/DoT design

This document describes the design of the DoT and DoH implementation for BIND9. This will be developed in the 9.17 development branch, and backported to 9.16 (with some exceptions). Unfortunately external Gitlab users cannot comment directly on wiki pages, but comments are welcome here: #1144 (closed)

netmgr

BIND 9.16 introduced the new framework for processing incoming requests - netmgr. Previously, the code responsible for processing incoming packets and e.g. reading from sockets and accepting new TCP connections was deeply intertwined - which made it complex, error-prone and made it very hard to add new transports to the code. The idea behind netmgr is to separate the transport layer from the packet processing layer completely.

The code currently supports Do53 for both UDP and TCP - and from the packet processing code perspective there's one single transport-agnostic function that gets a buffer with whole DNS packet (with the 2-byte length stripped for TCP). The DoT and DoH code will also be based on that principle - the transport layer processing will be kept in netmgr, while the query processing code will just receive a buffer with a binary packet.

The netmgr is layered in design - the tcpdns module which processes incoming TCP packets uses the netmgr itself, and it can use any type of streaming socket the netmgr supports - TCP for now, TLS for DoT.

External libraries

The implementation will use two external libraries - OpenSSL for encryption and NGHTTP2 for http/2. OpenSSL was chosen because it's already used extensively in BIND9 code (and using two crypto libraries simultaneously doesn't make any sense), NGHTTP2 was chosen as the most popular and well-maintained implementation of http/2 protocol - and DoH mandates http/2 usage.

TLS layer

The TLS layer will be added as another streaming socket type to netmgr - along with currently implemented TCP. The only difference will be in new connect - isc_nm_connecttls(), and listen - isc_nm_listentls() functions which will accept TLS context as one of their parameters. Additional generic functions will be added to allow the client code to e.g. get information about connections' TLS parameters. The TLS layer will be using OpenSSL library, using its BIO mechanism to provide IO over netmgr stream sockets.

DoT server

As it was stated above, the tcpdns module uses netmgr itself to communicate over any streaming socket supported by netmgr. That makes adding TLS support quite trivial - the isc_nm_listentcpdns() function will accept additional TLS context parameter which, if not null, will make the function call isc_nm_listentls() instead of isc_nm_listentcp() - the rest will be unchanged as it uses generic stream socket functions.

DoT client

DoT client will be built into dig/delv - it'll be using netmgr isc_nm_connecttls() function and then use the acquired socket as any other stream socket. The +dot option will tell dig to use DoT and set the default port to 853.

http/2

The http/2 layer will be built on top of any streaming socket supported by the netmgr - although the HTTP2 standard itself does not mandate TLS usage, in practice all clients support it and some don't support HTTP2 over an unencrypted connection at all. Internally the server will be based on nghttp2 library, externally it will be based on URI-callback model - the client (DoH server, statistics channel server) will launch a listener and then add callbacks to specific URIs, keeping the HTTP processing itself separate.

Statistics channel

BIND9 has a very limited http/1 server built in - it's used to provide statistics channel in JSON and XML formats. With a proper http/2 server, built-in statistics channel will be served with it too

This feature will not be backported to 9.16.

DoH server

DoH server will be using netmgr http/2 on one side, and the libns client library - specifically, ns_client_request() function, on the other - when an http request is received it will parse the incoming packet to a binary buffer, pass it to request processing function and, when the response is ready, pass it on to http server to be sent to the requesting client.

DISCUSS:

  • when BIND 9 is compiled with JSON-C library, the DoH server in BIND 9 should be able to also serve application/dns-json payload.

DoH client

DoH client will be built into dig/delv, using netmgr http2 layer (nghttp2 library provides both http2 client and server). DoH usage will be enabled by the '@<server_addr>' option - e.g. dig isc.org @https://public-dns.isc.org/query

Configuration options

DoT and DoH will have to extend BIND9 configuration syntax. Since it's virtually impossible to change the option syntax while keeping backward compatibility the proposed design might change after consulting the community.

TLS

Since TLS will be used by various services, it'd be convenient to introduce a single configuration option describing TLS parameters - most notably, key and certificate file. The proposed syntax for the option is:

tls <string> {
    key-file <quoted-string>;
    cert-file <quoted-string>;
};

To make deployment simpler, a generic default tls with autogenerated certificate might be provided.

DISCUSSION:

  • the autogenerated certificate will be emphemeral or saved in a secure place in workdir? (@ondrej)
  • should it support ACME protocol (LE) in future? (@ondrej)
  • this is also underspecified, there needs to be more global TLS options (using nginx option names) (@ondrej):
    • ssl_protocols (1.2 and 1.3, I would prevent anything less)
    • ssl_dhparam
    • ssl_ciphers (and ecdh ciphers) (ssl_prefer_server_ciphers could be always on?)
    • ssl_session configuration (ssl_session_timeout, ssl_session_cache, ssl_session_tickets)
    • ssl_stapling and ssl_stapling_verify

DoT

Configuring listening for TLS connections extends the current listen-on and listen-on-v6 syntax:

listen-on [ port <integer> ] [ tls <string> ] { <address_match_element>; ... };

DoH

Configuring DoH is more complex, as e.g. multiple views can use the same address, but different endpoints identified by URIs.

A HTTP/2 server is configured by the following options:

https-server <string> [ port <integer> ] [ tls <string> ] { <address_match_element>; ... };

A DoH endpoint for a server is configure with:

https-endpoint <quoted-string> [server <string> ]

DISCUSS:

  • I would recommend matching the https-server/server strings, e.g.: https-endpoint <quoted-string> [https-server <string> ] (@ondrej)
  • Is it https-endpoint or http(2)-endpoint? (@ondrej)

Example

tls my_config {
    key-file "key.pem";
    cert-file "cert.pem";
}
listen-on port 853 tls my_config { any; };
https-server my_server port 443 tls my_config { any; };
https-endpoint "/dns-query" server my_server;

DISCUSS:

  • And example with views would be useful. (@ondrej)
  • Example with IPv6 would be useful. (@ondrej)
  • I am convinced that we should redesign listen-on to be IP version agnostic (and adjust other options v4 vs v6 accordingly) in BIND 9.17+, in BIND 9.16 we need both listen-on and listen-on-v6 (@ondrej)

Statistics

Additional 'dot' and 'doh' performance counters will be added, similar to the ones for TCP. It's important to note, that since DoT and DoH use TCP as its underlying transport, e.g. DoT connections will be also counted as TCP connections.

Testing

Conformance

Conformance testing will be performed using existing tools that support DoT and DoH - such as kdig. Internally, system tests (most likely based on the current 'tcp' test) will be created.

DISCUSS:

  • for system tests, the new pytest framework should be used - requests + dnspython could be used to glue the DoH testing client, and hyper-h2 and dnspython could be used to glue the DoH testing server.

Performance

The DoT performance will be tested using flamethrower - a DNS performance testing tool with DoT support. The DoH performance will be tested using JMeter - an HTTP performance tool.

DISCUSS:

  • what about bulldohzer for DoH performance testing?
Clone repository
  • BIND 9 F2F Meeting in Warsaw, October 2019
  • BIND 9 PKCS11
  • BIND 9 Packaging
  • BIND 9.11 ESV Soft Code Freeze
  • BIND 9.15 Plan
  • BIND 9.17 Plan
  • BIND Development and Release Process 2019
  • BIND development workflow
  • Backporting a Merge Request
  • CVSS Scoring Guidelines
  • DNSSEC Key and Signing Policy (KASP)
  • Debian Packages
  • DoH
    • DOH and DoT Design
  • Formatting test scratchpad.
  • GSOC 2019
View All Pages