mirror of
https://github.com/acme-dns/acme-dns.git
synced 2026-04-27 12:55:48 +03:00
[GH-ISSUE #76] Raise the cap for TXT records per subdomain #30
Labels
No labels
Documentation
Documentation
bug
enhancement
feature request
feature request
help wanted
pull-request
question
security
security
testing
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/acme-dns#30
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @rmbolger on GitHub (Apr 28, 2018).
Original GitHub issue: https://github.com/acme-dns/acme-dns/issues/76
I recently released a new PowerShell based ACMEv2 client, Posh-ACME. It supports a DNS challenge plugin system and I was all ready to write a plugin for acme-dns after reading a bit about it. But after digging deeper into how it works, I realized that its usage model isn't really compatible with how my client's DNS challenge processing works.
My client currently tries to publish all required TXT records for a given certificate before sending the validation requests to the ACME server. And if I understand how the 2 record cap in acme-dns works, it means that a SAN cert with more than two names will never be properly validated. As soon as the 3rd record gets added, the oldest one is overwritten and its validation will ultimately fail.
Let's Encrypt's current rate limits enforce a maximum of 100 names per certificate. So raising the acme-dns cap to 100 before rolling over seems like the simplest way to successfully validate a single cert with the maximum 100 names.
Also, since acme-dns seems to be more of a fire-and-forget publishing model rather than add-and-remove, it might also make sense to add what is basically a TTL on the records that get published. Not an actual DNS TTL, but like a database TTL. When the records "expire", they're automatically removed.
I haven't had a chance to look at acme-dns's code yet. So I have no idea what a suggestion like this might take to implement. But does it seem doable?
@rmbolger commented on GitHub (Apr 28, 2018):
The related issue on my own project is rmbolger/Posh-ACME#1
@sahsanu commented on GitHub (Apr 28, 2018):
Hi @rmbolger,
You are correct, but keep in mind that you should register an entry in acme-dns per domain/subdomain so you should never reach the limit of 2 TXT per registration and the 2 TXT records are there only in case you want to issue a cert covering
*.example.organd base domainexample.orgbecause both should use the same_acme-challenge.example.org TXTrecord to validate the challenge.It won't work, Let's Encrypt will ignore DNS answers above 4096 bytes so 100 TXT records for a single entry like
_acme-challenge.example.orgwon't validate your domains because the DNS answer size limit.Cheers,
sahsanu
@rmbolger commented on GitHub (Apr 28, 2018):
I can see how that is the intended use. But that makes it way worse from a usability standpoint because then a potential user not only has to register a whole bunch of times and maintain a bunch of different credentials for the generated subdomains. They also have to provide all those separate sets of info to the ACME client. Imagine how tedious that would get if you're managing certs with large SAN counts.
I really want this to work. But that's a really hard sell to a potential user.
I wasn't aware of this limitation. Do you know if it's documented anywhere? I'm curious if it's a weird Go limitation like it not being able to get TCP DNS responses? Or is it something purposefully enforced by Boulder as a form of DOS protection?
Regardless, 4096 bytes can still hold quite a few TXT records. I just did some wireshark captures and with each TXT record being 43 characters, it looks like you can fit around 72 records within a 4096 byte response give or take variations in the query parameters.
@sahsanu commented on GitHub (Apr 28, 2018):
Sorry, I don't know where it is documented but this is the issue where boulder was modified a couple of months ago to accept BIG DNS responses (4096 bytes) https://github.com/letsencrypt/boulder/pull/3467
I've tested it and in my case it would fit 62 records but again, it won't cover all the domains allowed per cert and I think too many TXT records per _acme-challenge.domain is not very efficient from a DNS perspective.
@joohoi commented on GitHub (Apr 28, 2018):
This is the part which should be automated. I'm going to describe my view of optimal setup, much of what is already implemented in the authentication hook for Certbot: https://github.com/joohoi/acme-dns-certbot-joohoi
CNAMErecords to the main zones of the respective domain names.With a flow like this, the only thing the end user will see, is a prompt to create the
CNAMErecords, which would be mandatory anyway when using acme-dns. If the client needs to support only one or a small set of external DNS APIs, it should be rather easy to include theCNAMEcreation within the client too. The client would then be using user provided external API credentials, which would be only used during runtime to create theCNAMErecords, and would not be saved on the host.@rmbolger commented on GitHub (Apr 28, 2018):
You're right if we were talking about long lived records that are being queried by general Internet traffic on a regular basis. But this is a highly specific record only intended to be queried by an ACME server during issuance and renewal every 60 days or so. For someone who is hosting this server along with other more traditional web traffic. The additional transfer overhead seems like it would be negligible.
Don't you see how that workflow is dramatically different than a typical DNS provider though?
Even if we accept that every DNS name in a cert should have its own acme-dns subdomain, I feel like separating the account registration from the subdomain creation would be much more efficient. So a single account/registration could create multiple subdomains. Or to keep things backwards compatible, you could even make the existing registration endpoint optionally accept a username/password and use those rather than generating new ones. That would effectively accomplish the same goal of 1 username/password for multiple subdomains.
@joohoi commented on GitHub (Apr 29, 2018):
I'll start by saying that I do see the convenience benefits in this feature request. At the same time I have some concerns about the effects it would have across the board and I'm trying to describe them below for you to see where I'm coming from.
In general, the issues I'm seeing with the multiple TXT records in acme-dns are:
Making concept harder to grasp and choices possibly degrading security model
There would be a few cases where, if having multiple subdomains using the same credentials would degrade the security. An example would be an infrastructure where you'd have a server hosting multiple domains, for web for example and this certificate would have multiple names. One of these names needs a certificate on another box. If multiple subdomains would have a single set of credentials in this scenario, the only way to manage such environment would be to share these credentials to the box needing only one of the names, thus giving it credentials to issue certificates for all these other names in the first one.
Wording this kind of security considerations for users in a way that would actually get understood is really hard, and makes the concept even harder to get familiar with, unfortunately. I wish to have word "except" used as little as possible.
Yes, I do, and this is intentional. The typical DNS providers have issues in this exact behavior that acme-dns is trying to address. I wrote more about these issues in a blog post. It's a rather long, I'll apologize in advance ;) Acme-dns is not your typical DNS provider for these reasons.
My view on this is that the client needs to have a way to store and retrieve actual domain to acme-dns subdomain mapping, and username-password combination. Having different user names and passwords for them wouldn't make much difference.
So to recap; while I certainly see the added convenience in some use cases, I feel that the down sides of such implementation would outweigh the benefits unfortunately.
@rmbolger commented on GitHub (Apr 29, 2018):
To be honest, I've kind of given up on the original request for raising the maximum TXT record cap. The Boulder 4096 limitation and the variable nature of how many records can fit within the limit make it too unpredictable to rely on as a feature.
But I still think allowing multiple subdomains to share a single set of credentials would be a worthwhile addition. I'd be happy to open a new issue for it unless you don't think it's worth it.
I respectfully disagree about degrading the security model. If I understand your hypothetical situation correctly, you basically have two different web servers with the following config.
Let's assume an attacker has taken control of Web2. It is true that they could use Cred1 to make changes against Sub1-4. But first they need to know what those subdomains are. And since subdomains are randomly generated and there's no way to ask acme-dns for a list, there's no guaranteed way for the attacker to know what other subdomains are associated with Cred1 unless he also takes control of Web1. But in that case, those subdomains would still be compromised even if they weren't sharing the same Cred1.
I'm probably forgetting some obvious workaround because it's late here and I'm tired. But you also have the IP whitelisting feature as a backup security measure. If you're paranoid about shared credential compromise, just limit updates for Sub1-4 to Web1's IP.
@joohoi commented on GitHub (Apr 29, 2018):
We could change the title of this issue to keep the discussion intact while still pointing to the resulting feature request. I'm not ready to implement this feature yet, as I still think that down sides outweigh the potential benefits. I'm open for discussion however, and if there's more demand for this we should see how to implement it in a way that doesn't sacrifice other benefits of this project.
It's rather easy to manage by monitoring Certificate Transparency logs. A simple search using https://crt.sh/ would reveal the certificate on Web1, and DNS queries for
_acme-challenge.Name#would reveal that they all point to a single acme-dns instance. If there would be a feature to reuse username - password pair, that would be a low hanging fruit obviously tested by the attacker.This is true, but only in the case of IP whitelisting becoming a member of subdomain object (as the credentials would be separate), which again could potentially confuse users.
@rmbolger commented on GitHub (Apr 29, 2018):
You're right. Totally forgot that was a thing now. I stand corrected. Seems like I just have to suck it up and deal with the architecture as-is. I truly appreciate the discussion though.
There's a semi-related tangent I was thinking of with the multiple web servers using the same subdomain situation. What happens if they're all configured to renew at the same time? Would they run into the 2 name cap? Or does Boulder always give the same challenge token for the same name on the same account?
I have one more totally unrelated design decision question. But I'll open a separate issue for that.
@joohoi commented on GitHub (Apr 29, 2018):
If there's two different servers requesting at the exactly same time, I believe they would also have different account key each. In this case the validation would fail. Many clients check the state of the certificates every day or so, and try to renew only if needed, so they would then retry the renewal until they succeed.
The distribution packaging for Certbot for example installs cron jobs / systemd timers that run every 12 hour (with an added random sleep to distribute the renewal tries evenly). In this case one of the servers would eventually get it right and stop trying, letting the other to have full control over the record. In the future the certificates would be expiring on different times, so the race wouldn't be happening again.
@Kraeutergarten commented on GitHub (May 13, 2018):
I run into the same Issue. Have some SAN-Certs with 9-10 Domains.
@joohoi commented on GitHub (May 15, 2018):
Which client are you using? The discussion in this issue goes into detail why I think it's bad to use a single set of credentials for every domain in a certificate. I feel that due to the automated nature of the tooling, this should be handled on the client side, preferably transparently.
@joohoi commented on GitHub (Aug 12, 2018):
Closing the issue.