简体   繁体   English

使用Java实现简单的HTTPS代理应用程序?

[英]Implementing a Simple HTTPS Proxy Application with Java?

I'm writing a simple HTTPS proxy program with Java for educational purposes. 我正在用Java编写一个简单的HTTPS代理程序用于教育目的。 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 ). 我的程序在一个端口(比如7443 )上侦听来自浏览器(比如Firefox )的传入HTTPS请求,解析请求并将其转发到所需的目的地(比如https://www.comodo.com )。

Firefox's proxy settings are set to use my port for SSL connections ( 127.0.0.1 : 7443 ). Firefox的代理设置设置为使用我的端口进行SSL连接( 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. 例外情况表明连接可以是纯文本,但只有来自Firefox的HTTPS连接设置为使用此端口。 I have logged what Firefox is sending to my application which is this: 我已经记录了Firefox发送到我的应用程序的内容,这是:

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. Firefox正在谈论palin-text,我认为CONNECT是一个SOCKS命令(我不确定),我没有在Firefox的SOCKS设置中设置任何内容。 Below is a screenshot of Firefox's proxy settings: 以下是Firefox代理设置的屏幕截图:

Firefox代理设置

What am I missing here ?! 我在这里错过了什么?! What I need to do to make this work with Firefox or any other browser ?! 我需要做些什么来使用Firefox或任何其他浏览器?

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

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. 对于那些认为这是另一个问题的副本并且已经在另一个问题中得到回答的人我不得不说:是的,这两个问题都源于类似的问题,但引用问题中的唯一答案是指导使用SSL套接字。结果是误导,导致了这个新问题。 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. 因此,尽管它们针对的是类似的问题,但这个问题显示出解决问题的完全不同但又误导的路径,因此它可以为面临此类问题的未来人员提供有用的指导。

Get rid of all the SSL. 摆脱所有的SSL。 Just process the incoming CONNECT command, make a plaintext connection to the upstream server, and then start copying bytes. 只需处理传入的CONNECT命令,与上游服务器建立明文连接,然后开始复制字节。 The browser and the server will speak SSL but you don't need to at all. 浏览器和服务器将使用SSL,但您根本不需要。

Your setup is using HTTP tunneling, where the initial request sent to the proxy is not SSL encrypted; 您的设置使用HTTP隧道,其中发送到代理的初始请求不是 SSL加密的; since the SSL-enabled socket is expecting an SSL handshake, it throws an exception. 由于启用SSL的套接字期望进行SSL握手,因此会引发异常。

In this mechanism, the client asks an HTTP Proxy server to forward the TCP connection to the desired destination using the "CONNECT" HTTP method. 在此机制中,客户端要求HTTP代理服务器使用“CONNECT”HTTP方法将TCP连接转发到所需目标。 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. 一旦服务器建立了连接,代理服务器就会继续将TCP流代理到客户端或从客户端代理TCP流。 Note that only the initial connection request is HTTP - after that, the server simply proxies the established TCP connection. 请注意,只有初始连接请求是HTTP - 之后,服务器只是代理已建立的TCP连接。

You can read more about it at HTTP Tunneling wiki page. 您可以在HTTP隧道维基页面上阅读更多相关信息。 To see this in action, you can start off a netcat server and set the Firefox proxy to point to that port: 要查看此操作,您可以启动netcat服务器并将Firefox代理设置为指向该端口:

nc -l 8000

Now in Firefox type in https://www.google.com , and examine the nc output: 现在在Firefox中输入https://www.google.com ,并检查nc输出:

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. 下图演示了Firefox代理如何进行通信。

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM