【问题标题】:sslv2 and sslv3 compatability or a cert issue?sslv2 和 sslv3 兼容性还是证书问题?
【发布时间】:2014-07-25 23:22:21
【问题描述】:

我在服务器“CCC”中运行了一个 unix 脚本,从中调用在另一台服务器“GGG”中运行的 servlet。(服务器 GGG 是一个安全服务器,与普通服务器相比具有额外的防火墙)

另外,CCC 是一个 ETL 服务器,它有一个 JRE。脚本使用http调用servlet,因为应用了I规则,所以重定向到https,端口号也在变化。

当我尝试调用 servlet 时,我遇到了错误的证书错误。

在普通 IE 或 chrome 中给出的 servlet URL 给了我一个有效的响应,能够访问服务器 GGG。

得到的错误是:

javax.net.ssl.SSLHandshakeException: bad certificate
    at com.ibm.jsse.bg.a(Unknown Source)
    at com.ibm.jsse.b.a(Unknown Source)
    at com.ibm.jsse.b.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:139)
    at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:827)
    at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1975)
    at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:324)
    at com.tgt.task.client.TaskClient.doGet(TaskClient.java:153)
    at com.tgt.task.client.TaskClient.runClient(TaskClient.java:91)
    at com.tgt.task.client.TaskClient.completeTask(TaskClient.java:68)
    at com.tgt.task.client.TaskClient.main(TaskClient.java:53)

所以,最初我在 cacerts 中检查了 CCC 服务器的证书,它拥有所有根证书,但颁发给 URL 的证书除外。

我们发现问题是在 URL 的 BIG IP 证书续订后开始的,我已与我的网络团队跟进调查该问题,他们已确认来自服务器 CCC 的流量正常通过 GGG 传递防火墙。

所以当我们尝试调用 URL 时捕获了流量,我们得到了以下内容:

client  server  SSLV2   282 Client Hello
server  client  SSLV3   1631    Server Hello
server  client  SSLv3   433 Certificate
client  server  SSLV3   190 Alert(Level: Fatal, Description: Bad Certificate)

您能告诉我问题是因为客户端和服务器使用的 SSL 版本吗?

或其他一些我在分析中遗漏的东西。

我什至尝试将 URL 的证书导入服务器 CCC 中的 cacerts,但出现错误:

keytool 错误:java.lang.Exception:输入不是 X.509 证书

所以,我为 URl 获取了 PKCS7 证书并尝试将其转换为 .cer 并尝试导入,但得到了同样的错误。

【问题讨论】:

  • 请将错误范围缩小到一个简单的可重现用例(是否会在没有重定向的情况下发生?)。目前这听起来像是一台 Rube Goldberg 机器。
  • 不,如果不重定向到 https,我们就无法调用 servlet。我同意您的评论,但我想知道为什么会收到错误的证书错误?
  • 一些附加信息将有助于确定解决方案。当您使用浏览器访问GGG时,您使用的是IP地址还是域名? CCC访问GGG是用IP地址还是域名?
  • 看起来您正在使用 IBM JRE。您是否尝试过使用 Oracle JRE 看看是否有任何不同?
  • 我用域名...打服务器GGG

标签: java ssl https


【解决方案1】:

如果它适用于浏览器,但不适用于脚本,则通常与服务器名称指示 (SNI) 有关。使用 SNI,您可以在同一 IP 地址后面拥有多个具有不同证书的主机。虽然当前所有浏览器都支持 SNI,但其他实现可能不会或默认不启用 SNI。如果客户端无法在同一 IP 后面有多个证书的站点上使用 SNI,它只会获取默认证书,而这通常是错误的。

我不知道您正在运行哪个 Java 版本,但我建议您确定您的版本,然后在 google 上了解如何在您的版本中使用 SNI。据我了解,SNI 仅在 Java 版本 7 中启用。

【讨论】:

  • Java 版本是“1.4.2” Java(TM) 2 Runtime Environment,标准版(build 1.4.2) Classic VM(build 1.4.2,J2RE 1.4.2 IBM AIX 5L for PowerPC (64位JVM)构建caix64142-20080515(SR11)(启用JIT:jitc))
  • 这将是 Java 2 - 我认为您不会让 SNI 使用这个旧版本。而且它可能很久以前就不再受支持了。
【解决方案2】:

我检查了捕获的网络数据包,发现 URL 正在根据 BIG IP 端的 SSL 配置向服务器 CCC 提供正确的证书,客户端 CCC 无法验证它。并返回错误的证书消息。

这里我尝试了openssl并尝试了命令:

s_client -connect host:443
verify error:num=20:unable to get local issuer certificate
verify error:num=27:certificate not trusted
verify error:num=21:unable to verify the first certificate

`No client certificate CA names sent`
 SSL handshake has read 1745 bytes and written 304 bytes
 New, TLSv1/SSLv3, Cipher is RC4-SHA
 Server public key is 1024 bit
 Compression: NONE
 Expansion: NONE
 SSL-Session:
Start Time: 1402019174
Timeout   : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)

我猜我的服务器没有发送完整的信任链列表,因此客户端无法验证它。

不确定我的分析是否正确,我也参考了以下帖子:

OpenSSL: unable to verify the first certificate for Experian URL

如果我需要发送我的服务器来发送完整的可信链列表,我需要在哪里更改设置?在 BIG Ip 端,还是在服务器端?

【讨论】:

    猜你喜欢
    • 2014-12-11
    • 2013-03-02
    • 2013-01-17
    • 1970-01-01
    • 2013-12-11
    • 2013-01-25
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多