Pregunta

I'm writing a simple HTTPS proxy program with Java for educational purposes. My program listens on a port (say 7443) for incoming HTTPS requests from a browser (say Firefox), parses the request and forwards it to the desired destination (say https://www.comodo.com).

Firefox's proxy settings are set to use my port for SSL connections ( 127.0.0.1 : 7443 ).

My code is short and simple:

static // initializer
{
    System.setProperty("javax.net.ssl.keyStore", "MyKeyStore");
    System.setProperty("javax.net.ssl.keyStorePassword", "password");
}

SSLServerSocketFactory ssFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();

try {
    SSLServerSocket listener = (SSLServerSocket) ssFactory.createServerSocket(port, 64);
    listener.setUseClientMode(false);
    listener.setWantClientAuth(false);
    listener.setNeedClientAuth(false);

    SSLSocket connection = (SSLSocket) listener.accept();
    browser.startHandshake();  /*  <<==  Exception throws at this line  */

} catch (IOException ex) {
    ex.printStackTrace(System.err);
}

But I'm catching the following exception:

    javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

The exception says that the connection could be plain-text, but only HTTPS connections from Firefox are set to use this port. I have logged what Firefox is sending to my application which is this:

CONNECT www.comodo.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.comodo.com

Firefox is talking palin-text, and I think CONNECT is a SOCKS command (I'm not sure though), where I haven't set anything in Firefox's SOCKS settings. Below is a screenshot of Firefox's proxy settings:

Firefox Proxy Settings

What am I missing here ?! What I need to do to make this work with Firefox or any other browser ?!

------------------------------------------------------------------------------

For those who think this is a duplicate of another question and that it has been answered in the other one I have to say: Yes, both questions have roots in a similar problem but the only answer in the cited question directs at using SSL Sockets which turned out to be misleading and resulted in this new question. So although they are aimed at a similar problem, this question shows a completely different and yet mislead path to go for solving the problem and so it could provide useful guidance for future persons facing such a problem.

¿Fue útil?

Solución

Get rid of all the SSL. Just process the incoming CONNECT command, make a plaintext connection to the upstream server, and then start copying bytes. The browser and the server will speak SSL but you don't need to at all.

Otros consejos

Your setup is using HTTP tunneling, where the initial request sent to the proxy is not SSL encrypted; since the SSL-enabled socket is expecting an SSL handshake, it throws an exception.

In this mechanism, the client asks an HTTP Proxy server to forward the TCP connection to the desired destination using the "CONNECT" HTTP method. The server then proceeds to make the connection on behalf of the client. Once the connection has been established by the server, the Proxy server continues to proxy the TCP stream to and from the client. Note that only the initial connection request is HTTP - after that, the server simply proxies the established TCP connection.

You can read more about it at HTTP Tunneling wiki page. To see this in action, you can start off a netcat server and set the Firefox proxy to point to that port:

nc -l 8000

Now in Firefox type in https://www.google.com, and examine the nc output:

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) 
Proxy-Connection: keep-alive
Connection: keep-alive
Host: www.google.com

And this is completely in plaintext. Below diagram demonstrates how Firefox proxy expects to communicate.

enter image description here

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top