[Suggestion] Let's Encrypt operated, TXT-only DNS Hosting for DNS challenges

Hello,

Summary
Let’s Encrypt should host and provide access to a TXT-only DNS zone (e.g. acme-dns.net), which will provide stable TXT names, to which domains using Let’s Encrypt can CNAME alias their _acme-challenge records.

ACME clients will be able to call an API to update these TXT records, authenticated by their ACME Account Key Pair, that will allow successful and simplified use of the ACME DNS challenge.

Before/Now: We have to interact with our DNS Host every time we renew/issue a certificate.
After: We delegate authority of _acme-challenge labels from the DNS Host over to acme-dns.net as a once-off manual action, and then never worry about it again.

Background
The focus of the ACME DNS challenge has increased recently:

  1. TLS-SNI challenge is gone, meaning that clients that can’t use the ACME HTTP challenge are now reliant on it.
  2. Upcoming Let’s Encrypt wildcard support is reliant on it.

However, its usability is very poor, for a number of reasons:

  1. Clients choose a smattering of DNS hosts to support with their ACME DNS challenge support. Even projects like Lexicon are missing notable providers.
  2. The ability to automate/drive the DNS management of zones across providers is extremely spotty. There are many issues, from not supporting an API at all, to having wildly broad APIs that create a dangerous situation where ACME clients have too much privilege (in which @schoen points out the solution this idea uses) .
  3. Certbot has dependency/distribution issues, which makes it really hard to distribute plugins across all platforms.

Based on threads I’ve been reading/answering on these forums (where too often the fallback advice is: “you’ll need to implement an auth hook”), this seems like a major problem.

Idea
Let’s Encrypt would register a domain, such as acme-dns.net.

Let’s Encrypt would operate nameservers to serve this zone to the internet.

Let’s Encrypt would provide an API (“ACME DNS”), authenticated by the ACME Account Key Pair.

ACME DNS would permit registration of stable TXT names ONLY within the zone. e.g. {random-128bit-base64url}.acme-dns.net.

ACME DNS would permit update of TXT RDATA.

Domain owners would delegate authority of _acme-challenge. names to ACME DNS via CNAME, minimizing the interaction with the DNS Host to a single event, rather than having to do it repeatedly. This also means that the interaction with the DNS Host no longer needs to be automated.

ACME Clients (e.g. Certbot) would optionally act as a client to ACME DNS while performing ACME DNS challenges, providing the user with a set of instructions (e.g. for example.org):

  1. (If not already mapped previously, otherwise re-use) Automatically create new ACME DNS TXT name (e.g. z2vkagf1y2fwdao.acme-dns.net).
  2. (If not already mapped previously, otherwise re-use) Prompt user to create CNAME record for _acme-challenge.example.org to z2vkagf1y2fwdao.acme-dns.net).
  3. Confirm mapping of _acme-challenge.example.org to known ACME DNS TXT name.
  4. Proceed with ACME DNS challenge, but instead of requiring manual intervention or use of hook scripts, update mapped ACME DNS TXT record(s) using ACME DNS API.

Example
I am a Let’s Encrypt client.

I have a domain, example.org. It has its DNS hosted with a provider that does not have an API.

I run:

certbot certonly --dns-acme -d "*.example.org" -d "*.foo.example.org"

I do not need to download certbot-dns-acme because it is built into Certbot, as well as every other ACME client.

I am prompted to create _acme-challenge.example.org IN CNAME q3lks2fpy2tldgo.acme-dns.net.
I am prompted to create _acme-challenge.foo.example.org IN CNAME cgl1a3nvz3dhzwo.acme-dns.net.

I complete these tasks and continue. Certificates are issued.

+89 days, I go for renewal. Renewal happens non-interactively. I am not reliant on my DNS host to do anything except not delete the CNAME records.

