java.lang.IllegalArgumentException: 类型 0 的重复服务器名称

问题描述

我正在尝试客户端 SNI 实现,我发现我可以将多个主机名(生成相同的证书)传递给 SSLParameters,下面的代码片段。

SSLSocketFactory factory =(SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket =(SSLSocket)factory.createSocket("www.verisign.com",443);     
SNIHostName serverName1 = new SNIHostName("www.verisign.co.in");
SNIHostName serverName2 = new SNIHostName("www.verisign.co.uk");
List<SNIServerName> serverNames = new ArrayList<>();
serverNames.add(serverName1);
serverNames.add(serverName2);
SSLParameters params = socket.getSSLParameters();
params.setServerNames(serverNames);
socket.setSSLParameters(params);

但在进行 SSL 握手之前,我收到以下异常。

java.lang.IllegalArgumentException: Duplicated server name of type 0
at java.base/javax.net.ssl.SSLParameters.setServerNames(SSLParameters.java:343)
at SSLSocketClient.main(SSLSocketClient.java:69)

在 eclipse 中检查显示,两个 SNI 主机名的类型都是 host_name (0)。 [type=host_name (0),value=www.verisign.co.in,type=host_name (0),value=www.verisign.co.uk]

如果它不允许多个主机名,那么为什么要提供传递 serverNames 列表的规定。

解决方法

似乎该标准曾经支持多个主机名,但已放弃支持。

根据 SNI (https://datatracker.ietf.org/doc/html/rfc6066) 的 RFC

ServerNameList 不得包含多个相同的名称 name_type。

...

注意:本规范的早期版本允许使用多个名称 同名_类型。在实践中,当前的客户端实现 只发送一个名称,客户端不一定能找出哪个 命名选择的服务器。具有相同 name_type 的多个名称是 因此现在被禁止。

人们可能会尝试添加具有不同 name_types 的其他名称。但是,似乎唯一定义过的 name_type 是“host_name”,即 0。