TLS error with internal CA

1. Caddy version (caddy version):

v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=

2. How I run Caddy:

Standard Ubuntu package, through systemd.

a. System environment:

Ubuntu 20.04.3 LTS
Linux app 5.4.0-90-generic #101-Ubuntu SMP Fri Oct 15 20:00:55 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux through systemd

b. Command:

from the package

c. Service/unit/compose file:

from the package

d. My complete Caddyfile or JSON config:

Caddyfile:

{
    email "foo@domainx.com"
    acme_ca "https://acme-staging-v02.api.letsencrypt.org/directory"
}
import snippets/*
laravel "domainx.com" "/home/tcurdt/web"

Snippet:

(laravel) {
    {args.0} {
        root * {args.1}/public
        encode zstd gzip
        file_server
        tls internal
    }
}

3. The problem I’m having:

The domain has not been modified to point to the IP yet. TLS is configured to be using the internal CA. So I only expect a self-signed cert until I change the DNS entry and remove the tls internal. Now I want to test the site.

I am trying to connect with curl but get an “internal error” on the TLS HELLO.

$ curl -vk --resolve domainx.com:443:23.88.46.20 https://domainx.com 
* Added domainx.com:443:23.88.46.20 to DNS cache
* Hostname domainx.com was found in DNS cache
*   Trying 23.88.46.20:443...
* Connected to domainx.com (23.88.46.20) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS alert, internal error (592):
* error:14004438:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert internal error
* Closing connection 0
curl: (35) error:14004438:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert internal error

What am I missing here?

4. Error messages and/or full log output:

see above

5. What I already tried:

see above

6. Links to relevant resources:

none

What do your Caddy logs show? I think that would have the answer.

I wish - but it really only raises more questions…

Dec 25 10:25:01 app caddy[15755]: {"level":"info","ts":1640424301.9467854,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
Dec 25 10:25:01 app caddy[15755]: {"level":"warn","ts":1640424301.950815,"msg":"input is not formatted with 'caddy fmt'","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9551725,"logger":"admin.api","msg":"received request","method":"POST","host":"localhost:2019","uri":"/load","remote_addr":"127.0.0.1:58696","headers":{>
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9559178,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019",>
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9564555,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9566946,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["domainx.com","laravel"]}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.956949,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0000da7e0"}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9575431,"logger":"tls.obtain","msg":"acquiring lock","identifier":"laravel"}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9625113,"logger":"tls.obtain","msg":"acquiring lock","identifier":"domainx.com"}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.96309,"logger":"tls.obtain","msg":"lock acquired","identifier":"laravel"}
Dec 25 10:25:01 app caddy[1725]: {"level":"info","ts":1640424301.9671507,"logger":"tls.obtain","msg":"acquiring lock","identifier":"domainx.com"}

To me it looks like internal certs for domainx.com are setup correctly.
Why would it setup certs for a domain laravel though?

Because it’s in the place in your config where a site name goes. Make sure to double check your Caddyfile structure: Caddyfile Concepts — Caddy Documentation

Then I don’t understand the docs on snippets.

As I read it this

(laravel) {
    {args.0} {
        root * {args.1}/public
        file_server
        tls internal
    }
}

would expand to

    domainx.com {
        root * /home/tcurdt/web/public
        file_server
        tls internal
    }

Is there a way to see the expanded caddy config somehow?

Now trying on the very same machine running caddy:

$ grep domainx.com /etc/hosts
23.88.46.101 domainx.com

$ ss -ntulp | grep 443
tcp   LISTEN 0       4096                    *:443               *:*  

$ curl -vk https://domainx.com
*   Trying 23.88.46.101:443...
* TCP_NODELAY set
* Connected to domainx.com (23.88.46.101) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* 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

It seems the 2nd import is required.

{
    email "foo@domainx.com"
    acme_ca "https://acme-staging-v02.api.letsencrypt.org/directory"
}
import snippets/*
import laravel "domainx.com" "/home/tcurdt/web"

I somewhere found an example without and thought the snippet would have become a directive.

Now the behaviour is slowly starting to make sense.

So in the end it just wasn’t using the snippet, hence there was no tls internal.
All clear now.

Wished this were caught as an error condition. A little odd it allows these kind of site names.

Domains can technically be anything. For example, localhost is a single word domain. You could have a DNS server locally which would resolve any kind of name to an IP address. There isn’t really a good heuristic we can use to guess that laravel isn’t a valid domain.

Glad you figured it out! :relaxed:

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