Websocket (spring) ssl 连接(空链)
Websocket (spring) ssl connection (empty chain)
美好的一天!我有一个带有 websocket (STOMP) 的简单聊天应用程序。
我已经配置了带有相互身份验证的 ssl 连接。
服务器端:
server.port=8443
server.ssl.key-store=path/to/server.jks
server.ssl.trust-store=path/to/trusted.jks
server.ssl.key-store-password=22222222
server.ssl.trust-store-password=22222222
server.ssl.client-auth=need
客户:
System.setProperty("javax.net.ssl.keyStore","path/to/client.jks");
System.setProperty("javax.net.ssl.keyStorePassword","22222222");
System.setProperty("javax.net.ssl.trustStore","path/to/trusted.jks");
System.setProperty("javax.net.ssl.trustStorePassword","22222222");
服务器trusted.jks和客户端trusted.jks相同。
所以当我尝试连接
-Djavax.net.debug=ssl
我得到很多输出和一些奇怪的情况 - 我可以看到两个(?)密钥协议。第一个没问题 -
trustStore is: /path/to/trusted.jks
adding as trusted cert:
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Issuer: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Algorithm: RSA; Serial number: 0x9952f188496b2545
Valid from Wed Jun 28 15:39:04 MSK 2017 until Sat Jun 26 15:39:04 MSK 2027
所以我的 CA 证书被添加为受信任的。然后
*** ClientHello, TLSv1.2
//ok
*** ServerHello, TLSv1.2
//ok
*** Certificate chain
//my localhost server cert
***
Found trusted certificate:
Version: V3
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
所以我的客户端找到了该服务器证书的可信证书。
*** ECDH ServerKeyExchange
//ok
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
*** ServerHelloDone
而且我可以找到我的 CHAIN -
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: EMAILADDRESS=client3@mail.ru, CN=client3, OU=client3, O=client3, L=client3, ST=client3, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
chain [1] = [
[
Version: V3
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
*** ECDHClientKeyExchange
*** CertificateVerify
*** Finished
据我所知-没关系。
然后我可以看到:
DEBUG org.springframework.web.client.RestTemplate - GET request for "https://localhost:8443/chat/info" resulted in 200 (null)
DEBUG org.springframework.web.socket.sockjs.client.WebSocketTransport - Starting WebSocket session on wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket
DEBUG org.springframework.web.socket.client.standard.StandardWebSocketClient -
Connecting to wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket
再次添加信任库证书等,都是一样的,但是
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
所以服务器对我说
ttps-jsse-nio-8443-exec-9, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
对问题有什么想法吗?如果需要,我可以在此处 post 我的密钥库和客户端实现。
谢谢你的帮助!
更新卷曲输出
env -i curl -E ./chain.pem --key ./client.key --cacert ca.crt --verbose --user test:test https://localhost:8443/
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* found 1 certificates in ca.crt
* found 704 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: localhost (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject:
C=RU,ST=localhost,
L=localhost,O=localhost,OU=localhost,
CN=localhost,EMAIL=localhost@mail.com
* start date: Wed, 28 Jun 2017 13:07:14 GMT
* expire date: Thu, 28 Jun 2018 13:07:14 GMT
* issuer: C=RU,ST=ca,L=ca,O=ca,OU=ca,CN=ca,EMAIL=ca@ca.com
* compression: NULL
* ALPN, server did not agree to a protocol
* Server auth using Basic with user 'kitcpp'
> GET / HTTP/1.1
> Host: localhost:8443
> Authorization: Basic a2l0Y3BwOmtpdGNwcA==
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: DENY
< Set-Cookie: JSESSIONID=67BACDE78AF68627516075B29C987C86; Path=/; Secure; HttpOnly
< Last-Modified: Wed, 28 Jun 2017 16:29:53 GMT
< Accept-Ranges: bytes
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Content-Length: 6935
< Date: Fri, 30 Jun 2017 09:30:02 GMT
<
<!DOCTYPE html>
<html>
<head>
//and so on (my web chat page)
您正在使用 Tomcat 的 WebSocket 客户端。 Its documentation 描述了应该如何配置它以使用 SSL:
When using the WebSocket client to connect to secure server endpoints, the client SSL configuration is controlled by the userProperties of the provided javax.websocket.ClientEndpointConfig
. The following user properties are supported:
org.apache.tomcat.websocket.SSL_CONTEXT
org.apache.tomcat.websocket.SSL_PROTOCOLS
org.apache.tomcat.websocket.SSL_TRUSTSTORE
org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD
…
If the org.apache.tomcat.websocket.SSL_CONTEXT
property is set then the org.apache.tomcat.websocket.SSL_TRUSTSTORE
and org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD
properties will be ignored.
您正在使用 Spring 的 WebSocket,它正在为您创建 ClientEndpointConfig
。要配置其用户属性,您可以在 StandardWebSocketClient
上设置它们,然后它将在创建 ClientEndpointConfig
时使用它们。例如,假设默认的 SSL 上下文就足够了:
StandardWebSocketClient simpleWebSocketClient =
new StandardWebSocketClient();
Map<String, Object> userProperties = new HashMap<>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", SSLContext.getDefault());
simpleWebSocketClient.setUserProperties(userProperties);
美好的一天!我有一个带有 websocket (STOMP) 的简单聊天应用程序。 我已经配置了带有相互身份验证的 ssl 连接。
服务器端:
server.port=8443
server.ssl.key-store=path/to/server.jks
server.ssl.trust-store=path/to/trusted.jks
server.ssl.key-store-password=22222222
server.ssl.trust-store-password=22222222
server.ssl.client-auth=need
客户:
System.setProperty("javax.net.ssl.keyStore","path/to/client.jks");
System.setProperty("javax.net.ssl.keyStorePassword","22222222");
System.setProperty("javax.net.ssl.trustStore","path/to/trusted.jks");
System.setProperty("javax.net.ssl.trustStorePassword","22222222");
服务器trusted.jks和客户端trusted.jks相同。
所以当我尝试连接
-Djavax.net.debug=ssl
我得到很多输出和一些奇怪的情况 - 我可以看到两个(?)密钥协议。第一个没问题 -
trustStore is: /path/to/trusted.jks
adding as trusted cert:
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Issuer: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Algorithm: RSA; Serial number: 0x9952f188496b2545
Valid from Wed Jun 28 15:39:04 MSK 2017 until Sat Jun 26 15:39:04 MSK 2027
所以我的 CA 证书被添加为受信任的。然后
*** ClientHello, TLSv1.2
//ok
*** ServerHello, TLSv1.2
//ok
*** Certificate chain
//my localhost server cert
***
Found trusted certificate:
Version: V3
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
所以我的客户端找到了该服务器证书的可信证书。
*** ECDH ServerKeyExchange
//ok
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
*** ServerHelloDone
而且我可以找到我的 CHAIN -
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: EMAILADDRESS=client3@mail.ru, CN=client3, OU=client3, O=client3, L=client3, ST=client3, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
chain [1] = [
[
Version: V3
Subject: EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
*** ECDHClientKeyExchange
*** CertificateVerify
*** Finished
据我所知-没关系。 然后我可以看到:
DEBUG org.springframework.web.client.RestTemplate - GET request for "https://localhost:8443/chat/info" resulted in 200 (null)
DEBUG org.springframework.web.socket.sockjs.client.WebSocketTransport - Starting WebSocket session on wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket
DEBUG org.springframework.web.socket.client.standard.StandardWebSocketClient -
Connecting to wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket
再次添加信任库证书等,都是一样的,但是
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<EMAILADDRESS=ca@ca.com, CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
所以服务器对我说
ttps-jsse-nio-8443-exec-9, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
对问题有什么想法吗?如果需要,我可以在此处 post 我的密钥库和客户端实现。 谢谢你的帮助!
更新卷曲输出
env -i curl -E ./chain.pem --key ./client.key --cacert ca.crt --verbose --user test:test https://localhost:8443/
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* found 1 certificates in ca.crt
* found 704 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: localhost (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject:
C=RU,ST=localhost,
L=localhost,O=localhost,OU=localhost,
CN=localhost,EMAIL=localhost@mail.com
* start date: Wed, 28 Jun 2017 13:07:14 GMT
* expire date: Thu, 28 Jun 2018 13:07:14 GMT
* issuer: C=RU,ST=ca,L=ca,O=ca,OU=ca,CN=ca,EMAIL=ca@ca.com
* compression: NULL
* ALPN, server did not agree to a protocol
* Server auth using Basic with user 'kitcpp'
> GET / HTTP/1.1
> Host: localhost:8443
> Authorization: Basic a2l0Y3BwOmtpdGNwcA==
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: DENY
< Set-Cookie: JSESSIONID=67BACDE78AF68627516075B29C987C86; Path=/; Secure; HttpOnly
< Last-Modified: Wed, 28 Jun 2017 16:29:53 GMT
< Accept-Ranges: bytes
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Content-Length: 6935
< Date: Fri, 30 Jun 2017 09:30:02 GMT
<
<!DOCTYPE html>
<html>
<head>
//and so on (my web chat page)
您正在使用 Tomcat 的 WebSocket 客户端。 Its documentation 描述了应该如何配置它以使用 SSL:
When using the WebSocket client to connect to secure server endpoints, the client SSL configuration is controlled by the userProperties of the provided
javax.websocket.ClientEndpointConfig
. The following user properties are supported:
org.apache.tomcat.websocket.SSL_CONTEXT
org.apache.tomcat.websocket.SSL_PROTOCOLS
org.apache.tomcat.websocket.SSL_TRUSTSTORE
org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD
…
If the
org.apache.tomcat.websocket.SSL_CONTEXT
property is set then theorg.apache.tomcat.websocket.SSL_TRUSTSTORE
andorg.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD
properties will be ignored.
您正在使用 Spring 的 WebSocket,它正在为您创建 ClientEndpointConfig
。要配置其用户属性,您可以在 StandardWebSocketClient
上设置它们,然后它将在创建 ClientEndpointConfig
时使用它们。例如,假设默认的 SSL 上下文就足够了:
StandardWebSocketClient simpleWebSocketClient =
new StandardWebSocketClient();
Map<String, Object> userProperties = new HashMap<>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", SSLContext.getDefault());
simpleWebSocketClient.setUserProperties(userProperties);