TLS Alerts when having multiple sites

1. The problem I’m having:

I want to serve https on multiple ports. I want each site to just use the certificate I choose, regardless of SNI and SAN.
What I instead observe is that when I have multiple sites, calling one site where SAN doesn’t match, but it does match on a different site, will cause a TLS alert.

When 443 has a self-signed cert with SAN DNS:localhost:

$ openssl s_client -connect localhost:443
Connecting to ::1
CONNECTED(000001AC)
58410000:error:0A000438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error:../openssl-3.2.3/ssl/record/rec_layer_s3.c:909:SSL alert number 80
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 306 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
This TLS version forbids renegotiation.
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---

It works fine if :443 is the only site in my caddyfile or if I add -servername localhost

This behavior depends on the SAN in bar, in my example the bar certificate has SAN:
DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
If bar’s SAN didn’t match anything in the request no alert would be raised.

The only workaround I can see is to run multiple caddy instances with a single site block per caddyfile, but I’m hoping there’s some other solution I’ve missed.

2. Error messages and/or full log output:

$ caddy run
2025/02/11 22:47:03.730 INFO    using adjacent Caddyfile
2025/02/11 22:47:03.731 INFO    adapted config to JSON  {"adapter": "caddyfile"}
2025/02/11 22:47:03.736 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
2025/02/11 22:47:03.736 INFO    tls.cache.maintenance   started background certificate maintenance      {"cache": "0xc00042ee00"}
2025/02/11 22:47:03.736 WARN    tls     stapling OCSP   {"error": "no OCSP stapling for [localhost]: no OCSP server specified in certificate"}
2025/02/11 22:47:03.737 DEBUG   events  event   {"name": "cached_unmanaged_cert", "id": "29d790e1-5751-4ef1-8da2-ae0b2792e3f3", "origin": "tls", "data": {"sans":["localhost"]}}
2025/02/11 22:47:03.737 DEBUG   tls.cache       added certificate to cache      {"subjects": ["localhost"], "expiration": "2027/03/10 00:00:01.000", "managed": false, "issuer_key": "", "hash": "a26052287114a645295f6a1a01bf29320734ac4b65ef0f94c99b7203d6cff74a", "cache_size": 1, "cache_capacity": 10000}
2025/02/11 22:47:03.737 WARN    tls     stapling OCSP   {"error": "no OCSP stapling for [test-cert-self-signed localhost 127.0.0.1 ::1]: no OCSP server specified in certificate"}
2025/02/11 22:47:03.737 DEBUG   events  event   {"name": "cached_unmanaged_cert", "id": "e4dd2247-5ceb-4404-a43a-a7ede6eac8a0", "origin": "tls", "data": {"sans":["test-cert-self-signed","localhost","127.0.0.1","::1"]}}
2025/02/11 22:47:03.737 DEBUG   tls.cache       added certificate to cache      {"subjects": ["test-cert-self-signed", "localhost", "127.0.0.1", "::1"], "expiration": "2026/02/11 22:41:28.000", "managed": false, "issuer_key": "", "hash": "75f3b9a1b7923f83c5af0d3907fe5eef9b67c6cb3bb536441248414f4c66485d", "cache_size": 2, "cache_capacity": 10000}
2025/02/11 22:47:03.737 INFO    http.auto_https enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2025/02/11 22:47:03.737 INFO    http.auto_https enabling automatic HTTP->HTTPS redirects        {"server_name": "srv1"}
2025/02/11 22:47:03.737 DEBUG   http.auto_https adjusted config {"tls": {"automation":{"policies":[{}]}}, "http": {"servers":{"remaining_auto_https_redirects":{"listen":[":80"],"routes":[{},{},{}]},"srv0":{"listen":[":443"],"routes":[{"handle":[{"body":"foo","handler":"static_response"}]}],"tls_connection_policies":[{"certificate_selection":{"any_tag":["cert0"]}}],"automatic_https":{}},"srv1":{"listen":[":8443"],"routes":[{"handle":[{"body":"bar","handler":"static_response"}]}],"tls_connection_policies":[{"certificate_selection":{"any_tag":["cert1"]}}],"automatic_https":{}}}}}
2025/02/11 22:47:03.737 DEBUG   http    starting server loop    {"address": "[::]:443", "tls": true, "http3": false}
2025/02/11 22:47:03.737 INFO    http    enabling HTTP/3 listener        {"addr": ":443"}
2025/02/11 22:47:03.738 INFO    http.log        server running  {"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2025/02/11 22:47:03.738 DEBUG   http    starting server loop    {"address": "[::]:8443", "tls": true, "http3": false}
2025/02/11 22:47:03.738 INFO    http    enabling HTTP/3 listener        {"addr": ":8443"}
2025/02/11 22:47:03.738 INFO    http.log        server running  {"name": "srv1", "protocols": ["h1", "h2", "h3"]}
2025/02/11 22:47:03.739 DEBUG   http    starting server loop    {"address": "[::]:80", "tls": false, "http3": false}
2025/02/11 22:47:03.739 WARN    http    HTTP/2 skipped because it requires TLS  {"network": "tcp", "addr": ":80"}
2025/02/11 22:47:03.739 WARN    http    HTTP/3 skipped because it requires TLS  {"network": "tcp", "addr": ":80"}
2025/02/11 22:47:03.739 INFO    http.log        server running  {"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2025/02/11 22:47:03.740 INFO    autosaved config (load with --resume flag)      {"file": "C:\\Users\\Tratt\\AppData\\Roaming\\Caddy\\autosave.json"}
2025/02/11 22:47:03.740 INFO    serving initial configuration
2025/02/11 22:47:03.746 INFO    tls     storage cleaning happened too recently; skipping for now        {"storage": "FileStorage:C:\\Users\\Tratt\\AppData\\Roaming\\Caddy", "instance": "5a974297-e716-43bc-8a37-b6c15de022de", "try_again": "2025/02/12 22:47:03.746", "try_again_in": 86400}
2025/02/11 22:47:03.746 INFO    tls     finished cleaning storage units
2025/02/11 22:47:06.664 DEBUG   events  event   {"name": "tls_get_certificate", "id": "8b8d93a3-6339-4f76-9a3a-5c19a43d6088", "origin": "tls", "data": {"client_hello":{"CipherSuites":[4866,4867,4865,49196,49200,159,52393,52392,52394,49195,49199,158,49188,49192,107,49187,49191,103,49162,49172,57,49161,49171,51,157,156,61,60,53,47,255],"ServerName":"","SupportedCurves":[29,23,30,25,24,256,257,258,259,260],"SupportedPoints":"AAEC","SignatureSchemes":[1027,1283,1539,2055,2056,2074,2075,2076,2057,2058,2059,2052,2053,2054,1025,1281,1537,771,769,770,1026,1282,1538],"SupportedProtos":null,"SupportedVersions":[772,771],"RemoteAddr":{"IP":"::1","Port":55128,"Zone":""},"LocalAddr":{"IP":"::1","Port":443,"Zone":""}}}}
2025/02/11 22:47:06.664 DEBUG   tls.handshake   choosing certificate    {"identifier": "::1", "num_choices": 1}
2025/02/11 22:47:06.664 DEBUG   tls.handshake   custom certificate selection results    {"error": "no certificates matched custom selection policy", "identifier": "::1", "subjects": [], "managed": false, "issuer_key": "", "hash": ""}
2025/02/11 22:47:06.664 DEBUG   tls.handshake   no certificate matching TLS ClientHello {"remote_ip": "::1", "remote_port": "55128", "server_name": "", "remote": "[::1]:55128", "identifier": "::1", "cipher_suites": [4866, 4867, 4865, 49196, 49200, 159, 52393, 52392, 52394, 49195, 49199, 158, 49188, 49192, 107, 49187, 49191, 103, 49162, 49172, 57, 49161, 49171, 51, 157, 156, 61, 60, 53, 47, 255], "cert_cache_fill": 0.0002, "load_or_obtain_if_necessary": true, "on_demand": false}
2025/02/11 22:47:06.664 DEBUG   http.stdlib     http: TLS handshake error from [::1]:55128: no certificate available for '::1'

3. Caddy version:

$ caddy version
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=

4. How I installed and ran Caddy:

I downloaded caddy_windows_amd64.exe, renamed it to caddy.exe and put it in my PATH

a. System environment:

Windows 10. commands are run in git bash

b. Command:

caddy run

c. Service/unit/compose file:

d. My complete Caddy config:

{
	debug
}

:443 {
	tls "foo.cert" "foo.key"
	respond "foo"
}

:8443 {
	tls "bar.cert" "bar.key"
	respond "bar"
}

5. Links to relevant resources:

The closest I can find for this in Caddy is here. I’m not sure if what you want is entirely possible.

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