繁体   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