acme-dns icon indicating copy to clipboard operation
acme-dns copied to clipboard

Base the server's own name on "nsname", not "domain"

Open blkeller opened this issue 4 years ago • 6 comments

Summary:

When nsname and domain in the config are not identical, and the API is set to use Let's Encrypt for its own HTTPS needs, the API is unusable because it gets a cert for the name given in domain, but the API is accessed at nsname. All connections to the API then fail because the API cannot locate its own cert in the filesystem, though the cert would be invalid even if it could be located. Setting the api_domain config variable has no effect because this setting has been deprecated.

This bug is masked whenever nsname == domain, so the problem would not be noticeable in this very common case.

This PR fixes the problem by using nsname instead of domain for the API's Let's Encrypt cert's CN and SAN.

Examples:

Where the config file includes these entries:

[general]
# domain name to serve the requests off of
domain = "certs.mydomain.com"
# zone name server
nsname = "ns1.certs.mydomain.com"

[api]
# possible values: "letsencrypt", "letsencryptstaging", "cert", "none"
tls = "letsencrypt"

Without this patch:

$ sudo ls /var/lib/acme-dns/api-certs/acme/acme-v02.api.letsencrypt.org/sites
certs.mydomain.com

$ sudo openssl x509 -in /var/lib/acme-dns/api-certs/acme/acme-v02.api.letsencrypt.org/sites/certs.mydomain.com/certs.mydomain.com.crt -nocert -subject -ext subjectAltName
subject=CN = certs.mydomain.com
X509v3 Subject Alternative Name:
    DNS:certs.mydomain.com

With this patch:

$ sudo ls /var/lib/acme-dns/api-certs/acme/acme-v02.api.letsencrypt.org/sites
ns1.certs.mydomain.com

$ sudo openssl x509 -in /var/lib/acme-dns/api-certs/acme/acme-v02.api.letsencrypt.org/sites/ns1.certs.mydomain.com/ns1.certs.mydomain.com.crt -nocert -subject -ext subjectAltName
subject=CN = ns1.certs.mydomain.com
X509v3 Subject Alternative Name:
    DNS:ns1.certs.mydomain.com

blkeller avatar Apr 28 '20 01:04 blkeller

Coverage Status

Coverage increased (+0.1%) to 73.233% when pulling 51788ce9fd6ba445649b0102c4d3d3a29cff5bc3 on blkeller:nsname-is-own-name into 68bb6ab654b6fb1fe375e08807688c55621513a2 on joohoi:master.

coveralls avatar Apr 28 '20 01:04 coveralls

It doesn't seem strictly necessary for the API to be accessed at nsname; it could be exposed through any name within the zone that has been delegated to acme-dns. You might want to use a different name for it because then you could do this:

Static records (external):

ns1.magicauth.mydomain.com. A 123.1.1.1  # Public IP for acme-dns. Glue record.
magicauth.mydomain.com. NS ns1.magicauth.mydomain.com.
_acme-challenge.mydomain.com. CNAME __SOME_UUID__.magicauth.mydomain.com. # delegate acme-challenge to within the acme-dns managed zone

Static records (in acme-dns):

ns1.magicauth.mydomain.com. A 123.1.1.1  # Public IP for acme-dns.
magicauth.mydomain.com. NS ns1.magicauth.mydomain.com.
api.magicauth.mydomain.com. A 192.168.100.1  # IP to access the acme-dns HTTP API; not publicly routable (routable within your VPN or whatever)

Dynamic records (challenge responses):

_acme-challenge.api.magicauth.mydomain.com. TXT "... response key for acme-dns's own cert request..."
__SOME_UUID__.magicauth.mydomain.com. TXT "... response key for mydomain.com cert request..."

Edit: If you don't want to expose the private IP of api.magicauth.mydomain.com and if you're running your own DNS resolver within your private network then you could leave it out of the acme-dns static record set and just include it in your private resolver's config somehow. But acme-dns still needs to know at what domain you want to access it, and be able to run DNS-01 challenge-response to get a certificate for itself (which is simplest if the domain you're using to access the API is within the zone that acme-dns is authoritative for, otherwise you need to set up another CNAME record etc).

johnbartholomew avatar Oct 05 '20 19:10 johnbartholomew

@joohoi I merged in the latest master, resolved the merge conflicts, and all of the new GitHub Actions tests are passing. When you have a moment, could you please review?

blkeller avatar Jan 14 '21 00:01 blkeller

This PR fixes the problem by using nsname instead of domain for the API's Let's Encrypt cert's CN and SAN.

I think this is a reasonable request, and indeed it confused me why I wasn't able to do this initially. It would also remove the need to put static A/AAAA records inside the acme zone, and for glue records outside the acme zone.

However, I just wanted to point out that it adds another setup requirement: for acme-dns to be able to fetch a certificate for itself, the user will need to add something to the DNS to allow it to answer its own dns-01 challenge. Either:

_acme-challenge.<nsname>. NS <nsname>.

or for consistency with how acme-dns handles other domains:

_acme-challenge.<nsname>. CNAME something.<domain>.

Then 'something' needs to be defined which doesn't clash with any user domains. It could be empty for this special case.

candlerb avatar Mar 02 '22 11:03 candlerb

FYI this appears to be related to #295

Ajedi32 avatar Mar 03 '22 18:03 Ajedi32