2013-05-03 112 views
6

我正在爲教育目的用Java編寫一個簡單的HTTPS代理程序。我的程序在端口(例如)上偵聽來自瀏覽器的傳入HTTPS請求(如Firefox),解析請求並將其轉發到所需目標(如https://www.comodo.com)。用Java實現簡單的HTTPS代理應用程序?

Firefox的代理設置被設置爲使用我的端口進行SSL連接(127.0.0.1 : 7443)。

我的代碼很簡短:

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); 
} 

但是我趕上了以下異常:

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

例外說,連接可以是純文本,但只有HTTPS連接從Firefox設置爲使用此端口。我已經記錄了哪些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 

火狐在談論佩林文本,我認爲CONNECT是SOCKS命令(我不知道雖然),在那裏我有沒有在Firefox的SOCKS設置中設置任何內容。下面是Firefox的代理設置截圖:

Firefox Proxy Settings

缺少什麼我在這裏?!我需要做什麼才能使這個工作與Firefox或任何其他瀏覽器?!

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

對於那些認爲這是another question的重複,並且它有在另一個我不得不說的問題上得到了回答:是的,這兩個問題都有類似問題的根源,但是引用問題中的唯一答案指向使用SSL套接字,結果導致這個新問題。因此,儘管這些問題針對的是類似的問題,但這個問題表明瞭解決問題的完全不同而又誤導的路徑,因此它可以爲將來面臨這樣一個問題的人們提供有用的指導。

+1

這不是所引用問題的重複。這兩個問題明顯不同,在引用的問題中沒有可接受的解決方案。 – 2013-05-05 11:03:17

+0

對於那些最終在這個線程中的人:您可能對_TheConstructor_的工作示例感興趣:http://stackoverflow.com/questions/16351413/java-https-proxy-using-https-proxyport-and-https-代理主機 – Trinimon 2015-12-04 15:35:15

回答

6

擺脫所有的SSL。只需處理傳入的CONNECT命令,與上游服務器建立明文連接,然後開始複製字節。瀏覽器和服務器會說SSL,但你根本不需要。

+0

我不認爲這是正確的...我以前已經嘗試過這種解決方案,它沒有工作...你可以看看我以前的問題關於這個解決方案在http://stackoverflow.com/questions/14153662/java-https-connection-forwarding – 2013-05-05 06:09:12

+1

當然,這是正確的。請參閱RFC。很顯然,瀏覽器正在以明文形式發送CONNECT命令,顯然你可以推斷出它期望以明文形式回覆,顯然如果你在兩個方向上傳輸所有其他字節而不需要進一步干預,那麼存在的任何問題都必須在服務器或瀏覽器結束。你需要比「它沒有工作」更具體。你引用的另一個問題也沒有提供任何進一步的信息。 – EJP 2013-05-05 10:11:53

+0

正如我所說的,我已經嘗試了你的建議,實際上這是我想到的第一種方法,但它失敗了。正如我提供的另一個問題所述,將瀏覽器的'CONNECT'請求轉發給服務器總是會導致'連接重置'錯誤,這意味着服務器不響應並關閉連接......這種行爲很明顯,因爲服務器正在偵聽443上的SSL/TLS'HELLO'消息,並且它獲得了'CONNECT',這不是預期的SSL/TLS消息。 – 2013-05-05 10:57:41

3

您的設置正在使用HTTP隧道,其中發送到代理的初始請求是而不是 SSL已加密;由於支持SSL的套接字需要SSL握手,因此會引發異常。

在該機構中,客戶要求的HTTP代理服務器轉發使用「CONNECT」 HTTP 方法 TCP連接到期望的目的地。然後服務器繼續代表客戶端 進行連接。一旦服務器建立了連接, 代理服務器將繼續代理與客戶端之間的TCP流,以及來自 客戶端的TCP流。請注意,只有初始連接請求是HTTP - 在 之後,服務器只是代理建立的TCP連接。

你可以在HTTP Tunneling wiki頁面閱讀更多關於它的信息。要看到這個動作,你可以開始一個netcat的服務器,並設置Firefox的代理指向端口:

nc -l 8000 

現在在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 

而這完全在明文。下圖演示了Firefox代理期望通信。

enter image description here

相關問題