PowerDNS / pdns

PowerDNS Authoritative, PowerDNS Recursor, dnsdist
https://www.powerdns.com/
GNU General Public License v2.0
3.47k stars 885 forks source link

Auth (DNSSEC): a "hybrid" signing mode for serving RRSIG #14372

Open d-wibowo opened 1 week ago

d-wibowo commented 1 week ago

Short description

A hybrid signing mode for a particular zone, where certain record types can be pre-signed while other types can be signed directly by PDNS.

Usecase

A mode where signatures of DNSKEY record types are provided by the backend pre-signed, while other record types are still signed directly by PDNS Auth by providing it the ZSK's private key.

Description

When using PDNS Auth's online signing mode, we can provide PDNS Auth with the private keys of ZSK and/or KSK. If we provide both KSK and ZSK, PDNS Auth will sign DNSKEY record with KSK while the other record types with ZSK; however, without providing the KSK (only the ZSK), PDNS Auth will also sign the DNSKEY record type with the ZSK.

We are currently in a situation where our KSK's private key must be held by a certain KMS Service outside of our control. In this arrangement, we only have access to the KSK's public key and also a Sign method provided by the KMS; so we can still pre-sign the DNSKEY records before storing it in our backend. With this scenario in mind, the only option that we have is to use the pre-signed mode since we cannot provide the private key of our KSK to PDNS Auth.

We do manage the ZSK ourselves though, so we do have access to its private key. Technically with this, we can use the online signing mode, however, this will mean that we are not going to be utilising our KSK for the signing of the DNSKEY records, and we are not going to be using the pre-signed DNSKEY signatures generated from the KMS.

What we are proposing is some sort of hybrid mode between online signing and pre-signed.

The way we envisioned it is having DNSKEY signatures as pre-signed records provided by the backend, while for signatures of record types other than DNSKEY will be signed online by PDNS. This way, us that do not have access to the KSK's private key but still retain control over the ZSK, would still be able to take advantage of PDNS Auth's online signing mode, while allowing ourselves the option of having the DNSKEY signatures pre-signed by an external KMS.

Habbie commented 5 days ago

Can you check if https://doc.powerdns.com/authoritative/settings.html?highlight=direct%20dnskey#direct-dnskey helps your situation?

d-wibowo commented 1 day ago

Hi @Habbie, thanks for the reply 😺

I've checked out the direct-dnskey config and unfortunately, I don't think it would be able to help with our situation.

Do correct my understanding on direct-dnskey if I am mistaken; when disabled, PDNS Auth would effectively generate DNSKEY records by deriving it from the private keys (of ZSKs / KSKs) gathered by calling the backend (in my case I was using remote-backend and they called the GetDomainKeys function). However, when the config is enabled, PDNS Auth would not try to generate / construct the DNSKEY records by itself, rather it will query the backend for any available DNSKEY records and return it as such.

While it is definitely closer to something that we were hoping to be achieved, I do not think it is sufficient for our case.

Just to give an overview of what we had tried.

Setup:

  1. PDNS Auth with remote backend and online-signing enabled
  2. The GetDomainKeys function returns the private key for a ZSK
  3. The Lookup function for DNSKEY record types return the DNSKEY records of both ZSK and KSK

When direct-dnskey Disabled:

  1. Resolving for type DNSKEY only returns 1 DNSKEY record representing the ZSK
  2. PDNS Auth signs the DNSKEY RRSET with the ZSK

When direct-dnskey Enabled:

  1. Resolving for type DNSKEY returns 2 DNSKEY records representing the ZSK and KSK
  2. PDNS Auth signs the DNSKEY RRSET with ZSK

The problem that we have with either approach is that both ultimately uses the ZSK's private key to sign the DNSKEY RRSET, which we want to avoid.

What we had in mind goes on something like the following (using remote backend again just as an example)

Suppose we have a setup:

  1. PDNS Auth with remote backend
  2. We have the zone example.com on the backend, with records of type A , DNSKEY and RRSIG
  3. The DNSKEY RRSET has ZSK and KSK records
  4. The RRSIG record is the signature of the DNSKEY RRSET (presigned)
  5. The GetDomainKeys function return the private key of the ZSK

When resolving for example.com DNSKEY:

  1. PDNS Auth would do a lookup to the backend for the DNSKEY records and return the RRSET containing both ZSK and KSK (this is something that is achievable using the direct-dnskey config before)
  2. PDNS Auth would do a lookup to the backend for the presigned RRSIG of the DNSKEY RRSET
  3. It would effectively be processing DNSKEY record types in presigned mode

When resolving example.com A:

  1. Auth would do a lookup to the backend for the A record and return its corresponding value
  2. Auth would get the private key of the ZSK from the backend (via GetDomainKeys) and signs the response RRSET
  3. Here, Auth would effectively be running in online signing mode

In short, for a single zone, its DNSKEY record is treated as in presigned mode while its other types are treated as in online signing mode.

Let me know if you have any other questions. I am not sure if PDNS supports this currently since I haven't found any mention on the docs regarding this kind of setup.

cheers..

Habbie commented 1 day ago

However, when the config is enabled, PDNS Auth would not try to generate / construct the DNSKEY records by itself, rather it will query the backend for any available DNSKEY records and return it as such.

It should be doing both when enabled.

Habbie commented 1 day ago

PDNS Auth would do a lookup to the backend for the presigned RRSIG of the DNSKEY RRSET

right. I wonder if we could/should expand direct-dnskey to do this.

d-wibowo commented 12 hours ago

Interesting. Now that you mentioned it, it does sound similar to the way direct-dnskey works; maybe direct-dnskey could be expanded to cover the case when a DNSKEY signature was presigned.

Or, it might also be possible to have some sort of new configuration, something like direct-rrsig, where similar to direct-dnskey, if auth wasn't able to get the desired presigned RRSIG records from the backend, it will try to generate RRSIG by itself through online signing mode. This way, it wouldn't only be limited to DNSKEY records only. Though i'm not that familiar with the pdns code, so i'm not sure how great of an effort would be required to implement something like this.