Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to connect a SSL socket through a HTTP proxy?

Tags:

java

android

ssl

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.

like image 999
Eric Avatar asked Jan 16 '15 08:01

Eric


People also ask

What is HTTP proxy SSL?

HTTPS (Hypertext Transfer Protocol over Secure Socket Layer, or HTTP over SSL) is a request/response protocol between clients and servers used for secure communications and transactions.

Can I use HTTP proxy for https?

End-to-end security is achieved by establishing a secure channel between the client and the server after the proxy has connected to the server and confirmed the operation to the client. An HTTP proxy should not be used for HTTPS resources for purposes other than debugging or espionage.

What is SSLSocketFactory Java?

SSLSocketFactory acts as a factory for creating secure sockets. This class is an abstract subclass of javax. net. SocketFactory . Secure socket factories encapsulate the details of creating and initially configuring secure sockets.


2 Answers

java.net.Proxy, or the https.proxyHost/proxyPort properties, only support HTTP proxying via HttpURLConnection, not via a Socket.

To make that work for an SSLSocket of your own, all you need to to is create a plaintext socket, issue an HTTP CONNECT command on it, check the response for 200, and then wrap it in an SSLSocket.

EDIT When sending the CONNECT command, you must not close the socket, of course; and when reading its reply you must not use a BufferedReader, otherwise you will lose data; either read the line by hand or use DataInputStream.readLine(), despite its deprecation. You also need to follow RFC 2616 entirely.

like image 81
user207421 Avatar answered Sep 21 '22 14:09

user207421


You have to use javax.net lib . you can archive to your target using javax.net.ssl.*.

I think you can get solution using oracle docs. Here is the link for that.

SSLSocketClientWithTunneling

like image 45
MadukaJ Avatar answered Sep 21 '22 14:09

MadukaJ