Let's Encrypt issues with OPNSense Caddy

1. The problem I’m having:

I am attempting to setup a very simple reverse proxy using the OPNSense Caddy plugin. I have followed the tutorial given by the author (which appears to be out of date) and I am getting errors from Let’s Encrypt. They are claiming that there are no valid A records found for the domain, however I have absolutely set them. I had a Debian based Caddy setup just fine before this, and had not gotten this error.

2. Error messages and/or full log output:

2024-08-07T07:01:15-04:00	Warning	caddy	 "warn","ts":"2024-08-07T11:01:15Z","logger":"admin.api","msg":"exiting; byeee!! 👋"}
2024-08-07T07:01:15-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:01:15Z","logger":"admin.api","msg":"received request","method":"POST","host":"127.0.0.1","uri":"/stop","remote_ip":"","remote_port":"","headers":{"Accept-Encoding":["gzip"],"Content-Length":["0"],"User-Agent":["Go-http-client/1.1"]}}
2024-08-07T07:01:15-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:01:15Z","logger":"tls.cache.maintenance","msg":"stopped background certificate maintenance","cache":"0x87074cd00"}
2024-08-07T07:01:15-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:01:15Z","logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
2024-08-07T07:01:15-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:01:15Z","logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
2024-08-07T07:01:15-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:01:15Z","logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x87074cd00"}
2024-08-07T07:00:53-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"liyue.dead-end.quest","challenge_type":"http-01","ca":"https://acme.zerossl.com/v2/DV90"}
2024-08-07T07:00:53-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme.zerossl.com/v2/DV90/account/ONksIX_GOmcTHzY0RYJnAA","account_contact":["mailto:aidan@aidansmith.dev"]}
2024-08-07T07:00:53-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["liyue.dead-end.quest"],"ca":"https://acme.zerossl.com/v2/DV90","account":"aidan@aidansmith.dev"}
2024-08-07T07:00:53-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["liyue.dead-end.quest"],"ca":"https://acme.zerossl.com/v2/DV90","account":"aidan@aidansmith.dev"}
2024-08-07T07:00:53-04:00	Error	caddy	 "error","ts":"2024-08-07T11:00:53Z","logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"liyue.dead-end.quest","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:dns - no valid A records found for liyue.dead-end.quest; no valid AAAA records found for liyue.dead-end.quest"}
2024-08-07T07:00:53-04:00	Error	caddy	 "error","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"liyue.dead-end.quest","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for liyue.dead-end.quest; no valid AAAA records found for liyue.dead-end.quest","instance":"","subproblems":[]},"order":"https://acme-v02.api.letsencrypt.org/acme/order/1878338416/294202344556","attempt":2,"max_attempts":3}
2024-08-07T07:00:53-04:00	Error	caddy	 "error","ts":"2024-08-07T11:00:53Z","logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"liyue.dead-end.quest","challenge_type":"http-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for liyue.dead-end.quest; no valid AAAA records found for liyue.dead-end.quest","instance":"","subproblems":[]}}
2024-08-07T07:00:52-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:52Z","logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"liyue.dead-end.quest","challenge_type":"http-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
2024-08-07T07:00:51-04:00	Error	caddy	 "error","ts":"2024-08-07T11:00:51Z","logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"liyue.dead-end.quest","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for liyue.dead-end.quest; no valid AAAA records found for liyue.dead-end.quest","instance":"","subproblems":[]},"order":"https://acme-v02.api.letsencrypt.org/acme/order/1878338416/294202339306","attempt":1,"max_attempts":3}
2024-08-07T07:00:51-04:00	Error	caddy	 "error","ts":"2024-08-07T11:00:51Z","logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"liyue.dead-end.quest","challenge_type":"tls-alpn-01","problem":{"type":"urn:ietf:params:acme:error:dns","title":"","detail":"no valid A records found for liyue.dead-end.quest; no valid AAAA records found for liyue.dead-end.quest","instance":"","subproblems":[]}}
2024-08-07T07:00:51-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:51Z","logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"liyue.dead-end.quest","challenge_type":"tls-alpn-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
2024-08-07T07:00:50-04:00	Informational	caddy	 "info","ts":"2024-08-07T11:00:50Z","logger":"tls.issuance.acme","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/1878338416","account_contact":["mailto:aidan@aidansmith.dev"]}

3. Caddy version:

The version listed for the plugin is 1.6.0.
SSHing into the machine, the version is: v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

4. How I installed and ran Caddy:

a. System environment:

Caddy Plugin running on OPNSense 24.1.10_8

b. Command:

Not Applicable.

c. Service/unit/compose file:

Once again, I don’t think this is applicable.

d. My complete Caddy config:


# DO NOT EDIT THIS FILE -- OPNsense auto-generated file


