[英]Connect to websocket with self-signed certificate in java
我需要使用 Java 连接到使用自签名证书的 WebSocket 服务器。 我正在尝试使用 Jetty 库,并且在 Java 方面还是很新的,但我发现很难弄清楚需要做什么。 我可以非常简单地使用 NodeJS 进行连接:
const WebSocket = require('ws');
const ws = new WebSocket('wss://192.168.100.220:9000/', ['ws-valence'], {
rejectUnauthorized: false,
});
但是,修改我在Jetty 文档上找到的示例并没有让我走得很远。
我实现了一个与回声测试服务器配合良好的基本客户端,就像上面链接的例子一样。 然后我继续用我自己的协议和 IP 地址配置它:
private static void connectToBasestation() {
// String destUri = "ws://echo.websocket.org";
String basestationUri = "wss://192.168.100.220:9000/";
SslContextFactory ssl = new SslContextFactory(); // ssl config
ssl.setTrustAll(true); // trust all certificates
WebSocketClient client = new WebSocketClient(ssl); // give ssl config to client
BasestationSocket socket = new BasestationSocket();
ArrayList<String> protocols = new ArrayList<String>();
protocols.add("ws-valence");
try
{
client.start();
URI bsUri = new URI(basestationUri);
ClientUpgradeRequest request = new ClientUpgradeRequest();
request.setSubProtocols(protocols);
client.connect(socket, bsUri, request);
System.out.printf("Connecting to : %s%n", bsUri);
// wait for closed socket connection.
socket.awaitClose(5,TimeUnit.SECONDS);
}
catch (Throwable t)
{
t.printStackTrace();
}
finally
{
try
{
client.stop();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
但是,我收到了一个UpgradeException
0 null
的UpgradeException
,并且我的onConnect
方法永远不会被调用。 我猜这是一个安全问题,但我不能确定,因为服务器是一台旧机器——有点像黑匣子。 但我在想也许我的方法有问题? 任何人都可以在这里提供任何建议吗?
编辑 1:按照建议包含可信任的 SSL 工厂。 它没有改变任何东西,包括下面的堆栈跟踪。
编辑 3:上面列出了一个类似的问题,但这是不同的,因为 1) 我收到了不同的错误代码 2) 添加可信任的 SSL 工厂并不能解决问题。
编辑 2:这是我从下面的 OnError 中获得的堆栈跟踪:
Caused by: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:681)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:128)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73)
at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:155)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:291)
at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:151)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
... 3 more
org.eclipse.jetty.websocket.api.UpgradeException: 0 null
at org.eclipse.jetty.websocket.client.WebSocketUpgradeRequest.onComplete(WebSocketUpgradeRequest.java:522)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:216)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:208)
at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:470)
at org.eclipse.jetty.client.HttpReceiver.abort(HttpReceiver.java:552)
at org.eclipse.jetty.client.HttpChannel.abortResponse(HttpChannel.java:156)
at org.eclipse.jetty.client.HttpSender.terminateRequest(HttpSender.java:381)
at org.eclipse.jetty.client.HttpSender.abort(HttpSender.java:566)
at org.eclipse.jetty.client.HttpSender.anyToFailure(HttpSender.java:350)
at org.eclipse.jetty.client.HttpSender$CommitCallback.failed(HttpSender.java:717)
at org.eclipse.jetty.client.http.HttpSenderOverHTTP$HeadersCallback.failed(HttpSenderOverHTTP.java:310)
at org.eclipse.jetty.io.WriteFlusher$PendingState.fail(WriteFlusher.java:263)
at org.eclipse.jetty.io.WriteFlusher.onFail(WriteFlusher.java:516)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint$FailWrite.run(SslConnection.java:1251)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680)
at java.lang.Thread.run(Thread.java:748)
TLS/SSL 握手错误相当普遍。
您不知道问题发生在 TLS/SSL 握手的哪个部分。
您可以在 Java 上使用
-Djavax.net.debug=all
命令行选项来查看 TLS/SSL 握手的原始详细信息,这可能是开始解决问题的好地方。
一些选择...
如果您连接到服务器并且提供的证书与您在 URI 中用于连接的主机名不匹配,则这违反了 Java 本身中存在的端点识别算法。
示例场景:
wss://192.168.1.0:8443/chat
chatserver.acme.com
这是违规行为,因为 URI 192.168.1.0
中的主机名与证书chatserver.acme.com
不匹配
这在使用wss://localhost
或wss://127.0.0.1
测试时尤其常见
你可以告诉 Java 不要像这样执行端点识别检查......
SslContextFactory.Client ssl = new SslContextFactory.Client(); // ssl config
ssl.setEndpointIdentificationAlgorithm(null); // disable endpoint identification algorithm.
WebSocketClient client = new WebSocketClient(ssl); // give ssl config to client
⚠️警告:不推荐这样做,很容易被中间人攻击!
尝试为所有证书启用信任。
示例(假设 Jetty 9.4.19.v20190610 或更新版本):
SslContextFactory.Client ssl = new SslContextFactory.Client(); // ssl config
ssl.setTrustAll(true); // trust all certificates
WebSocketClient client = new WebSocketClient(ssl); // give ssl config to client
⚠️警告:不推荐这样做,很容易被中间人攻击!
用于创建证书的算法将限制在 TLS/SSL 握手期间可用的可用密码套件。
例如,如果服务器只有一个 DSA 证书(已知易受攻击的证书),那么 RSA 或 ECDSA 证书都不可用。
用于创建证书的位数也是相关的,好像服务器证书太少了,那么 Java 本身就会拒绝它。
如果您控制服务器证书,请确保您已生成包含 RSA 和 ECDSA 证书的证书,其中至少 2048 位用于 RSA(或更多),256 位用于 ECDSA。
在 Jetty 端尝试一个空的密码套件排除列表。
⚠️ 警告:这让您可以使用已知的易受攻击的密码套件!
示例(假设 Jetty 9.4.19.v20190610 或更新版本):
SslContextFactory.Client ssl = new SslContextFactory.Client(); // ssl config
ssl.setExcludeCipherSuites(); // blank out the default excluded cipher suites
WebSocketClient client = new WebSocketClient(ssl); // give ssl config to client
⚠️警告:不建议这样做,任何现代计算机(甚至手机)都可以轻松读取您的加密流量
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.