Java (JSSE)Java
错误信息
javax.net.ssl.SSLHandshakeException: (unrecognized_name) Received fatal alert: unrecognized_name
也可能输出为
- Received fatal alert: unrecognized_name
JDK 25 报告“(unrecognized_name) Received fatal alert: unrecognized_name”。Java 7 和早期的 Java 8 版本在服务器只是把这个告警作为警告发送时也会中止,这是 Apache httpd 配置缺少匹配的 ServerName 时的经典问题。
Java (JSSE) — TLS alert 112 from a server that does not serve the requested SNI name
含义
JVM 把 URL 中的主机名作为 SNI 发送,而服务器没有为这个名称配置站点,于是以致命告警的形式返回了 TLS 告警 112(unrecognized_name)。Java 把这个告警当作致命错误处理并停止连接。服务器是可达的,只是不认识你使用的名称。
原因
服务器上没有对应该名称的站点
常见新的 DNS 名称(或指向某个平台或 CDN 的 CNAME)指向的服务器上,从未添加过这个名称。
客户端使用了服务器未列出的别名
常见客户端配置中的内部名称或旧名称,不在服务器的虚拟主机所包含的名称之中。
Apache httpd 缺少匹配的 ServerName
偶见如果没有任何 TLS 虚拟主机的 ServerName 或 ServerAlias 与 SNI 名称匹配,Apache 就会发送 unrecognized_name。
修复方法
- 1.
找出服务器接受的名称
用 openssl s_client -servername 以各个候选名称尝试握手。
bash # Which SNI names does the server accept? for n in api.example.com www.example.com; do printf '%-18s ' "$n" echo | openssl s_client -connect api.example.com:443 -servername "$n" -brief 2>&1 | grep -m1 -E 'Protocol version|alert' || echo fail done - 2.
在服务器上添加这个名称
配置 ServerName 或 ServerAlias(或者 nginx、CDN、平台中的等效设置),同时配置覆盖该名称的证书。
text # Apache httpd: every name clients use must be a ServerName or ServerAlias of a TLS vhost <VirtualHost *:443> ServerName api.example.com ServerAlias api-legacy.example.com SSLEngine on </VirtualHost> - 3.
使用已配置的主机名
优先修正 URL,而不是全局禁用 SNI。
text Use the server's configured host name in the URL. Turning SNI off with -Djsse.enableSNIExtension=false only works if the server's default site is the one you need, and it breaks every server that relies on SNI; avoid it.