# Global Options
{
        log {
        	output net unixgram//var/caddy/var/run/log {}
       		format json {
            		time_format rfc3339
        	}
	}

    email aidan@aidansmith.dev
    grace_period 10s
    import /usr/local/etc/caddy/caddy.d/*.global
}

# Reverse Proxy Configuration
# Reverse Proxy Domain: "7e007152-316a-44c8-8b49-29320a987b86"
liyue.dead-end.quest {                                                                                            
	handle {
		reverse_proxy	192.168.1.3:8006 {
            transport http {
				tls_insecure_skip_verify
			}
		}
	}
}
    
import /usr/local/etc/caddy/caddy.d/*.conf

Man, I had to save the spacing on that file, it was completely unreadable. The only difference between this and my personal is that there is an “https://” before the IP address, but that’s definitely not causing the problem here.

5. Links to relevant resources:

NAME                 	TYPE	CLASS	TTL 	ADDRESS    	NAMESERVER    
liyue.dead-end.quest.	A   	IN   	600s	192.168.1.1	127.0.0.53:53	

192.168.1.1 isn’t a valid A record for a public CA.

Also, I’m getting NXDOMAIN for the root nameservers:

.                    	SOA 	IN   	86350s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86398s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86350s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86348s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	7199s 	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86339s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86335s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86339s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400                         	             	        	
.                    	SOA 	IN   	86335s	a.root-servers.net.           	127.0.0.53:53	NXDOMAIN	
                     	    	     	      	nstld.verisign-grs.com.       	             	        	
                     	    	     	      	2024080700 1800 900 604800    	             	        	
                     	    	     	      	86400
1 Like

Okay, if 192.168.1.1 is not a valid record, I am not sure how to setup what I would like to create. I do not want the majority of the websites I am connecting with Caddy to be available to users not connected to my network. This was working just fine before moving to OPNSense Caddy, so I’m really not sure why it was okay when I was running Caddy on Debian.

Could you please advise on the proper procedure for creating an environment where there is absolutely no access whatsoever for users not on the LAN network for specific addresses?

Honestly, I have no clue what “NXDOMAIN for the root nameservers” means. I have not modified the nameservers with my DNS provider, so I have no idea what could have gone wrong with them.

Hi @gryphon,

This is the first step, afterwards likely there will be a few more.

From the machine Caddy is intended to run on,
execute one set (or all) command line commands
this will show what the public Internet see as its IP Address(es).

curl -4 ifconfig.me
curl -6 ifconfig.me

and/or

curl -4 ifconfig.co
curl -6 ifconfig.co

and/or

curl -4 ifconfig.io
curl -6 ifconfig.io

And that’s what the domain’s name servers need to return for the domain’s IPv4 DNS A record and IPv6 DNS AAAA record. Also all IP Addresses need to respond the same.

And to assist with debugging there is a great place to start is Let’s Debug and the online tool https://unboundtest.com/

There are ways to handle that concern, other Caddy Community members are much better in assisting with that than I.

Ah; well, a DNS record is just a lookup table. It doesn’t actually give you any security. It just makes things convenient, or makes domain names “work” when they are typed into clients like browsers or scripts or whatever.

To limit access to only your LAN then you need to mainly configure your network. You can tell Caddy to bind to a certain network interface, for example:

example.com {
   bind 192.168.1.1
}

and then make sure that your LAN is configured properly to not allow outside access to your port (i.e. port forwarding is disabled, etc).

1 Like

Also, bear in mind that LetsEncrypt counts as a “user not on the LAN”. If you want users outside your LAN not to access a site, then LetsEncrypt won’t, either.

There’s a few strategies you can take to make your sites unavailable externally.

The simplest is to simply firewall Caddy entirely - completely block all external access - and use a DNS challenge so that you don’t need LetsEncrypt to access your site to validate it.

Things get less simple if you want some sites to be externally accessible and some sites to only be internally accessible, but this is definitely achievable a few different ways. On your OPNsense I imagine binding to an interface like Matt mentioned would be one valid strategy.

1 Like

I feel that something people have missed is that I only want some of my websites to be blocked externally. Not all. Completely blocking caddy through the firewall is not an option.

From what people have said, I think it is just best for me to revert back to what I was doing previously. This really isn’t worth the effort in the slightest. I was able to get certs from Let’s Encrypt with port 443 and 80 blocked (only temporary, but I need it for a bit), I was able to use my DNS to direct to a local IP such that nothing would resolve if you weren’t on my network.

I seem to have misunderstood Matt’s last message. Does Bind make it such that only computers on the LAN network can connect? The way it was phrased and the config looked, it does not look like that’s what it does.

Only the DNS-01 challenge can be used if ports 80 & 443 are not accessible.

That’s fine, I had filled out all of the DNS connection secrets and I had built caddy with the Porkbun plugin. The OPNSense Caddy should be built with Porkbun, and I’ve filled everything out there.

bind configures Caddy only to listen on that interface.

For a device like OPNsense where I expect you’ll have a LAN interface and a WAN interface, it means that for that specific site, it will only respond to requests incoming on the LAN interface and ignore requests incoming on others (like the WAN interface).

It is not an IP allow/denylist. bind only cares which interface it’s receiving packets on. You can configure an allowlist for private IP address ranges by using a matcher to filter for LAN IPs and only serving requests that match.

You should be good to either bind those sites or allowlist LAN IPs for them without an issue.

Heck, I think you should even be fine to add LAN IPs to your public DNS like you had at the start of the thread in that case. LetsEncrypt shouldn’t care if you configure it to use the DNS challenge; that doesn’t use A records, it uses TXT.

1 Like

Changing to a TXT record yields the same issue. The functionality of “bind” appears to be what I want, but given that the OPNSense version can’t seem to understand what I’m trying to do, I have 100% decided that my previous setup will be sufficient for now. Perhaps I will revisit this when the plugin is more mature, as it definitely appears to be new.

/cc @Monviech

1 Like

I dont understand what is happening here, the docs I wrote are pretty complete.

https://docs.opnsense.org/manual/how-tos/caddy.html#restrict-access-to-internal-ips

https://docs.opnsense.org/manual/how-tos/caddy.html#bind-caddy-to-interfaces

And for anybody who does not like the GUI:

https://docs.opnsense.org/manual/how-tos/caddy.html#custom-configuration-files

2 Likes

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