5

Caddy thinks everything is fine:

{"level":"info","ts":...,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-v02.api.letsencrypt.org/acme/order/.../..."}
{"level":"info","ts":...,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-v02.api.letsencrypt.org/acme/cert/..."}
{"level":"info","ts":...,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"service.internal.example.com"}
{"level":"info","ts":...,"logger":"tls.obtain","msg":"releasing lock","identifier":"service.internal.example.com"}

Inside the Caddy container:

# curl https://localhost/ -H "Host: service.internal.example.com" -v
*   Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, internal error (592):
* error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error
* Closing connection 0
curl: (35) error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error

Caddyfile:

{
  acme_dns cloudflare ... # github.com/caddy-dns/cloudflare
}

service.internal.example.com {
  reverse_proxy localhost:1234 # curl localhost:1234 works
}

Wget throws the same error text with a slightly different error number:

# wget https://localhost/ --header "Host: service.internal.example.com" -v
--...--  https://localhost/
Resolving localhost (localhost)... 127.0.0.1, ::1
Connecting to localhost (localhost)|127.0.0.1|:443... connected.
OpenSSL: error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error
Unable to establish SSL connection.

Thanks to @Buffoonism, I've tried:

$ curl https://service.internal.example.com --resolve service.internal.example.com:443:127.0.0.1

This call (inside the Caddy container) has a successful 200 response. I've backed out to the server and same result:

$ curl https://service.internal.example.com --resolve service.internal.example.com:443:10.1.2.3.4 # works

So, this seems to be my clue: a host header of service.internal.example.com fails, but curl's resolve flag works.

I'm not sure what to try next.

knite
  • 6,033
  • 6
  • 38
  • 54

1 Answers1

3

It looks like a TLS SNI thing. Because you connect to localhost, curl and wget will be sending a TLS SNI of localhost, not service.internal.example.com. Which means the server rejects it.

As an alternative approach, use curl's resolve option to pin the address to the domain:

curl https://service.internal.example.com --resolve service.internal.example.com:443:127.0.0.1
Buffoonism
  • 1,669
  • 11
  • 11