srvrco / getssl

obtain free SSL certificates from letsencrypt ACME server Suitable for automating the process on remote servers.
GNU General Public License v3.0
2.1k stars 378 forks source link

Bug report + Extra variable request #801

Open hytron00 opened 1 year ago

hytron00 commented 1 year ago

Hello,

My setup is like this: Linux Slackware64 version 15.0 (64-bit) Kernel version: 5.10.175 x86_64 Bind DNS server version 9.18.13 Bash version 5.1.16 Getssl V2.48

I have tried to obtain a wildcard certificate from letsencrypt.org however things failed and here are some reasons why they failed: I am using BIND 9 DNS server with multiple views (Split-DNS). That means depending on the source who is requesting the query, answers can be different. When I ran the getssl for *.hytron.org (wildcard certificate), the getssl script found my local DNS and dynamically injected a TXT record with acme challenge. However because the contact with the DNS server was made locally, only the INTERNAL view of the DNS was updated. Letsencrypt cannot see that challenge because Letsencrypt falls in the group EXTERNAL view and when their server requested to see my TXT record, they were unable to see it and of course if failed. I have tried setting the AUTH_DNS_SERVER variable in the getssl.conf but it has no effect. I suggest that you modify the script to do the checking and if the value of AUTH_DNS_SERVER is a non zero value then it should use the value specified as the primary name server over the one it obtains automatically. That way only a particular IP of the DNS server will be queried and proper TXT record will be injected to respond to the right view. Until this is implemented, I may have to see where in the script the DNS name is recorded and hard code the IP of the DNS server that I want to use. Here is and example: My local network is 192.168.22.0/24 My DNS server local IP is 192.168.22.14/24 This same DNS server has a dual homed IP of 192.168.254.14/24. All my local machines are on 192.168.22.0/24. When the query request comes from 192.168.22.0/24, the DNS server responds to INTERNAL view. When the request comes from 192.168.254.0/24 the DNS server responds to EXTERNAL view. (This is how I need to contact my DNS server and perform the TXT challenge update, so I need to manually specify the IP and not use the one that was discovered from the SOA record).

So in other words when I want to update my public (EXTERNAL) view, the request needs to come from 192.168.254.0/24 network. Otherwise there is no way to update the EXTERNAL view and therefore no way to obtain a wildcard certificate when using BIND with views.

The second part is the bug and here it is: Once the request failed, the script terminated and left the TXT record in my DNS server without removing it. Obviously that will not harm anything but why would the record stay there when it should get removed?

Here are some logs:

REQUESTING A CERTIFICATE THAT FAILED:

root@veverica:~/.getssl# getssl .hytron.org .hytron.org: no certificate obtained from host creating key - /root/.getssl/.hytron.org/.hytron.org.key Generating RSA private key, 2048 bit long modulus (2 primes) ..............+++++ ................+++++ e is 65537 (0x010001) creating domain csr - /root/.getssl/.hytron.org/.hytron.org.csr Registering account Verify each domain Verifying .hytron.org checking DNS at ns10.hytron.net sleeping 60 seconds before asking the ACME server to check the dns sending request to ACME server saying we're ready for challenge checking if challenge is complete getssl: .hytron.org:Verify error: "detail": "DNS problem: NXDOMAIN looking u p TXT for _acme-challenge.hytron.org - check that a DNS record exists for this d omain", root@veverica:~/.getssl#

BIND's Dynamic Update log:

25-Mar-2023 03:53:33.465 update: info: client @0x7ff68bfc0b68 2001:470:1f11:4c:: aaaa:54c0#41525: view internal: updating zone 'hytron.org/IN': adding an RR at '_ acme-challenge.hytron.org' TXT "g7YDJ74DqX8Otigz_u5DwPc4EH7vLiyDMXy__xwWoSY"

Yes it used IPv6 network, but considering it is my INTERNAL network it only updated the INTERNAL view (See the log).

CHALLENGE STAYED IN THE DNS:

root@oceana:/etc# dig axfr @192.168.22.14 hytron.org|grep acme hytron.org. 86400 IN NSEC _acme-challenge.hytron.org. NS S OA MX RRSIG NSEC DNSKEY CDS CDNSKEY TYPE65534 _acme-challenge.hytron.org. 86400 IN RRSIG NSEC 13 3 86400 20230406092336 2 0230325065333 1615 hytron.org. GbuQOCYR+VB2QYPFNLl51Qam5VXTrK2x4GTy3Sn4EtQ5cJ5Lv MAKqe7y O67aTbSlWv/LLIckWDgkaDSO1nPr2g== _acme-challenge.hytron.org. 86400 IN NSEC mailx01.hytron.org. TXT RRSIG NS EC _acme-challenge.hytron.org. 300 IN RRSIG TXT 13 3 300 20230406092336 2023 0325065333 1615 hytron.org. B9SDf2ZXNI9ixXF838q/bX4qvQ3hoelZtXJZ0JIItUPFl9HtEOER hab3 jokidRbdyM+Qt6dJUE31T2GobIMtRA== _acme-challenge.hytron.org. 300 IN TXT "g7YDJ74DqX8Otigz_u5DwPc4EH7vLiy DMXy__xwWoSY"

If you need any additional information please let me know.

Thank you!! Darko

agusdomin commented 1 year ago

Hi, same problem here

tlhackque commented 7 months ago

Using the IP address to select views for updates is inadvisable due to forgery issues. Using TSIG is strongly preferred. See the bind documentation.

It appears that you are using dns_scripts/dns_{add,del}_nsupdate. It supports DNS_NSUPDATE_KEYFILE and DNS_NSUPDATE_GETKEY for the TSIG use case.

However, for those who "can't" use TSIG, here's a patch that adds DNS_NSUPDATE_LOCALIP. It takes an IP adddress or IP address & port (space separated). I'll add this to my current PR. You can apply the patch, or use https://github.com/tlhackque/getssl

Note that these variables must be declared with export - e.g. export DNS_NSUPDATE_LOCALIP="192.168.254.123".

nsupdate_localip.patch

With respect to left-over challenge tokens: There are many error exit paths that can cause this.

https://github.com/tlhackque/certtools contains acme_challenge_check, which handles cleanup of a zone. I have a cron job that runs it periodically. You want to schedule it at a time that getssl isn't running. You need to permit acme_challenge_check to do zone transfers (by TSIG or IP address).