Snake-oil TLS for all requests on a specific port

1. Caddy version (caddy version):

Binary installed from Github release.

$ caddy version
v2.4.3 h1:Y1FaV2N4WO3rBqxSYA8UZsZTQdN+PwcoOcAiZTM8C0I=

2. How I run Caddy:

$ caddy run -watch

a. System environment:

ChromeOS, inside the penguin “Linux” container (although Caddy isn’t being “containerised” here!)

b. Command:

$ caddy run -watch
2021/08/15 18:03:18.747 INFO    using adjacent Caddyfile
2021/08/15 18:03:18.751 WARN    admin   admin endpoint disabled
2021/08/15 18:03:18.751 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc00035c700"}
2021/08/15 18:03:18.762 INFO    tls     cleaning storage unit   {"description": "FileStorage:/home/user/.local/share/caddy"}
2021/08/15 18:03:18.765 INFO    tls     finished cleaning storage units
2021/08/15 18:03:18.762 DEBUG   http    starting server loop    {"address": "[::]:8443", "http3": false, "tls": true}
2021/08/15 18:03:18.767 INFO    http    enabling automatic TLS certificate management   {"domains": ["*"]}
2021/08/15 18:03:18.777 WARN    tls     stapling OCSP   {"error": "no OCSP stapling for [*]: no OCSP server specified in certificate"}
2021/08/15 18:03:18.779 WARN    pki.ca.local    root certificate trust store installation disabled; unconfigured clients may show warnings      {"path": "storage:pki/authorities/local/root.crt"}
2021/08/15 18:03:18.781 INFO    autosaved config (load with --resume flag)      {"file": "/home/user/.config/caddy/autosave.json"}
2021/08/15 18:03:18.782 INFO    serving initial configuration
2021/08/15 18:03:18.783 INFO    watcher watching config file for changes        {"config_file": "Caddyfile

c. Service/unit/compose file:

d. My complete Caddyfile or JSON config:

{
        auto_https disable_redirects
        admin off
        local_certs
        skip_install_trust
        debug
        #default_sni wibble
}

https://*:8443 {
        tls internal
        file_server browse
}

3. The problem I’m having:

I’m trying to figure out an unopinionated, works-in-all-situations, TLS-enabling Caddyfile to give to the devs I work with, for embedding into some non-internet-connected containers (i.e. ACME isn’t an option).

Basically, when an app they’re working with doesn’t have TLS out of the box, I’d like to reverse-proxy its localhost:8080 (or whatever port its listening on) and add TLS to their container mix with zero changes needed apart from the backend port that’s being proxied.

But! I’m very very aware that the Caddyfile I’ve posted above doesn’t bring any identity assurance to the party! I know that what I’ve posted is snake-oil, and that’s just fine! :slight_smile: This config will be used behind TLS-terminating load balancers, and is for “securing” the load-balancer-to-backend connection, alone. I am 100% aware of the security downgrade I’m injecting, here! :slight_smile:

What I’m trying to convince Caddy to do is this:

  • Listen on port 8443 (and only that port; no http redirects, please!)
  • Serve a snake-oil/internal/etc TLS certificate that Caddy itself has created (either on demand, or on startup, either’s fine)
  • Inject X-F-For, X-F-Proto, & X-F-Host headers as appropriate, matching whatever was received
  • Reverse-proxy to a localhost port

I can’t seem to figure out how to tell Caddy to care a little less about the site address. When testing with https://nip.io/ dynamic DNS hostnames, and the above config, I get:

DEBUG   http.stdlib     http: TLS handshake error from 100.115.92.199:38542: no certificate available for '100-115-92-199.nip.io'

I can fix this for my machine, here, by adding that specific site into my config, but that’s not going to help my colleagues out there in Azure land …

How do I wildcard TLS on a particular listener port, when I really don’t care about the identity provision of the TLS connection?

4. Error messages and/or full log output:

As above, I see lots of this:

DEBUG   http.stdlib     http: TLS handshake error from 100.115.92.199:38542: no certificate available for '100-115-92-199.nip.io'

5. What I already tried:

I’ve tried putting host-/SNI-specific names in the site address, and that works with the above config. My problem is how to decouple the Caddyfile from the requests that’ll hit the containers, so that (apart from the container’s reverse-proxy port) the same config can be bolted onto arbitrary containers.

I’ve tried commenting the various tls / local_certs / default_sni options in and out, with all the binary combinations I can think of. No dice, thus far!

Thanks for any pointers or help, folks - much appreciated :slight_smile:

The issue with your current config is that you didn’t specify a name for which Caddy could issue certificates for. * isn’t really valid, since it’s a wildcard label, and Caddy won’t issue a wildcard certificate unless the DNS challenge is enabled.

What you can do is turn on on_demand, which will make Caddy issue certificates on-the-fly if it doesn’t have one for the domain/IP (hostname) in the request.

https://:8443 {
	tls internal {
		on_demand
	}
	respond "Yep, you got TLS!"
}

Keep in mind this is ripe for abuse, as noted in the docs, so if on_demand is used in production, an ask SHOULD be configured to avoid an attack vector. (Mainly saying this for any future readers of this thread who end up here)

1 Like

Many thanks, @francislavoie - this did indeed solve my problem :slight_smile:

1 Like

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