joohoi / acme-dns

Limited DNS server with RESTful HTTP API to handle ACME DNS challenges easily and securely.
MIT License
2.19k stars 234 forks source link

How do you bootstrap when you have a split-DNS? #354

Closed gctwnl closed 5 months ago

gctwnl commented 5 months ago

[Update: this is a dumb question. Ignore]

I need to get the acme-dns server running locally, on a server that is already running an instance of my split-DNS (so 53 is not available).

Outside public DNS for mydomain.tld:

acmedns     IN    NS   usedname.mydomain.tld
usedname    IN    A    100.11.12.13
linuxserver IN    A    100.11.12.14

Inside private DNS for mydomain.tld:

linuxserver IN    A    192.168.10.10

acme-dns is running as a container via docker compose, with this:

    ports:
      - "943:443"
      - "953:53"
      - "953:53/udp"
      - "980:80"

It starts fine:

acmedns-1  | time="2024-06-08T12:46:06Z" level=info msg="Using config file" file=/etc/acme-dns/config.cfg
acmedns-1  | time="2024-06-08T12:46:06Z" level=info msg="Connected to database"
acmedns-1  | time="2024-06-08T12:46:06Z" level=debug msg="Adding new record to domain" domain=vanroodewierda.rna.nl. recordtype=A
acmedns-1  | time="2024-06-08T12:46:06Z" level=debug msg="Adding new record to domain" domain=acmedns.rna.nl. recordtype=NS
acmedns-1  | time="2024-06-08T12:46:06Z" level=debug msg="Adding new record to domain" domain=acmedns.rna.nl. recordtype=SOA
acmedns-1  | time="2024-06-08T12:46:06Z" level=info msg="Listening HTTPS" domain=acmedns.rna.nl host="0.0.0.0:443"
acmedns-1  | time="2024-06-08T12:46:06Z" level=info msg="Listening DNS" addr="0.0.0.0:53" proto=udp
acmedns-1  | time="2024-06-08T12:46:06Z" level=info msg="Listening DNS" addr="0.0.0.0:53" proto=tcp

NAT is like

100.11.12.13:53 -> 192.168.10.10:953

From the outside, my acme-dns is reachable:

nc -v -z -u usedname.mydomain.tld 53
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to k.l.m.n:53.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.01 seconds.

From the inside as well:

nc -v -z -u linuxserver.mydomain.tld 953
Connection to linuxserver port 953 [udp/*] succeeded!

Now, when on the inside I try to register, I get

root@linuxserver:/srv/docker/nameserver# curl -X POST https://linuxserver.mydomain.tld:943/register
curl: (35) error:0A000438:SSL routines::tlsv1 alert internal error

and the log says:

acmedns-1  | time="2024-06-08T12:47:43Z" level=info msg="http: TLS handshake error from 192.168.10.10:53822: no certificate available for 'linuxserver.mydomain.tld'"

My config is a mess, of course, because I don't understand this all very well.

# domain name to serve the requests off of
domain = "acmedns.mydomain.tld"
# zone name server
nsname = "usedname.mydomain.tld"
# admin email address, where @ is substituted with .
nsadmin = "hostmaster.mydomain.tld"
# predefined records served in addition to the TXT
records = [
    # domain pointing to the public IP of your acme-dns server 
    "usedname.rna.nl. A 100.11.12.13",
    # specify that auth.example.org will resolve any *.auth.example.org records
    "acmedns.mydomain.tld. NS usedname.mydomain.tld.",
]

Is there a way to get the acme-dns running self-hosted in this situation?

gctwnl commented 5 months ago

I worked around it by copying a valid cert over from another machine and setting

# possible values: "letsencrypt", "letsencryptstaging", "cert", "none"
tls = "cert"
# only used if tls = "cert"
tls_cert_privkey = "/etc/letsencrypt/live/mydomain.tld/privkey.pem"
tls_cert_fullchain = "/etc/letsencrypt/live/mydomain.tld/fullchain.pem"

That is of course not a real solution.

gctwnl commented 5 months ago

I can now successfully use the API, but not entirely:

% curl -X POST https://linuxserver.mydomain.tld:943/update -H "X-Api-User: <snip>" -H "X-Api-Key: <snip>" --data '{"subdomain": "<snip>", "txt": "___validation_token_recieved_from_the_ca___"}'| python3 -m json.tool
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   161  100    54  100   107    688   1364 --:--:-- --:--:-- --:--:--  2064
{
    "txt": "___validation_token_recieved_from_the_ca___"
}

That is a call on the inside. 443 is not available from outside (no NAT). The log says:

acmedns-1  | time="2024-06-08T16:06:57Z" level=info msg="  Actual request no headers added: missing origin"
acmedns-1  | time="2024-06-08T16:06:57Z" level=debug msg="TXT updated" subdomain=<snip> txt=___validation_token_recieved_from_the_ca___

But when I try to read this from the outside:

$ dig _acme-challenge.acmedns.mydomain.tld txt

; <<>> DiG 9.11.36-RedHat-9.11.36-14.el8_10 <<>> _acme-challenge.acmedns.mydomain.tld txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42965
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 327e502452512e255ca948b766647f7248f5c0f8d3a99f53 (good)
;; QUESTION SECTION:
;_acme-challenge.acmedns.mydomain.tld.  IN  TXT

;; ANSWER SECTION:
_acme-challenge.acmedns.mydomain.tld.   1 IN    TXT ""

;; AUTHORITY SECTION:
acmedns.mydomain.tld.       207 IN  NS  usedname.mydomain.tld.

;; Query time: 37 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat Jun 08 17:57:38 CEST 2024
;; MSG SIZE  rcvd: 129

So, almost there?

gctwnl commented 5 months ago

Never mind @joohoi, it was in part a dumb question (there is a 'none' option).

gctwnl commented 5 months ago

Never mind, the error was mine (no surprise here). I had CNAME'd _acme-challenge.acmedns.mydomain.tld to <acme-dns-subdomain>.acmedns.mydomain.tld but I should have CNAME'd _acme-challenge.mydomain.tld of course because that is where LE CA will look... 😬 Now just see if I can get it working in full.

So, probably the bootstrap would have worked too, maybe. I'll probably check later.

gctwnl commented 5 months ago

This was (as least in part) a dumb question.