TLS On Demand Approval Logic

Need help to create logic for the TLS ask endpoint. Here I am blindly accepting all (see respond 200), but I want to allow certain domains only:

  • myapp.mydomain.com
  • myapp.eastus.azurecontainer.io

I was troubleshooting TLS On Demand. If you want to log what is arriving to the ask endpoint, do the following:

http://localhost:5555 {
	trace tag="tls-on-demand"
	respond 200
}

I am hosting my app eastus.azurecontainer.io. The setup resembles (not 100%) the one listed here: Secure Deployment of Application with Azure Container Instances and Caddy | AuthCrunch aka Caddy Security Documentation

Here is what I got when I browsed to https://auth.myfiosgateway.com:

{"level":"debug","time":"2024-03-26T10:07:55.545-0400","msg":"debugging request","request_id":"bc742f10-e1e9-420d-964c-d934caef4949","direction":"incoming","tag":"tls-on-demand","method":"GET","proto":"HTTP/1.1","host":"localhost:5555","uri":"/?domain=auth.myfiosgateway.com","remote_addr_port":"127.0.0.1:43018","remote_addr":"127.0.0.1","remote_port":43018,"content_length":0,"cookie_count":0,"user_agent":"Go-http-client/1.1","referer":"","cookies":[],"query_params":{"domain":"auth.myfiosgateway.com"},"headers":{"Accept-Encoding":"gzip","User-Agent":"Go-http-client/1.1"},"form":{}}

And this is for https://localhost/:

{"level":"debug","time":"2024-03-26T10:07:55.544-0400","msg":"debugging request","request_id":"4e6ce777-b661-465f-90af-5a71d5d23709","direction":"incoming","tag":"tls-on-demand","method":"GET","proto":"HTTP/1.1","host":"localhost:5555","uri":"/?domain=localhost","remote_addr_port":"127.0.0.1:43018","remote_addr":"127.0.0.1","remote_port":43018,"content_length":0,"cookie_count":0,"user_agent":"Go-http-client/1.1","referer":"","cookies":[],"query_params":{"domain":"localhost"},"headers":{"Accept-Encoding":"gzip","User-Agent":"Go-http-client/1.1"},"form":{}}

As you can see the query parameters are in play. Specifically, domain.

How would you implement the logic of allowing specific domains provided via domain query parameter.

The ‘ask’ endpoint needs to:

  • Decode the query string and read the domain parameter.
  • Determine if the value is an allowed domain name. This often involves a check against a list or a query of a database to see if it is known.
  • Return 200 only if the domain is allowed.

How you implement it is up to you.

You can also do it in Caddy directly simply by making another site and using a query matcher like this, a very basic example:

localhost:1234 {
    bind 127.0.0.1
    @allowed query domain=example.com
    respond @allowed 200
    respond 400
}

That’s just one way to do it. Does that help?

@matt , this helps!

What if I want to allow multiple domains? How would you extend your example?

  • myapp.mydomain.com
  • myapp.eastus.azurecontainer.io

What if I want to allow domains with wildcards?

  • *app.mydomain.com
  • myapp-*.eastus.azurecontainer.io

@matt , additionally, I want to user replacers. Would this work?

	@allowed query domain={env.LOCAL_APP_NAME}.{env.LOCAL_APP_DOMAIN}

Here is what I have at the moment:

http://localhost:5555 {
	bind 127.0.0.1
	trace tag="tls-on-demand"
	@allowed_localhost query domain=localhost
	@allowed_local query domain={env.LOCAL_APP_NAME}.{env.LOCAL_APP_DOMAIN}
	@allowed_global query domain={env.GLOBAL_APP_NAME}.{env.GLOBAL_APP_DOMAIN}
	respond @allowed_localhost 200
	respond @allowed_local 200
	respond @allowed_global 200
	respond 400
}