我正在尝试使用Java(Android)连接到具有SSL套接字的服务器.请注意,这不是HTTP数据.这是具有文本和二进制数据混合的专有协议.
我想通过HTTP代理中继SSL连接,但我遇到了很多问题.现在我使用的场景以及我的浏览器似乎与squid代理一起使用的场景如下
[客户端] - > [http连接] - > [代理] - > [ssl连接] - > [服务器]
这适用于浏览器,因为在代理进行ssl连接后,立即进行TLS协商.但是我的代码似乎没有这样做.
final TrustManager[] trustManager = new TrustManager[] { new MyX509TrustManager() };
final SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManager, null);
SSLSocketFactory factory = context.getSocketFactory();
Socket s = factory.createSocket(new Socket(proxy_ip, 3128), hostName, port, true);
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是createSocket NEVER RETURNS.通过代理机器的wireshark转储,我可以看到代理和服务器之间发生了tcp握手.通过Web会话转储,我可以看到客户端通常会在此时启动SSL握手,这在我的方案中不会发生.
这对于信任管理器来说不是问题,因为证书永远不会回复给我并且永远不会被验证.
编辑:
经过讨论,这是我正在尝试运行的代码的更完整版本.上面这个版本的简单(新的Socket(...))作为参数是我后来尝试过的.
我试图调试的代码的原始版本抛出
java.net.ConnectException: failed to connect to /192.168.1.100 (port 443): connect failed: ETIMEDOUT (Connection timed out)
顺序如下(再次简化):
final Socket proxySocket = new Socket();
proxySocket.connect(proxyAddress, 2000); // 2 seconds as the connection timeout for connecting to the proxy server
[Start a thread and write to outputStream=socket.getOutputStream()]
final String proxyRequest = String.format("CONNECT %s:%d HTTP/1.1\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: %s:%d\r\n\r\n", hostName, port, hostName, port);
outputStream.close(); // Closing or not doesn't change anything
[Stop using that thread and let it exit by reaching the end of its main function]
Run Code Online (Sandbox Code Playgroud)
然后使用以下代码阅读响应:
final InputStreamReader isr = new InputStreamReader(proxySocket.getInputStream());
final BufferedReader br = new BufferedReader(isr);
final String statusLine = br.readLine();
boolean proxyConnectSuccess = false;
// readLine consumed the CRLF
final Pattern statusLinePattern = Pattern.compile("^HTTP/\\d+\\.\\d+ (\\d\\d\\d) .*");
final Matcher statusLineMatcher = statusLinePattern.matcher(statusLine);
if (statusLineMatcher.matches())
{
final String statusCode = statusLineMatcher.group(1);
if (null != statusCode && 0 < statusCode.length() && '2' == statusCode.charAt(0))
{
proxyConnectSuccess = true;
}
}
// Consume rest of proxy response
String line;
while ( "".equals((line = br.readLine())) == false )
{
}
Run Code Online (Sandbox Code Playgroud)
我可以说这段代码有效,因为它没有SSL.这里创建的套接字proxySocket是传递给createSocket函数的套接字,而不是像我原来的例子一样动态创建一个新套接字.
use*_*421 15
java.net.Proxy或者https.proxyHost/proxyPort属性,仅HttpURLConnection,通过a来支持HTTP代理Socket.
为了使SSLSocket你自己的工作,您需要创建一个纯文本套接字,HTTP CONNECT在其上发出命令,检查200的响应,然后将其包装在一个SSLSocket.
编辑发送CONNECT命令时,当然不能关闭套接字; 在阅读回复时,你不能使用BufferedReader,否则会丢失数据; 要么手工阅读,要么DataInputStream.readLine(),尽管不赞成使用.您还需要完全遵循RFC 2616.
小智 6
你必须使用javax.net lib.您可以使用javax.net.ssl.*归档到目标.
我想你可以使用oracle docs获得解决方案.这是链接.
| 归档时间: |
|
| 查看次数: |
10387 次 |
| 最近记录: |