[英]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.