2016-04-28 111 views
0

這是使用Java 8,squid 3.1.2和tyrus-standalone-client-1.12.jar爲websocket實現。Tyrus wss:// websocket不通過魷魚代理


UPDATE: 它仍然無法與泰魯斯工作。但是,它似乎問題不是與魷魚,因爲當我讓Chrome使用代理並連接到這裏SO,連接到wss://qa.stackoverflow.com通過魷魚代理,並正常工作。


我使用公認的答案給javax.websocket client simple example測試程序,試圖得到一個Squid代理運行。

但是,我已將其更改爲使用websockets.org回顯服務器,因此URI已從wss://real.okcoin.cn:10440/websocket/okcoinapi更改爲wss://echo.websocket.org

當我不使用代理時,測試程序正常工作,與wss://echo.websocket.orgws://echo.websocket.org

當我通過-Dhttp.proxyHost-Dhttp.proxyPort-Dhttps.proxyHost-Dhttps.proxyPortws:// URI指定一個JVM級代理工作正常,但wss://一個沒有。

我已驗證(使用tcpdump)流量正在進入代理,測試程序正在向代理髮送CONNECT,並且代理髮回了Connection established。然而,在那一點上沒有其他事情發生:

# tcpdump -n -l -s 0 -S -X 'host 172.16.99.15' 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode 
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 
17:21:45.361023 IP 172.16.99.21.36521 > 172.16.99.15.3128: S 1720321489:1720321489(0) win 14600 <mss 1460,sackOK,timestamp 1135431 0,nop,wscale 5> 
     0x0000: 4500 003c 5696 4000 4006 c5e0 ac10 6315 E..<[email protected]@.....c. 
     0x0010: ac10 630f 8ea9 0c38 668a 05d1 0000 0000 ..c....8f....... 
     0x0020: a002 3908 1e74 0000 0204 05b4 0402 080a ..9..t.......... 
     0x0030: 0011 5347 0000 0000 0103 0305   ..SG........ 
17:21:45.361763 IP 172.16.99.15.3128 > 172.16.99.21.36521: S 1626710395:1626710395(0) ack 1720321490 win 14480 <mss 1460,sackOK,timestamp 1127109 1135431,nop,wscale 7> 
     0x0000: 4500 003c 0000 4000 4006 1c77 ac10 630f E..<[email protected]@..w..c. 
     0x0010: ac10 6315 0c38 8ea9 60f5 a17b 668a 05d2 ..c..8..`..{f... 
     0x0020: a012 3890 613d 0000 0204 05b4 0402 080a ..8.a=.......... 
     0x0030: 0011 32c5 0011 5347 0103 0307   ..2...SG.... 
17:21:45.361789 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710396 win 457 <nop,nop,timestamp 1135431 1127109> 
     0x0000: 4500 0034 5697 4000 4006 c5e7 ac10 6315 [email protected]@.....c. 
     0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..| 
     0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5347 .....l........SG 
     0x0030: 0011 32c5        ..2. 
17:21:45.407930 IP 172.16.99.21.36521 > 172.16.99.15.3128: P 1720321490:1720321613(123) ack 1626710396 win 457 <nop,nop,timestamp 1135442 1127109> 
     0x0000: 4500 00af 5698 4000 4006 c56b ac10 6315 [email protected]@..k..c. 
     0x0010: ac10 630f 8ea9 0c38 668a 05d2 60f5 a17c ..c....8f...`..| 
     0x0020: 8018 01c9 1ee7 0000 0101 080a 0011 5352 ..............SR 
     0x0030: 0011 32c5 434f 4e4e 4543 5420 6563 686f ..2.CONNECT.echo 
     0x0040: 2e77 6562 736f 636b 6574 2e6f 7267 3a34 .websocket.org:4 
     0x0050: 3433 2048 5454 502f 312e 310d 0a48 6f73 43.HTTP/1.1..Hos 
     0x0060: 743a 2065 6368 6f2e 7765 6273 6f63 6b65 t:.echo.websocke 
     0x0070: 742e 6f72 670d 0a50 726f 7879 2d43 6f6e t.org..Proxy-Con 
     0x0080: 6e65 6374 696f 6e3a 206b 6565 702d 616c nection:.keep-al 
     0x0090: 6976 650d 0a43 6f6e 6e65 6374 696f 6e3a ive..Connection: 
     0x00a0: 206b 6565 702d 616c 6976 650d 0a0d 0a .keep-alive.... 
17:21:45.408347 IP 172.16.99.15.3128 > 172.16.99.21.36521: . ack 1720321613 win 114 <nop,nop,timestamp 1127121 1135442> 
     0x0000: 4500 0034 93b9 4000 4006 88c5 ac10 630f [email protected]@.....c. 
     0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M 
     0x0020: 8010 0072 c795 0000 0101 080a 0011 32d1 ...r..........2. 
     0x0030: 0011 5352        ..SR 
