Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] DNSSEC validation: configuration syntax #2194

Open
japaric opened this issue Apr 24, 2024 · 3 comments
Open

[RFC] DNSSEC validation: configuration syntax #2194

japaric opened this issue Apr 24, 2024 · 3 comments

Comments

@japaric
Copy link

japaric commented Apr 24, 2024

Motivation

Currently, the recursive resolver (AKA "recursor") component of the hickory-dns binary has DNSSEC validation disabled and cannot be enabled through its configuration options.

We want to be able to enable DNSSEC validation in the resolver.

Use cases

We want to support these use cases:

  • DNSSEC validation is disabled
  • DNSSEC validation is enabled

and when DNSSEC validation is enabled we have these sub- use cases:

  • use a static user-provided / externally-managed trust anchor
  • use a self-managed trust anchor, which is automatically updated given an initial trust anchor. see RFC5011

Prior art

unbound

To enable DNSSEC validation and use an externally-managed trust anchor, one has to set the server.trust-anchor-file setting to the path to the trust anchor file

server:
    trust-anchor-file: /etc/trust-key.key

To enable DNSSEC validation and use a self-managed (RFC5011) trust anchor, one has to set the server.auto-trust-anchor-file setting to the path to an initial trust anchor file

server:
    auto-trust-anchor-file: /etc/trust-key.key

An initial trust anchor file can be generated using the unbound-anchor tool.

More details about auto-trust-anchor-file and unbound-anchor can be found in https://nlnetlabs.nl/documentation/unbound/howto-anchor/

In both cases, the syntax of the trust anchor file is a newline-separated list of DNS records:

.	86400	IN	DNSKEY	257 3 7 (.. omitted base64-encoded data ..)
.	86400	IN	DNSKEY	256 3 7 (.. omitted base64-encoded data ..)

BIND (named)

named's configuration syntax is more complex. In the named.conf file, DNSSEC validation can be enabled / disabled using the options.dnssec-validation option:

options {
     dnssec-validation auto;
}

The trust anchor is configured in the file /etc/bind/bind.keys, which uses BIND-specific syntax instead of the DNS record syntax.

trust-anchors {
  . static-key 257 3 7 "(.. omitted base64-encoded data ..)";
  . static-key 256 3 7 "(.. omitted base64-encoded data ..)";
};

The static-key column indicates whether the key is externally managed (static-key) or managed according to RFC5011 (initial-key).

Current state

The recursive resolver component is enabled and configured using a [[zones]] section that looks like this:

[[zones]]
zone = "."
zone_type = "Hint"
stores = { type = "recursor", roots = "/tmp/root.hints" }

Where the stores entry corresponds to RecursiveConfig when type is recursor.

Proposal

Although hickory-dns configuration file is modeled after (BIND) named's configuration file, I would propose using a configuration syntax closer to unbound's. Namely, adding these two fields to RecursiveConfig

pub struct RecursiveConfig {
    pub roots: PathBuf,
    pub ns_cache_size: usize,
    pub record_cache_size: usize,
    /// Path to trust anchor file
    pub trust_anchor_file: Option<PathBuf>,
    /// Whether to manage the trust anchor file using RFC5011 or not (default: false)
    pub rfc5011: bool,
}
trust_anchor_file rfc5011 DNSSEC validation
None _ No
Some(_) false Yes, trust_anchor_file is static key
Some(_) true Yes, use RFC5011; trust_anchor_file is initial key

The syntax of the trust anchor file will be a newline-separated list of DNS records, either DS or DNSKEY records

This proposal can be implemented incrementally. We can add only trust_anchor_file first and only support static keys. We can then add rfc5011 when RFC5011 is implemented (if we want to implement it).

Alternatives

If we foresee supporting different trust anchor management strategies we could use a single enum field instead of an extra boolean field. Something like this:

pub struct RecursiveConfig {
    pub roots: PathBuf,
    pub ns_cache_size: usize,
    pub record_cache_size: usize,
    pub dnssec_validation: DnssecValidation,
}

#[non_exhaustive]
pub enum DnssecValidation {
    Disabled,
    // RFC5011
    InitialKey { file: PathBuf },
    // externally-managed key
    StaticKey { file: PathBuf },

    // .. other strategies ..
}
@djc
Copy link
Collaborator

djc commented Apr 24, 2024

How does DnssecValidation get represented in TOML? I like that the enum approach is more explicit.

@japaric
Copy link
Author

japaric commented Apr 24, 2024

to use an enum with serde/toml we need to give pick a name for the tag field that will hold the enum variant name.

if we give the tag the name "mode" then the TOML would look like this

stores = {
    type = "recursor"
    roots = "/etc/root.hints",

    dnssec_validation = { 
        mode = "Disabled"
    }
    # Or
    dnssec_validation = { 
        mode = "InitialKey",
        file = "/etc/trusted.key"
    }
    # Or
    dnssec_validation = { 
        mode = "StaticKey",
        file = "/etc/trusted.key"
    }
}

@djc
Copy link
Collaborator

djc commented Apr 25, 2024

That looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants