I'm trying to use Java (Android) to connect to a server with a SSL socket. Please note that this is not HTTP data. This is proprietary protocol with a mix of text and binary data.
I want to relay that SSL connection through a HTTP proxy, but I am facing a lot of problems with that. Right now the scenario that I use and that my browser seems to use with a squid proxy is as follow
[client]->[http connection]->[proxy]->[ssl connection]->[server]
This works for the browser, because after the proxy makes the ssl connection, a TLS negotiation takes place immediately. However my code does not seem to do that.
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);
The problem that I have is that createSocket NEVER RETURNS. With a wireshark dump from the proxy machine, I can see that a tcp handshake takes place between the proxy and the server. With dumps from web sessions, I can see that the client usually initiate a SSL handshake at this point, which does not happen in my scenario.
This is not a problem with the trust manager, because the certificate never gets back to me and it is never validated.
EDIT :
After discussion, this is the more complete version of the code I'm trying to run. This version above with the simple (new Socket(...)) as parameter is something I've tried later on.
The original version of the code I'm trying to debug throws
java.net.ConnectException: failed to connect to /192.168.1.100 (port 443): connect failed: ETIMEDOUT (Connection timed out)
The sequence is as follow (a bit simplified again) :
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]
Then read the response with the following code :
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 )
{
}
I can say that this code works because it works without SSL. The socket created here, proxySocket
is the one that is passed to the createSocket function instead of just creating a new one on the fly like in my original example.