【发布时间】:2016-02-12 15:50:40
【问题描述】:
Oracle 文档似乎表明 Java 8 默认自动发送 SNI。 Wireshark 另有说明。我是 PowerShell 系统管理员,而不是 Java 开发人员,所以几乎可以肯定我忽略了一些东西。
当与正确的信任密钥库一起使用时,以下代码会从所有不需要 SNI 的 SSL 网站返回状态 200。当连接到多主机 Apache 服务器的默认 SSL 网站时,它也能很好地返回。但是,当被要求连接到非默认站点时,由于证书名称与站点名称不匹配,它会失败,因为它连接到默认站点。
import java.util.*;
import java.net.*;
import javax.net.ssl.*;
import java.io.*;
public class testJavaHttpConn {
public static void main(String[] args) throws Exception {
String strUrl = args[0];
System.out.println("Trying to connect to " + strUrl);
try {
URL url = new URL(strUrl);
HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
System.out.println("Connecting");
urlConn.connect();
System.out.println("Done");
System.out.println("Response " + urlConn.getResponseCode());
} catch (IOException e) {
System.err.println("Error creating HTTP connection");
e.printStackTrace();
throw e;
}
}
}
我没有设置 System.setProperty ("jsse.enableSNIExtension", "false");当我设置 -Djavax.net.debug=ssl 时,它清楚地显示未设置服务器扩展名。
我知道我可以实现 SSLSocket 并设置 SSLParameter serverName,如果我愿意深入到下一个更深的抽象层,但我想避免这种情况。
编辑:代码的工作方式与上面为 cmets 中的 Flo 编写的一样。 Linux 2.6.18-194.11.3.el5 上的 1.8.0_72 和 Windows 7 上的 1.8.0_51 对我来说都失败了。Windows 安装是 vanilla,而 Linux 安装已将 urandom 值更新为 securerandom.source=file: /dev/./urandom.我不确定如何确定我的安装与 Flo 的不同。
【问题讨论】:
-
所以你在寻找documented here以外的方法?
-
我受限于无知。使用 SSLSocket 的代码 sn-ps 假定知道构建之前和之后的所有内容,而我缺乏这一点。我还没有找到显示如何使用 SSLSocket 执行连接和检索并将输出转换为 HttpURLConnection 返回的相同对象的示例。我已经根据这些 sn-ps 构建了所有这些对象,但是一旦拥有它们就无法对它们做任何事情。鉴于我的无知,询问我是否在某处忽略了导致 HttpsURLConnection 发送 SNI 的简单属性似乎是明智的。如果答案是否定的,那么就是 SSLSocket。
-
我使用“sni.velox.ch”测试了您的代码,调试结果显示为
Extension server_name, server_name: [type=host_name (0), value=sni.velox.ch]。它导致状态 200。使用System.setProperty ("jsse.enableSNIExtension", "false")我得到一个错误(如预期的那样)并且在调试中缺少扩展。系统:Ubuntu Linux、Java 1.8.0_72(但也适用于 1.7.0_95)。很遗憾,我没有适合你的解决方案。 -
啊。谢谢你,弗洛!当我运行代码时,我确实没有看到 Extension_server_name。所以,你的 1.8.0_72 和我的有些不同,如果我的正确,它真的应该发送 SNI。我在安装中调整的唯一文件是 ${JDK_HOME}/jre/lib/security/java.security。我想知道那里是否有什么东西会妨碍我。
-
哇。实际上,我注意到 flo 的别名是完全限定的,而且我使用的是短名称别名(Intranet,你知道吗?)。我尝试了 FQDN,并发送了服务器名称。现在我在证书命名问题上出错了,所有这些都应该很好地解决!取消狩猎。当我 100% 确定这是解决方案时,我将在下面发布答案。