赞
踩
现象描述:javax.net.ssl.SSLException: Received fatal alert: internal_error
问题定位:不同版本jdk对ssl/tsl的支持程度不同。我遇到的问题是jdk1.6不支持tlsv1.2导致;
处理登记:jdk版本升级到1.7之后不再报错。
客户端访问服务端报错,如下图:
- 2018-09-13 17:37:21,872 E ReqAcquirer-00445821(default) [HttpClientComm ] - 专线(7-1-2-2-1) @ 组件执行出错,进入异常处理
- javax.net.ssl.SSLException: Received fatal alert: internal_error
- at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.8.0_162]
- at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[na:1.8.0_162]
- at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2038) ~[na:1.8.0_162]
- at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135) ~[na:1.8.0_162]
- at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385) ~[na:1.8.0_162]
httpclient发送请求,应该不是客户端的问题。并且客户端没有对服务端证书做验证,强制信任。所以不应该是客户端报错。
一个可行的方式,网络抓包。服务器通过tcpdump抓网络包,下载文件,通过wireshark打开解析。简单命令如下,需要root权限,详细命令通过tcpdump --help 和man tcpdump可查看。
- #tcpdump --help
- #tcpdump host somehostip and port someport -w client2server.cap
通过wireshark解析如下:
然而这次分析,我并没有看出太多有用的信息。
对于https的握手阶段,我搜索了一张简单直白的图片。
对于每一步的解释如下:
步骤 1: 客户端通过发送 Client Hello 报文开始 SSL 通信。报文中包含客户端支持的 SSL 的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)。
步骤 2: 服务器可进行 SSL 通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL 版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。
步骤 3: 之后服务器发送 Certificate 报文。报文中包含公开密钥证书。
步骤 4: 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的SSL握手协商部分结束。
步骤 5: SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret 的随机密码串。该报文已用步骤 3 中的公开密钥进行加密。
步骤 6: 接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密。
步骤 7: 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准。
步骤 8: 服务器同样发送 Change Cipher Spec 报文。
步骤 9: 服务器同样发送 Finished 报文。
步骤 10: 服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完成。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP请求。
步骤 11: 应用层协议通信,即发送 HTTP 响应。
步骤 12: 最后由客户端断开连接。断开连接时,发送 close_notify 报文。上图做了一些省略,这步之后再发送 TCP FIN 报文来关闭与 TCP 的通信。在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。
下面是对整个流程的图解。图中说明了从仅使用服务器端的公开密钥证书(服务器证书)建立 HTTPS 通信的整个过程
了解了如上https的交互内容,那我们可以强行前进了。到底出现在了哪一部分?
在程序启动脚本中我们增加配置项:javax.net.debug=SSl
|
|
开启了网络SSL的debugging,我们看到可客户端和服务端交互的更多细节:
- trustStore is: /home/bsp/jdk1.8.0_162/jre/lib/security/cacerts
- trustStore type is : jks
- trustStore provider is :
- init truststore
- adding as trusted cert:
- Subject: CN=Equifax Secure Global eBusiness CA-1, O=Equifax Secure Inc., C=US
- Issuer: CN=Equifax Secure Global eBusiness CA-1, O=Equifax Secure Inc., C=US
- Algorithm: RSA; Serial number: 0xc3517
- Valid from Mon Jun 21 12:00:00 CST 1999 until Mon Jun 22 12:00:00 CST 2020
-
- adding as trusted cert:
- Subject: CN=Entrust Root Certification Authority - EC1, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
- Issuer: CN=Entrust Root Certification Authority - EC1, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
- Algorithm: EC; Serial number: 0xa68b79290000000050d091f9
- Valid from Tue Dec 18 23:25:36 CST 2012 until Fri Dec 18 23:55:36 CST 2037
-
- adding as trusted cert:
- Subject: CN=SecureTrust CA, O=SecureTrust Corporation, C=US
- Issuer: CN=SecureTrust CA, O=SecureTrust Corporation, C=US
- Algorithm: RSA; Serial number: 0xcf08e5c0816a5ad427ff0eb271859d0
- Valid from Wed Nov 08 03:31:18 CST 2006 until Tue Jan 01 03:40:55 CST 2030
-
- ......(此处省略N多个证书)
-
- adding as trusted cert:
- Subject: CN=KEYNECTIS ROOT CA, OU=ROOT, O=KEYNECTIS, C=FR
- Issuer: CN=KEYNECTIS ROOT CA, OU=ROOT, O=KEYNECTIS, C=FR
- Algorithm: RSA; Serial number: 0x1121bc276c5547af584eefd4ced629b2a285
- Valid from Tue May 26 08:00:00 CST 2009 until Tue May 26 08:00:00 CST 2020
-
- adding as trusted cert:
- Subject: CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US
- Issuer: CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US
- Algorithm: RSA; Serial number: 0x33af1e6a711a9a0bb2864b11d09fae5
- Valid from Thu Aug 01 20:00:00 CST 2013 until Fri Jan 15 20:00:00 CST 2038
-
- trigger seeding of SecureRandom
- done seeding SecureRandom
- trigger seeding of SecureRandom
- done seeding SecureRandom
- Allow unsafe renegotiation: false
- Allow legacy hello messages: true
- Is initial handshake: true
- Is secure renegotiation: false
- Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
- Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
- Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
- Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
- Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
- Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
- Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
- Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
- Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
- %% No cached client session
- *** ClientHello, TLSv1.2
- RandomCookie: GMT: 1520046760 bytes = { 246, 213, 192, 77, 83, 196, 208, 176, 204, 116, 200, 95, 35, 121, 105, 94, 138, 108, 50, 253, 44, 8, 137, 203, 125, 27, 51, 164 }
- Session ID: {}
- Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
- Compression Methods: { 0 }
- Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
- Extension ec_point_formats, formats: [uncompressed]
- Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
- Extension extended_master_secret
- ***
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, WRITE: TLSv1.2 Handshake, length = 213
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, READ: TLSv1.2 Handshake, length = 652
- *** ServerHello, TLSv1.2
- RandomCookie: GMT: 1520046909 bytes = { 232, 185, 231, 33, 209, 40, 98, 148, 20, 177, 225, 135, 113, 195, 49, 232, 170, 131, 87, 27, 165, 211, 11, 147, 102, 194, 199, 190 }
- Session ID: {91, 154, 19, 61, 215, 22, 4, 237, 187, 180, 61, 215, 190, 132, 29, 16, 215, 91, 34, 217, 220, 113, 154, 65, 48, 43, 81, 238, 94, 79, 21, 0}
- Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256
- Compression Method: 0
- Extension renegotiation_info, renegotiated_connection: <empty>
- ***
- %% Initialized: [Session-3, TLS_RSA_WITH_AES_128_CBC_SHA256]
- ** TLS_RSA_WITH_AES_128_CBC_SHA256
- *** Certificate chain
- chain [0] = [
- [
- Version: V3
- Subject: CN=XXXX, OU=XXXX, O=XXXX, L=XXXX, ST=XXX, C=ZN
- Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
-
- Key: Sun RSA public key, 1024 bits
- modulus: 109660329459022741437327619671185182724841857765365169921016424994461637474017405477331233293849582577525594525417222259293946192607547979725687997737705435309372352898249675054641345778050522664011255588691309420287663442328544092938577243341014550159599942338331465012863451437949619972693990304194043657157
- public exponent: 65537
- Validity: [From: Mon May 07 19:17:10 CST 2018,
- To: Thu May 04 19:17:10 CST 2028]
- Issuer: CN=XXXX, OU=XXXX, O=XXXX, L=XXXXXX, ST=XX, C=ZN
- SerialNumber: [ 5af035b6]
-
- ]
- Algorithm: [SHA1withRSA]
- Signature:
- 0000: 4F E7 8E 68 26 DB 61 EB 6F C9 AA E0 C5 7E 09 2D O..h&.a.o......-
- 0010: A1 E8 5B 60 F0 D1 E0 3F EF C1 AF 20 8D 45 20 9C ..[`...?... .E .
- 0020: E2 6B F5 31 D6 FB 74 38 C3 B7 7C CF E8 27 E7 A7 .k.1..t8.....'..
- 0030: 0F DE C4 87 23 E2 71 F1 F8 DB DF 74 5D 58 31 5C ....#.q....t]X1\
- 0040: 9A C7 52 3F F2 94 4A 11 50 AF 04 8C D4 31 19 F3 ..R?..J.P....1..
- 0050: 44 24 07 F5 40 81 7F 01 D5 95 53 75 1E A6 58 93 D$..@.....Su..X.
- 0060: 8A 99 2E 1F F4 A5 6E 1A 9C 2B 01 E0 25 B2 CC C2 ......n..+..%...
- 0070: 6A 7A FF 33 84 6A CA 8B DF 78 EB F6 CF 5C 4B 62 jz.3.j...x...\Kb
- ]
- ***
- *** ServerHelloDone
- *** ClientKeyExchange, RSA PreMasterSecret, TLSv1.2
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, WRITE: TLSv1.2 Handshake, length = 134
- SESSION KEYGEN:
- PreMaster Secret:
- 0000: 03 03 DC 25 D9 AD D2 6E F7 40 F4 29 4F 1C C5 83 ...%...n.@.)O...
- 0010: 93 98 AA 96 67 17 94 93 37 9D 77 F3 80 BA 32 19 ....g...7.w...2.
- 0020: CB 64 B9 64 4A 97 E9 CB 82 21 A3 12 40 CB C5 8C .d.dJ....!..@...
- CONNECTION KEYGEN:
- Client Nonce:
- 0000: 5B 9A 13 A8 F6 D5 C0 4D 53 C4 D0 B0 CC 74 C8 5F [......MS....t._
- 0010: 23 79 69 5E 8A 6C 32 FD 2C 08 89 CB 7D 1B 33 A4 #yi^.l2.,.....3.
- Server Nonce:
- 0000: 5B 9A 13 3D E8 B9 E7 21 D1 28 62 94 14 B1 E1 87 [..=...!.(b.....
- 0010: 71 C3 31 E8 AA 83 57 1B A5 D3 0B 93 66 C2 C7 BE q.1...W.....f...
- Master Secret:
- 0000: A5 E4 73 1B 10 AA 2B 54 2A AD C1 13 10 8D CF 9D ..s...+T*.......
- 0010: 18 44 E2 E5 CF E5 F8 2A 6B 22 2F C2 42 20 3A 8A .D.....*k"/.B :.
- 0020: 52 3F 49 8D 60 B2 50 8A 22 EA 74 67 5D 34 D4 F1 R?I.`.P.".tg]4..
- Client MAC write Secret:
- 0000: 1F E6 44 34 EF 15 79 83 AD E1 1C 1C 56 FD D7 3A ..D4..y.....V..:
- 0010: 7A E6 F6 0F 09 2B AB 04 E8 BB 30 C1 42 7E 32 AC z....+....0.B.2.
- Server MAC write Secret:
- 0000: AC D5 BC E5 DE E0 AB CF C4 44 95 DE 16 0B 5A E9 .........D....Z.
- 0010: E1 A7 79 D7 CB 31 86 5E 5E CE 0D D9 C3 7E 32 A5 ..y..1.^^.....2.
- Client write key:
- 0000: 83 01 24 CE 30 38 DF E9 22 34 3F F1 5B 8A 16 9A ..$.08.."4?.[...
- Server write key:
- 0000: EB 7E 65 67 93 70 36 57 84 73 5F 7E 1B 0F 68 1F ..eg.p6W.s_...h.
- ... no IV derived for this protocol
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, WRITE: TLSv1.2 Change Cipher Spec, length = 1
- *** Finished
- verify_data: { 129, 146, 65, 253, 207, 111, 59, 106, 159, 92, 106, 141 }
- ***
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, WRITE: TLSv1.2 Handshake, length = 80
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, READ: TLSv1.2 Alert, length = 2
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, RECV TLSv1.2 ALERT: fatal, internal_error
- %% Invalidated: [Session-3, TLS_RSA_WITH_AES_128_CBC_SHA256]
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, called closeSocket()
- NBPS.NBPSOUTTER.ReqAcquirerAliPay/ReqAcquirer-2, handling exception: javax.net.ssl.SSLException: Received fatal alert: internal_error
大家可以自行对照SSL的日志及HTTPS的交互过程对照,发线在上图的倒数第四行的报错信息:
RECV TLSv1.2 ALERT: fatal, internal_error
尽管我还是不知道发生了什么。但是,知道了一件事:当客户端发送*** Finished verify_data即全部报文的整体校验值后,服务器没搭理客户端。那我们理直气壮地去找服务端问问。额,其实问不出什么来。
但是了解到服务端的JDK版本为1.6。直接贴oracle官网图:
服务端采用的1.6jdk根本不支持TLSv1.2。那来一次验证,当把版本升到jdk1.7之后,再发交易,顺利通过。
此时客户端还需要做一件事情,通过设置首选协议及最高支持协议,不展开讲。
- -Dhttps.protocols=TLSv1,TLSv1.1,TLSv1.2
- -Djdk.tls.client.protocols=TLSv1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。