Benefits

  • Significantly simplified renewal story for ACME DNS Challenge
    • All ACME clients can implement a single, lowest common denominator DNS challenge
    • End-user only has to create a CNAME once per name, rather than updating a record once per issuance/renewal.
    • Interaction with DNS Host is minimized to a once-off, manual event. Significantly reduces size and scope of all ACME client code.
  • Does not break the ACME spec or the CAB/F BRs. Still works within the assumptions of the ACME DNS Challenge while cutting out the complexity.
  • No need to trust more parties than already trusted
  • Avoiding exposing additional and potentially dangerous domain registrar/DNS hosting credentials to the client environment.
  • Re-using existing authentication model of ACME.

Risks

  • More servers and CDN services, staff time required from Let’s Encrypt.
  • Some kind of misuse of the zone? Being able to put rate limits against account keys/IPs and the fact that it only serves TXT records should mitigate this, though.

Why should Let’s Encrypt run this?
I was going to implement this myself and provide the service for free as acme-dns.net.

However, why would anybody trust me with the delegation of their _acme-challenge records? It creates a situation where I can fraudulently issue certificates for reliant domains.

If Let’s Encrypt runs this, all questions of trust are gone, and provides the opportunity to re-use the existing authentication mechanism of the ACME Account Key Pair.

Here’s the thing - I think this can only work with the trustworthiness of a major organisation behind it. I am fully willing to build it and run it myself, but the fact of me having to operationalize it would kill it, at least in my mind, for widespread use.

Thanks for reading …

4 Likes

sometimes it seems the ppl think that LE has unlimited budget for their infrastructure. Why don’t you pay for this and make it public accessible for everyone and after development is done you give admin pass and sourcecode to LE, while keep paying for the infrastructure.
Thank you

When you have to set a static record only (and the non-static record is set by LE to be validated by LE), isn’t it the same as if the dns-challenge uses static records only? Maybe static records are allowed in the near future, for example for dnssec-secured domains? Then the corresponding RRSIG-record is the non-static part of the validation.

For what it's worth, @joohoi's acme-dns software is designed for running exactly this sort of service.

joohoi used to run a public instance too, but phased it out.

Edit:

Morally, kind of. From a regulatory standpoint, it seems to be acceptable. A number of CAs have similar DNS validation methods.

Something like, the CA tells you to create a record like "cca8e1a1b1f7132951078e4dc75f153e.example.com. CNAME 6067a5e6c24842b53a25f595dba81ca4.validation.some-ca.com.".

I guess the important thing is that the DNS query returns a random record, and the use of static CNAMEs, or the question of who's operating the DNS servers, aren't a factor.

5 Likes

Cool, hadn't seen this somehow.

I guess the other half of this is solving both the trustworthiness and reliability problems. Namely:

  • Don't want the owner/operator of acme-dns to be able to issue certificates for delegated domains (unless I had a reason to trust them e.g. they are Let's Encrypt)
  • Don't want to cause a scenario where e.g. auth.acme-dns.io goes offline, leaving all of its users scratching their heads

It would be ideal for the entire thing to be encapsulated by the CA, but I'm sure there's other opportunities here.

For trustworthiness, if the account-uri CAA extension does land in Boulder (draft-ietf-acme-caa-03), it would allow delegation of the _acme-challenge into untrusted zones without compromising the entire zone itself. However, I know that many DNS registrars/hosts still do not support CAA records and it still creates an extra step for end-users - avoiding both of these is an explicit goal of this idea.

For reliability (in the case that the CA does not want to run it), it may be better to use e.g. Cloudflare or Route53 or other major DNS provider as the backing nameserver for the ACME DNS zone rather than serving it from the API endpoint, as this would outsource the problem of DDoS protection and probably significantly reduce operational cost, without comprimising on trustworthiness too much.

I believe that ACME validations are remembered for at most 30 days. The TXT rdata of the name pointed to by the CNAME still needs to be updated at renewal time, so in this way it is not actually static. What is static is the delegation of authority over these records to ACME DNS.

As I mentioned, fully willing to, especially if CAA account-uri ends up implemented in Boulder. As of today there is no way to build it in a way that does not compromise safety of domains.

