错误信息
SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
也可能输出为
- error:0A000458:SSL routines::tlsv1 unrecognized name
- SSL alert number 112
OpenSSL 3.x 输出“error:0A000458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name:…:SSL alert number 112”。Java 客户端把同一个告警报告为“javax.net.ssl.SSLHandshakeException: Received fatal alert: unrecognized_name”。
OpenSSL (client side) — TLS alert 112 (unrecognized_name) sent by a server that does not serve the requested SNI name
含义
客户端发送的服务器名称(SNI)不在该服务器的服务范围内,服务器以致命告警的形式返回了 TLS 告警 112(unrecognized_name)。RFC 6066 允许服务器以警告级或致命级发送这个告警;严格的服务器(以及部分专用设备)把未知名称视为致命错误,因此握手在出示任何证书之前就结束了。
原因
服务器上没有该名称的配置
常见指向现有服务器的新主机名、改过名的服务,或者指向 CDN 或平台、但从未在那里添加自定义域名的 CNAME。
客户端发送的名称与预期不符
常见通过内部别名或负载均衡器名称连接的客户端会把这个别名作为 SNI 发送,而服务器只认识公共名称。
没有 SNI,或者用地址代替了名称
偶见一些客户端通过 IP 地址连接时不发送 SNI;配置为必须提供已知名称的服务器会拒绝这些客户端。
修复方法
- 1.
找出服务器接受的名称
用每个候选名称分别尝试握手;握手成功的名称就是服务器上已配置的名称。
bash # Which names does the server accept? for n in example.com www.example.com api.example.com; do printf '%-20s ' "$n" echo | openssl s_client -connect 203.0.113.10:443 -servername "$n" -brief 2>&1 | grep -m1 -E 'Protocol version|error' || echo fail done - 2.
在服务器上配置缺失的名称
把这个名称添加到 server 块(或 CDN/平台的域名列表)中,同时配置覆盖该名称的证书。
text # nginx: a server block (and certificate) for every name clients use server { listen 443 ssl; server_name api.example.com legacy-api.example.com; ssl_certificate /etc/nginx/tls/api.fullchain.pem; ssl_certificate_key /etc/nginx/tls/api.key; } - 3.
让客户端发送正确的名称
在 URL 中保留真实的主机名,只覆盖地址(curl --resolve、各个库中的 servername 选项)。
bash # Send the server's real name as SNI when connecting by address curl --resolve api.example.com:443:203.0.113.10 https://api.example.com/ openssl s_client -connect 203.0.113.10:443 -servername api.example.com </dev/null