Caddy does not consider IP addresses as a valid ServerName for TLS
Hi,
So I wanted to try out TLS client authentication in a lab environment. This environment does not have a DNS server, so no domains.
I generated 3 certificates for my test:
- The certificate authority
CN=REDACTED-VLAN98 Certifiacte authority,OU=VLAN98,O=REDACTED- One server certificate
CN=172.16.128.56,OU=VLAN98,O=REDACTEDwithextendedKeyUsage=serverAuthandsubjectAltName=IP:172.16.128.56 - One client certificate
CN=User1,OU=VLAN98,O=REDACTEDwithextendedKeyUsage=clientAuth
- One server certificate
And used this config
172.16.128.56 {
tls /etc/caddy/keys/server.crt /etc/caddy/keys/server.key
encode gzip
root * /usr/share/caddy
file_server
}
Navigating to https://172.16.128.56/ using Firefox returned the default "Caddy works!" page and there was no SSL issues after importing the CA.
I then moved on and added the client_auth directive
172.16.128.56 {
tls /etc/caddy/keys/server.crt /etc/caddy/keys/server.key {
client_auth {
mode require_and_verify
trust_pool file {
pem_file /etc/caddy/keys/root.crt
}
}
}
encode gzip
root * /usr/share/caddy
file_server
}
Navigating to https://172.16.128.56/ using Firefox returned a HTTP 421 which after some googling was caused by strict_sni_host being automatically enabled by client_auth.
And sure enought looking at the logs it seems that it doesn't match, in fact, there is nothing at all!
2025/01/10 11:20:57.887 DEBUG http.log.error strict host matching: TLS ServerName () and HTTP Host (172.16.128.56) values differ {"request": {"remote_ip": "10.5.0.5", "remote_port": "34514", "client_ip": "10.5.0.5", "proto": "HTTP/2.0", "method": "GET", "host": "172.16.128.56", "uri": "/", "headers": {"Accept-Encoding": ["gzip, deflate, br"], "Sec-Fetch-Dest": ["document"], "Sec-Fetch-Mode": ["navigate"], "Cache-Control": ["no-cache"], "Accept-Language": ["fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3"], "Sec-Fetch-User": ["?1"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"], "Dnt": ["1"], "Te": ["trailers"], "Sec-Fetch-Site": ["none"], "Upgrade-Insecure-Requests": ["1"], "Pragma": ["no-cache"]}, "tls": {"resumed": false, "version": 772, "cipher_suite": 4865, "proto": "h2", "server_name": ""}}, "duration": 0.000030603, "status": 421, "err_id": "sxiu5tuj1", "err_trace": "caddyhttp.(*Server).enforcementHandler (server.go:479)"}
After disabling the strict_sni_host option by setting it to insecure_off I could access the page, but the client authentication was not working at all.
After much frustration, the only last thing was that I was using an IP and not a domain, so I temporarily set the host file of my machine so that server.vlan98.redacted.fr would point to 172.16.128.56. I also re-issued the server certificate with the domain to CN=server.vlan98.redacted.fr,OU=VLAN98,O=REDACTED and subjectAltName=IP:172.16.128.56, DNS:server.vlan98.redacted.fr
After editing the config and reloading, everything worked without any issue and Firefox prompted me for a client certificate.
This affects much more than TLS client authentication. The fact that strict_sni_host is off by default, hides the issue the real issue, which is that caddy does not consider an IP address as a valid ServerName for TLS
While this bug is very unlikely to appear for front-facing domains, it is entirely possible for local environments.
Thanks
caddy does not consider an IP address as a valid ServerName for TLS
RFC 6066 does not consider an IP address a valid ServerName for TLS:
The only server names supported are DNS hostnames.
Did not know that, thanks!
While I know understand that the behavior of caddy and strict_sni_host is normal, the issue still stands.
The client_auth directive does not work when using TLS without domains.
PS: Maybe the issue should be renamed then?
I think this might be the first time I've heard of trying to use client auth with an IP address. I'm not really sure if we can safely make this work for IP addresses.
There's no need to implement something unsafe, and we can both agree that it's a very unusual setup.
But in that case, a warning/error or at least documentation would be nice if someone tries to do something similar. Even if you know that IPs are not valid ServerNames it's no obvious why client_auth is not working.