This is a cool idea! And yeah, as @mnordhoff pointed out, @joohoi has already done some work in this direction. Your intuition that we won’t have time to work on it soon is accurate, but I’d be interested in exploring this idea in more detail. For instance, how would the ACMEDNS authenticate clients? Using the same accounts and signing protocol as ACME would be pretty convenient. But how would ACMEDNS decide who is allowed to upload which records? I think that essentially requires the ACMEDNS server to do a domain validation process, which creates a chicken-and-egg problem.

Another idea I’ve been kicking around, very similar to @joohoi’s work, is for an ACME client to run its own authoritative resolver for challenges, and delegate _acme-challenge.example.com to the ACME client via NS records.

2 Likes

I guess you could allow anyone to request any name, without validation, and then rely on them setting _acme-challenge.www.example.com. CNAME a8b0f4e8854aecdc7c5725c590eb164c.acme-dns.letsencrypt.org. or whatever correctly.

I’m pretty sure that wouldn’t cause any new security problems but don’t quote me on it. :stuck_out_tongue_winking_eye:

To expand on that: The idea would be you'd claim the name once, before setting the CNAME, and then no-one else would be able to claim that name ever?

Maybe it would be better to say: Register your ACME account. You get an account ID, say 1234, then your portion of the acme-dns namespace would be 1234.acme-dns.letsencrypt.org. That way we would use the unique identifier space we already have, the names are shorter, and the fact that the CNAME is essentially authorizing a given ACME account to issue for your domain becomes clearer.

More or less. You don’t have to stop other people from trying to claim the name, since it’s harmless if they can’t modify/poison the _acme-challenge CNAME.

That makes sense, I think.

Would also make it easy to allow people to have multiple servers issue certificates for the same name, as long as they share ACME accounts. And, conversely, make it impossible without sharing ACME accounts, but a hosted DNS service doesn’t have to cover every use case.

I have no idea how compatible any of this is with the BRs. :stuck_out_tongue: Third-party ACME DNS hosting isn’t required to be designed particularly sensibly, but anything CA-operated probably does (and probably should) fall under regulations… :confused:

1 Like

It's actually critical to stop others from claiming the name, because the expectation is that _acme-challenge.example.com CNAME abc123def.acmedns.net would remain in place in the long term. If a third party could upload resource records for abc123def.acmedns.net, they could answer challenges from example.com.

I'm pretty sure this would all be BR-compatible, though I'd want to give them another close read to be sure. There was some discussion on the CA/Browser Forum mailing list around the CAA vote that discussed an exception for when the CA runs the DNS service for someone, so presumably some variant of "your CA runs your DNS" is already out there. Running a full DNS service would certainly be out of scope for Let's Encrypt, but this smaller subset could be interesting.

You’re right.

I thought you meant "only one person can register to use the ACME DNS service for www.example.com". And I meant that, as long as different people get different abc123def.acmedns.net CNAMEs – e.g. the first person gets “abc.acmedns.net” and the second person gets “def.acmedns.net” (attempted) registration doesn’t have to be validated or limited.

Edit: Is discussing what, if anything, other CAs do in this area a legal or CABF issue?

Not totaly clear on why ACMEDNS would need to perform domain validation.

My envisioned flow is that ACMEDNS would allow an ACME Account to request a name within the acme-dns.net zone, and ACMEDNS would generate {random}.acme-dns.net and permanently remember that only that ACME Account Key Pair may update it.

It is then up to the user to delegate their _acme-challenge. labels to the ACMEDNS name, and the ACME Client will instruct the user to do so.

At this stage, the only way for an illegitimate party to misuse the ACMEDNS Name would be compromise of the ACME Account Key Pair, and I believe we already have a framework for dealing with that within ACME. Revocation of the ACME Account Key Pair would also deactivate all the ACMEDNS names under that ACME Account (but they would still remain reserved).