17:21:45.423007 IP 172.16.99.15.3128 > 172.16.99.21.36521: P 1626710396:1626710435(39) ack 1720321613 win 114 <nop,nop,timestamp 1127124 1135442> 
     0x0000: 4500 005b 93ba 4000 4006 889d ac10 630f E..[[email protected]@.....c. 
     0x0010: ac10 6315 0c38 8ea9 60f5 a17c 668a 064d ..c..8..`..|f..M 
     0x0020: 8018 0072 bdab 0000 0101 080a 0011 32d4 ...r..........2. 
     0x0030: 0011 5352 4854 5450 2f31 2e30 2032 3030 ..SRHTTP/1.0.200 
     0x0040: 2043 6f6e 6e65 6374 696f 6e20 6573 7461 .Connection.esta 
     0x0050: 626c 6973 6865 640d 0a0d 0a    blished.... 
17:21:45.423041 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710435 win 457 <nop,nop,timestamp 1135446 1127124> 
     0x0000: 4500 0034 5699 4000 4006 c5e5 ac10 6315 [email protected]@.....c. 
     0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`... 
     0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 5356 .....l........SV 
     0x0030: 0011 32d4        ..2. 
17:22:15.649132 IP 172.16.99.21.36521 > 172.16.99.15.3128: F 1720321613:1720321613(0) ack 1626710435 win 457 <nop,nop,timestamp 1143003 1127124> 
     0x0000: 4500 0034 569a 4000 4006 c5e4 ac10 6315 [email protected]@.....c. 
     0x0010: ac10 630f 8ea9 0c38 668a 064d 60f5 a1a3 ..c....8f..M`... 
     0x0020: 8011 01c9 1e6c 0000 0101 080a 0011 70db .....l........p. 
     0x0030: 0011 32d4        ..2. 
17:22:15.650241 IP 172.16.99.15.3128 > 172.16.99.21.36521: F 1626710435:1626710435(0) ack 1720321614 win 114 <nop,nop,timestamp 1134681 1143003> 
     0x0000: 4500 0034 93bb 4000 4006 88c3 ac10 630f [email protected]@.....c. 
     0x0010: ac10 6315 0c38 8ea9 60f5 a1a3 668a 064e ..c..8..`...f..N 
     0x0020: 8011 0072 8c5b 0000 0101 080a 0011 5059 ...r.[........PY 
     0x0030: 0011 70db        ..p. 
17:22:15.650255 IP 172.16.99.21.36521 > 172.16.99.15.3128: . ack 1626710436 win 457 <nop,nop,timestamp 1143003 1134681> 
     0x0000: 4500 0034 569b 4000 4006 c5e3 ac10 6315 [email protected]@.....c. 
     0x0010: ac10 630f 8ea9 0c38 668a 064e 60f5 a1a4 ..c....8f..N`... 
     0x0020: 8010 01c9 1e6c 0000 0101 080a 0011 70db .....l........p. 
     0x0030: 0011 5059        ..PY 

這不是代理服務器與Java TLS連接有問題。如果我改爲(仍然使用Java 8)通過代理進行vanilla HTTPS連接(對https://www.google.com),我會看到客戶端發送的相同的CONNECT以及代理髮回的相同的Connection established,但接下來是TLS握手等正常進行,請求/響應正常結束。

坦率地說,我很難理解發生了什麼事(或者說沒有繼續)。

回答

1

我能夠按問題描述的100%重現問題。我使用Squid版本3.5.17(Windows 10 64bit), 本地Tomcat使用帶有「echo」web-socket和Java 7的自簽名證書(但我認爲Java 8沒有任何區別)。
一切工作正常,當我用org.glassfish.tyrus.bundles:tyrus-standalone-client:1.11而不是1.12

我決定使用以前的版本時,我發現這個修正:
2015年/月/ 13:灰熊運輸無法打開通過HTTP代理 (github-commit)WSS連接。

版本1.11於2015年6月發佈,版本1.12 2015年9月,我預計該修訂版本將在版本1.13 (另請參閱pom history)。

this question的解決方案可能是相關的(2015/Aug/21)。

僅供參考,12(在org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT中存在30秒 的硬編碼超時,因此您必須等待一段時間纔會出現錯誤)。

 
05:07:25.514 [Grizzly(1) SelectorRunner] TRACE o.g.t.c.g.c.GrizzlyClientFilter - handleConnect 
Using SSLEngineImpl. 
Allow unsafe renegotiation: false 
Allow legacy hello messages: true 
Is initial handshake: true 
Is secure renegotiation: false 
05:07:25.651 [Grizzly(1)] DEBUG o.g.t.c.g.c.GrizzlyClientFilter - handleRead websocket: null content-size=0 headers= 
HttpResponsePacket (
    status=200 
    reason=Connection established 
    protocol=HTTP/1.1 
    content-length=-1 
    committed=false 
    headers=[] 
) 
javax.websocket.DeploymentException: Connection to 'wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation' failed. 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket._connect(GrizzlyClientSocket.java:398) 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.access$000(GrizzlyClientSocket.java:103) 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket$1.call(GrizzlyClientSocket.java:235) 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket$1.call(GrizzlyClientSocket.java:231) 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientSocket.connect(GrizzlyClientSocket.java:249) 
    at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.openClientSocket(GrizzlyClientContainer.java:95) 
    at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:663) 
    at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:712) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) 
    at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:866) 
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:110) 
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:511) 
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:355) 
    at nl.fw.wsclienttest.WsClient.echoDemo(WsClient.java:69) 
    at nl.fw.wsclienttest.WsClient.main(WsClient.java:41) 

而對於完全不安全的測試客戶端的代碼我使用:

import java.io.IOException; 
import java.net.URI; 
import java.security.KeyStore; 
import java.security.cert.*; 
import java.util.concurrent.*; 

import javax.net.ssl.*; 
import javax.websocket.*; 

import org.glassfish.tyrus.client.*; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.slf4j.bridge.SLF4JBridgeHandler; 

public class WsClient { 

    static { 
     SLF4JBridgeHandler.removeHandlersForRootLogger(); 
     SLF4JBridgeHandler.install(); 
    } 

    private static final Logger log = LoggerFactory.getLogger(WsClient.class); 

    public static void main(String[] args) { 

     System.getProperties().put("javax.net.debug", "ssl,handshake,data,sslctx"); 
     try { 
      new WsClient().echoDemo(); 
      log.info("done"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    // localhost does not work via squid proxy 
    String destUri = "wss://127.0.0.1:8443/wstest/ws/echoAsyncAnnotation"; 
    String proxyUri = "http://localhost:3128"; 
    volatile Session wsSession = null; 

    void echoDemo() throws Exception { 

     final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build(); 
     ClientManager client = ClientManager.createClient(); 
     client.getProperties().put(ClientProperties.PROXY_URI, proxyUri); 
     client.getProperties().put(ClientProperties.SHARED_CONTAINER, false); 

     SSLContext sslCtx = createAllTrustingContext(); 
     SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator(sslCtx, true, false, false); 
     sslEngineConfigurator.setHostVerificationEnabled(false); //skip host verification 
     client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator); 
     // time-out is set to 30 seconds for all operations, so handshake timeout does not work ... 
     // see org.glassfish.tyrus.container.grizzly.client.GrizzlyClientContainer.CLIENT_SOCKET_TIMEOUT 
     client.getProperties().put(ClientProperties.HANDSHAKE_TIMEOUT, 3000); 
     final CountDownLatch messageLatch = new CountDownLatch(1); 
     client.connectToServer(new Endpoint() { 

      @Override 
      public void onOpen(final Session session, EndpointConfig config) { 
       try { 
        session.addMessageHandler(new MessageHandler.Whole<String>() { 

         @Override 
         public void onMessage(String message) { 
          log.info("Received message: {}", message); 
          wsSession = session; 
          messageLatch.countDown(); 
         } 
        }); 
        session.getBasicRemote().sendText("Hello world"); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }, cec, new URI(destUri)); 
     try { 
      messageLatch.await(5, TimeUnit.SECONDS); 
      if (wsSession != null) { 
       wsSession.close(); 
      } 
     } finally { 
      client.shutdown(); 
     } 
    } 

    public static SSLContext createAllTrustingContext() throws Exception { 

     SSLContext ctx = SSLContext.getInstance("TLSv1.2"); 
     KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     kmf.init((KeyStore) null, "changeit".toCharArray()); 
     ctx.init(kmf.getKeyManagers(), new TrustManager[] { new TrustServerCertAlways() }, null); 
     return ctx; 
    } 

    static class TrustServerCertAlways implements X509TrustManager { 

     @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { 
      log.debug("Trusting all client certificates."); 
     } 

     @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { 
      log.debug("Trusting all server certificates."); 
     } 

     @Override public X509Certificate[] getAcceptedIssuers() { 
      log.debug("No accepted issuers."); 
      return null; 
     } 
    } 
} 
+0

謝謝! 1.11工作正常。我會留心1.13。 – QuantumMechanic