【问题标题】:How to set “jsse.enableSNIExtension” to false only for a single HTTPURLConnection?如何仅为单个 HTTPURLConnection 将“jsse.enableSNIExtension”设置为 false?
【发布时间】:2015-11-11 03:07:34
【问题描述】:

我目前有一个应用程序可以向许多 URL 发出 HTTP 发布请求。一些连接失败,但出现以下异常。

线程“主”javax.net.ssl.SSLProtocolException 中的异常: 握手警报:unrecognized_name at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1410) 在 sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2004) 在 sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113) 在 sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363) 在 sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)

。 . .

因此,我只想将“jsse.enableSNIExtension”设置为 false,仅针对引发上述异常的特定连接。

如何在 HTTPsURLConnection/SSLSocket 级别上执行此操作?

代码

URL url = new URL("https://artofskinmd.localgiftcards.com/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();

httpConnection.connect();

我正在尝试找到一种方法来更改 HttpsURLConnection 对象的 SSLParameters。但我找不到任何用于设置空服务器名称列表的 setSSLParameters() 方法。我无法在网上找到任何关于为 HttpURLConnection、SSLContext 等设置 SSLParameters 的内容

【问题讨论】:

  • 另一个问题将阐明设置 jsse 系统属性的安全问题。如果该方法没有高安全风险,这个问题将很有用。
  • 根据我拥有并由 javap 为 7u80 和 8u51 验证的稍旧的源代码,sun.security.ssl.ClientHandshaker 中的private final static boolean enableSNIExtension 仅在加载类时初始化,并且有没有 API 可以改变它。未经测试,但假设您不在 SecurityManager(例如浏览器小程序)下,它应该使用反射来暂时破坏它。如果任何其他线程可以同时执行(客户端)SSL/TLS,则需要互斥;在ClientHandshaker.class 上同步简单明了。

标签: java ssl httpurlconnection sslexception


【解决方案1】:

显然站点依赖于 SNI,否则它不会关心客户端在 SNI 扩展中发送的名称。这意味着禁用扩展可能无济于事,但是您可能会遇到一些握手失败或一些默认站点(和证书),并且可能不是您想要的站点。要解决此问题,您不应禁用 SNI,而应使用正确的名称,即站点预期的名称。

编辑:这看起来像是一个糟糕的服务器配置以及 Java7 和 Java8 中的一个错误。访问 URL https://artofskinmd.localgiftcards.com/ 将导致一个 unknown_name TLS 警报 warning,Java7 和 Java8 错误地认为它是致命的(与非常旧的 OpenSSL 0.9.8 相同)。在这种情况下,禁用 SNI 实际上会有所帮助,但似乎无法为单个 HttpURLConnection 对象禁用 SNI。

【讨论】:

  • 根据我的阅读,这是服务器配置的问题。参考:javaresolutions.blogspot.ie/2014/07/… 由于我没有访问服务器的权限,我将无法修改服务器配置。有没有办法查看主机接受的所有服务器名称?
  • @Sashwat:服务器被配置为只接受一些主机名,并且会拒绝所有其他带有未知名称的(包括没有 SNI)。这是一个有效的配置。不,您无法直接确定服务器将接受哪些名称,但您可以尝试所有解析为同一 IP 地址的名称。不幸的是,没有简单的方法来获得这些名字:(
  • @Sashwat:您提供的地址(artofskinmd.localgiftcards.com)与 SNI 没有问题。如果你得到了这个 URL 的 unknown_name,那就是有别的问题了。
  • @Sashwat:根据SSLLabs,unknown_name 问题似乎特定于 Java7 和 Java8,而 Java6(不执行 SNI)可以工作。没有其他客户有问题。奇怪。
  • @Sashwat:实际上,当使用带有潜在错误名称的 SNI 时,服务器会发送 TLS 警报级别警告。 Java 7 和 Java 8 认为这个警告是致命的,因此会失败 - 所有其他人都认为这只是一个警告并继续。这与多年前 OpenSSL 0.9.x 的错误相同。
【解决方案2】:
猜你喜欢
  • 2012-08-10
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多