The ACME Client would have to maintain a mapping of (ACME Account, ACMEDNS Name, Validating Domain) to know which ACMEDNS Name to update during issuance.

Even with the alternative you proposed ({account-id}.acme-dns.net) I’m not sure why ACME would need to do any DV.

I thought about this too, but ran into some roadblocks:

  • Opening 53/udp inbound from the internet may not be acceptable in many environments.
  • Issue of users needing to figure out a separate DNS zone purely for ACME purposes.
  • Not sure it is sufficiently simple. If hosts sit behind NAT/load balancer things really get complicated.

You're correct, and @mnordhoff also helped convince me that this is not necessary. All that's necessary is a unique subdomain assigned per-account. I had been thinking in terms of _acme-challenge.example.net CNAME example.net.acmedns.net.

This is true, although I think in a lot of environments it's fine. If we can get a solution that works in most cases, it's probably okay to ask people with NAT or firewall issues to do a bit of extra setup work. Though, as you point out, it may be tricky to notice that that's the actual problem. :slight_smile:

This may be me revealing my DNS ignorance, but isn't it sufficient to put a _acme-challenge.example.com NS ns1.acmedns.net record in your zone for example.com?

Not necessarily -- client could ask the ACME DNS API server. For that matter, the client doesn't routinely need to know at all. It could just send (account, hostname). It only needs to know the ACME DNS name when telling the user how to set the CNAME record.

You're right, though that would raise the issue of validation again.

It's likely that some limited DNS providers don't allow users to create NS records and delegate subdomains, but many (and hopefully most) do.

Bad idea to avoid validation: Generate a unique ns-abc123def.acmedns.net nameserver name with a unique IPv6 address (2001:db8::a:bc12:3def or whatever). Only answer DNS queries on that IP address. Ergo, validation using someone else's nameserver name/IP would fail.

(IPv4 isn't entirely necessary, since only Let's Encrypt must be able to query it.)

For self-hosted authoritative NS idea, we can’t use acmedns.net, right? e.g.

User issuing a certificate for *.example.org,

User creates acme-challenges.example.org IN A <ip of ACME client>,

User creates _acme-challenge.example.org. IN NS acme-challenges.example.org. (as @mnordhoff mentioned I’m aware of major DNS hosts that don’t allow this kind of subdelegation).

Complete DV process.

I guess it’s not that bad, but carries some complexity (more ways to go wrong). If there are multiple ACME clients on different hosts issuing for example.org, acme-challenges.example.org may actually need to be acme-challenges-{random-base64url}.example.org, since distinct clients will be distinct authoritative nameservers.

We also need to prevent other people on that IP from binding to :53 while the ACME client nameserver is not running. That I really don’t like the sound of.

@_az You’re right. Self-hosted DNS would be a bit complicated for the user to set up, as you say. DNS hosted by Let’s Encrypt would only take one NS record.

We’re talking about a couple different things here. :zipper_mouth_face:

Self-hosted could, under some circumstances, be simpler. You could do:

_acme-challenge.www.example.com.  NS  www.example.com.

That would cover what people need like 90% of the time, when they’re running the ACME client on the same server they need the cert for.

IANAL, but AFAIK it's not. :slight_smile:

Yeah, the issue with ACME-DNS is that it’s not designed around the idea of everyone running their own instances. It’s aimed more towards people or organizations running more complex infrastructure from the get go.

The reason I took acme-dns.io which was running an public test instance down, was that I didn’t want to encourage people pointing their CNAME records towards my instance. I’m not sure how this issue would be best to solve on the large scale, but the sad truth is that the options are rather sparse.

I gave a talk about these issues at a Finnish infosec conference few days ago, and am most likely going to create a blog post about this subject in the coming days.

3 Likes

If anyone on this thread would like to start a discussion on the ACME list, I think that would a good way to get additional input. I agree that the general question of “who runs the validation service” is a tricky one, and that a CA is in a good position to do so because they necessarily have a trusted channel with the subscriber.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.