我正在努力通过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端口可以通过,所有其他人都拒绝连接。
在研究这个问题的过程中,我已经在网上找了不少地方,还没有找到任何解决方案,有没有人对如何通过代理来解决这个问题有任何建议?
发布于 2015-06-26 14:33:32
while (newlinesSeen < 2) {
如果在状态行之后有更多的标头,即使是响应CONNECT请求,我也不会感到惊讶。您可能应该尝试更灵活地检测标题的末尾(在本例中是响应的结尾),就像here描述的那样,而不是计算新行的数量。
在这个阶段,更多的头肯定会导致Unrecognized SSL message, plaintext connection错误。
if(replyStr.toLowerCase().indexOf( "200 connection established") == -1) {
同样,为了获得更多的灵活性,我不会寻找确切的原因短语,仅仅是状态代码。
https://stackoverflow.com/questions/31075038
复制相似问题