我有一个在服务器“CCC”中运行的unix脚本,从中调用在另一台服务器“GGG”中运行的servlet。(服务器GGG是一个安全服务器,与普通服务器相比具有额外的防火墙)
此外,CCC是一个ETL服务器,它有一个JRE。该脚本使用http调用servlet,因为我应用了规则,因此重定向发生在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 error:java.lang.Exception:输入的不是X.509证书
所以,我为URl获取了PKCS7证书,并试图将其转换为.cer并尝试导入,但得到了同样的错误。
答案 0 :(得分:0)
如果它适用于浏览器,但不适用于脚本,则通常与服务器名称指示(SNI)有关。使用SNI,您可以在同一IP地址后面拥有多个具有不同证书的主机。虽然所有当前浏览器都支持SNI,但其他实现可能默认情况下不启用或不启用SNI。如果客户端无法在具有相同IP的多个证书的站点上使用SNI,则只能获得默认证书,这通常是错误的证书。
我不是您正在运行的Java版本,但我建议您确定您的版本,然后谷歌了解如何在您的版本中使用SNI。根据我的理解,SNI仅在Java版本7中启用。
答案 1 :(得分:0)
我检查了捕获的网络数据包,发现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结束,还是在服务器端?