簡體   English   中英

通過Java中的HTTP代理創建TLS連接

[英]Creating a TLS connection through an HTTP proxy in Java

我正在嘗試通過Java中的TLS連接來連接服務。 我能夠在一個環境中連接服務並獲得響應,但似乎無法在使用防火牆和代理服務器的另一個環境中通過。 在這種環境下,我的應用程序試圖直接穿過防火牆並返回未知的主機異常。

我找到了一些非常簡單的代碼來處理並以這種方式實現-這不是真正的IP,但端口為8080。此外,我也不會保留IP的硬編碼,這只是出於測試目的。

String tunnelHost = "111.11.11.11";
int tunnelPort = 8080;
Socket proxyTunnel = new Socket(InetAddress.getByName(tunnelHost), tunnelPort);
socket = (SSLSocket)factory.createSocket(proxyTunnel, path.getHost(), path.getPort(), true);

這段代碼會思考很長時間,最終會引發另一個異常-javax.net.ssl.SSLHandshakeException:握手期間遠程主機關閉連接

我發現該代碼甚至都沒有到達代理服務器,因此我嘗試通過一些我在網上看到的代碼來實現“隧道握手”,從而制作了完整的代碼-

String tunnelHost = "111.11.11.11";
int tunnelPort = 8080;
Socket proxyTunnel = new Socket(InetAddress.getByName(tunnelHost), tunnelPort);
doTunnelHandshake(proxyTunnel, path.getHost(), path.getPort());
try {
    socket = (SSLSocket)factory.createSocket(proxyTunnel, path.getHost(), path.getPort(), true);
} catch(IOException e) {
    e.printStackTrace();
}

public void doTunnelHandshake(Socket tunnel, String host, int port) throws IOException {
    OutputStream out = tunnel.getOutputStream();  
    String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"  
            + "User-Agent: "  
            + sun.net.www.protocol.http.HttpURLConnection.userAgent  
            + "\r\n\r\n";  
    byte b[];  
    try {  
        b = msg.getBytes("ASCII7");  
    } catch (UnsupportedEncodingException ignored) {  
        b = msg.getBytes();  
    }  
    out.write(b);  
    out.flush();  
    byte reply[] = new byte[200];  
    int replyLen = 0;  
    int newlinesSeen = 0;  
    boolean headerDone = false;     /* Done on first newline */  
    InputStream in = tunnel.getInputStream();
    try {
        while (newlinesSeen < 2) {
            int i = in.read();  
            if (i < 0) {  
                throw new IOException("Unexpected EOF from proxy");  
            }  
            if (i == '\n') {  
                headerDone = true;  
                ++newlinesSeen;  
            } else if (i != '\r') {  
                newlinesSeen = 0;  
                if (!headerDone && replyLen < reply.length) {  
                    reply[replyLen++] = (byte) i;  
                }
            }
        }
        String replyStr;
        try {
            replyStr = new String(reply, 0, replyLen, "ASCII7");
        } catch (UnsupportedEncodingException ignored) {
            replyStr = new String(reply, 0, replyLen);
        }
        if(replyStr.toLowerCase().indexOf(
                "200 connection established") == -1) {
        throw new IOException("Unable to tunnel through proxy."
                + " Proxy returns \"" + replyStr + "\"");
        }
    } catch (Exception e) {
        e.printStackTrace();
        log.fine("Tunnel Handshake Failed");
    }
    log.finer("Tunnel Handshake Completed");
}

這段代碼給了我另一個錯誤

javax.net.ssl.SSLException:無法識別的SSL消息,純文本連接?

因此,似乎正在嘗試使用TLS通過代理端口8080並失敗。 另外,我沒有HTTPS端口可以通過,其他所有端口都拒絕連接。

我已經在網上研究過很多地方,但沒有找到任何解決方案,有人對如何通過代理工作有任何建議嗎?

while (newlinesSeen < 2) {

如果您在狀態行之后有更多標頭,即使是響應CONNECT請求,我也不會感到驚訝。 你應該嘗試檢測頭的結束(在這種情況下,響應結束)更靈活,如所描述這里 ,而不是計算的新線的數量。

當然,更多的標頭肯定會導致Unrecognized SSL message, plaintext connection錯誤。

  if(replyStr.toLowerCase().indexOf( "200 connection established") == -1) { 

同樣,為了獲得更大的靈活性,我不會尋找確切的原因短語,而只是尋找狀態代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM