Trust-dns

A Rust based DNS server

Download as .zip Download as .tar.gz View on GitHub

Build Status codecov License: MIT License: Apache 2.0 Dependabot Status Discord

Trust-DNS

Trust-DNS

A Rust based DNS client, server, and Resolver, built to be safe and secure from the ground up.

This repo consists of multiple crates:

Library Description
Trust-DNS Binaries for running a DNS authoritative server.
Proto trust-dns-proto Raw DNS library, exposes an unstable API and only for use by the other Trust-DNS libraries, not intended for end-user use.
Client trust-dns-client Used for sending query, update, and notify messages directly to a DNS server.
Server trust-dns-server Use to host DNS records, this also has a named binary for running in a daemon form.
Resolver trust-dns-resolver Utilizes the client library to perform DNS resolution. Can be used in place of the standard OS resolution facilities.
Rustls trust-dns-rustls Implementation of DNS over TLS protocol using the rustls and ring libraries.
NativeTls trust-dns-native-tls Implementation of DNS over TLS protocol using the Host OS’ provided default TLS libraries
OpenSsl trust-dns-openssl Implementation of DNS over TLS protocol using OpenSSL

Goals

Status:

Resolver

The Trust-DNS Resolver is a native Rust implementation for stub resolution in Rust applications. The Resolver supports many common query patterns, all of which can be configured when creating the Resolver. It is capable of using system configuration on Unix and Windows. On Windows there is a known issue that relates to a large set of interfaces being registered for use, so might require ignoring the system configuration.

The Resolver will properly follow CNAME chains as well as SRV record lookups. There is a long term plan to make the Resolver capable of fully recursive queries, but that’s not currently possible.

Client

The Trust-DNS Client is intended to be used for operating against a DNS server directly. It can be used for verifying records or updating records for servers that support SIG0 and dynamic update. The Client is also capable of validating DNSSEC. As of now NSEC3 validation is not yet supported, though NSEC is. There are two interfaces that can be used, the async/await compatible AsyncClient and a blocking Client for ease of use. Today, Tokio is required for the executor Runtime.

Unique client side implementations

These are standards supported by the DNS protocol. The client implements them as high level interfaces, which is a bit more rare.

Feature Description
SyncDnssecClient DNSSec validation
create atomic create of a record, with authenticated request
append verify existence of a record and append to it
compare_and_swap atomic (depends on server) compare and swap
delete_by_rdata delete a specific record
delete_rrset delete an entire record set
delete_all delete all records sets with a given name
notify notify server that it should reload a zone

Server

The server code is complete, the daemon supports IPv4 and IPv6, UDP and TCP. There currently is no way to limit TCP and AXFR operations, so it is still not recommended to put into production as TCP can be used to DOS the service. Zone file parsing is complete and supported. There is currently no forking option, and the server is not yet threaded (although it is implemented with async IO, so threading may not be a huge benefit). There is still a lot of work to do before a server can be trusted with this externally. Running it behind a firewall on a private network would be safe.

Zone signing support is complete, to insert a key store a pem encoded rsa file in the same directory as the initial zone file with the .key suffix. Note: this must be only readable by the current user. If one is not present one will be created and written to the correct location. This also acts as the initial key for dynamic update SIG(0) validation. To get the public key, the DNSKEY record for the zone can be queried. This is needed to provide to other upstream servers to create the DS key. Dynamic DNS is also complete, if enabled, a journal file will be stored next to the zone file with the jrnl suffix. Note: if the key is changed or updated, it is currently the operators responsibility to remove the only public key from the zone, this allows for the DNSKEY to exist for some unspecified period of time during key rotation. Rotating the key currently is not available online and requires a restart of the server process.

DNS-over-TLS and DNS-over-HTTPS on the Server

Support of TLS on the Server is managed through a pkcs12 der file. The documentation is captured in the example test config file, example.toml. A registered certificate to the server can be pinned to the Client with the add_ca() method. Alternatively, as the client uses the rust-native-tls library, it should work with certificate signed by any standard CA.

DNS-over-TLS and DNS-over-HTTPS

DoT and DoH are supported. This is accomplished through the use of one of native-tls, openssl, or rustls (only rustls is currently supported for DoH). The Resolver requires only requires valid DoT or DoH resolvers being registered in order to be used.

To use with the Client, the TlsClientConnection or HttpsClientConnection should be used. Similarly, to use with the tokio AsyncClient the TlsClientStream or HttpsClientStream should be used. ClientAuth, mTLS, is currently not supported, there are some issues still being worked on. TLS is useful for Server authentication and connection privacy.

To enable DoT one of the features dns-over-native-tls, dns-over-openssl, or dns-over-rustls must be enabled, dns-over-https-rustls is used for DoH.

DNSSec status

Currently the root key is hardcoded into the system. This gives validation of DNSKEY and DS records back to the root. NSEC is implemented, but not NSEC3. Because caching is not yet enabled, it has been noticed that some DNS servers appear to rate limit the connections, validating RRSIG records back to the root can require a significant number of additional queries for those records.

Zones will be automatically resigned on any record updates via dynamic DNS. To enable DNSSEC, one of the features dnssec-openssl or dnssec-rustls must be enabled.

RFCs implemented

Basic operations

Update operations

Secure DNS operations

RFCs in progress or not yet implemented

Basic operations

Update operations

Secure DNS operations

Usage

This assumes that you have Rust stable installed. These presume that the trust-dns repos have already been synced to the local system:

$ git clone https://github.com/bluejekyll/trust-dns.git
$ cd trust-dns

Prerequisites

Minimum Rust Version

Mac OS X: using homebrew

  $ brew install openssl
  $ export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include
  $ export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib

Debian-based (includes Ubuntu & Raspbian): using apt-get

  # note for openssl that a minimum version of 1.0.2 is required for TLS, 
  #  if this is an issue, TLS can be disabled (on the client), see below.
  $ apt-get install openssl
  $ apt-get install libssl-dev pkg-config

Testing

Trust-DNS uses cargo-make for build workflow management. While running cargo test at the project root will work, this is not exhaustive. Install cargo-make with cargo install cargo-make.

$ cargo make
$ cargo make all-features
$ cargo make dns-over-https-rustls

Building

$ cargo build --release -p trust-dns

Running

Warning: Trust-DNS is still under development, running in production is not recommended. The server is currently only single-threaded, it is non-blocking so this should allow it to work with most internal loads.

$ ./target/release/named --version
$ ./target/release/named --help

You may want not passing the -p parameter will run on default DNS ports. For the tls features, there are also port options for those, see trust-dns --help

$ ./target/release/named -c ./tests/test-data/named_test_configs/example.toml -z ./tests/test-data/named_test_configs/ -p 24141
$ dig @127.0.0.1 -p 24141 www.example.com

Using the trust-dns-resolver CLI

Available in 0.20

$ cargo install --bin resolve trust-dns-util

Or from source, in the trust-dns directory

$ cargo install --bin resolve --path util

example:

$ resolve www.example.com.
Querying for www.example.com. A from udp:8.8.8.8:53, tcp:8.8.8.8:53, udp:8.8.4.4:53, tcp:8.8.4.4:53, udp:[2001:4860:4860::8888]:53, tcp:[2001:4860:4860::8888]:53, udp:[2001:4860:4860::8844]:53, tcp:[2001:4860:4860::8844]:53
Success for query name: www.example.com. type: A class: IN
        www.example.com. 21063 IN A 93.184.216.34

Using as a dependency and custom features

The Client has a few features which can be disabled for different reasons when embedding in other software.

Using custom features in dependencies:

[dependencies]
  ...
trust-dns = { version = "*", default-features = false, features = ["dnssec-openssl"] }

Using custom features during build:

$> cargo build --release --features dns-over-rustls
...

FAQ

Community

For live discussions beyond this repository, please see this Discord.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.