2013-05-03 6 views
6

Ich schreibe ein einfaches HTTPS-Proxy-Programm mit Java für Bildungszwecke. Mein Programm hört auf einem Port (zB) nach eingehenden HTTPS-Anfragen von einem Browser (zB Firefox), analysiert die Anfrage und leitet sie an das gewünschte Ziel weiter (zB https://www.comodo.com).Implementierung einer einfachen HTTPS-Proxy-Anwendung mit Java?

Die Proxy-Einstellungen von Firefox sind so eingestellt, dass sie meinen Port für SSL-Verbindungen verwenden (127.0.0.1 : 7443).

Mein Code ist kurz und einfach:

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

Aber ich fange die folgende Ausnahme:

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

Die Ausnahme besagt, dass die Verbindung Klartext sein könnte, aber nur HTTPS-Verbindungen von Firefox sind auf diesen Port eingestellt. Ich habe angemeldet, was Firefox meine Anwendung sendet, welche das ist:

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 spricht palin-Text, und ich denke, CONNECT ist ein SOCKS-Befehl (ich bin aber nicht sicher), wo ich nicht Legen Sie alles in den SOCKS-Einstellungen von Firefox fest. Nachstehend ist ein Screenshot von Proxy-Einstellungen des Firefox:

Firefox Proxy Settings

Was ich hier fehlt?! Was muss ich tun, damit dies mit Firefox oder einem anderen Browser funktioniert?

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

Für diejenigen, die denken, dass dies ein Duplikat von another question ist und das es hat In der anderen Frage muss ich antworten: Ja, beide Fragen haben Wurzeln in einem ähnlichen Problem, aber die einzige Antwort in der zitierten Frage bezieht sich auf die Verwendung von SSL Sockets, die sich als irreführend herausstellte und zu dieser neuen Frage führte. Obwohl sie auf ein ähnliches Problem abzielen, zeigt diese Frage einen völlig anderen und doch irreführenden Weg zur Lösung des Problems und könnte somit eine nützliche Orientierungshilfe für zukünftige Personen sein, die sich mit einem solchen Problem konfrontiert sehen.

+1

Dies ist kein Duplikat der genannten Frage. Die beiden Fragen sind eindeutig verschieden, und in der zitierten Frage gibt es keine akzeptable Lösung. –

+0

Für diejenigen, die in diesem Thread gelandet sind: Sie könnten sich für das Arbeitsbeispiel von _TheConstructor_ interessieren: http://StackOverflow.com/Questions/16351413/Java-https-Proxy-using-https-Proxyport-und-https- proxyhost – Trinimon

Antwort

6

Entfernen Sie alle SSL. Verarbeiten Sie einfach den eingehenden CONNECT-Befehl, stellen Sie eine Klartextverbindung zum Upstream-Server her und starten Sie anschließend das Kopieren der Bytes. Der Browser und der Server sprechen SSL, müssen aber nicht.

+0

Ich glaube nicht, dass das korrekt ist ... Ich habe diese Lösung bereits ausprobiert und es hat nicht funktioniert ... Sie können meine vorherige Frage zu dieser Lösung unter http://stackoverflow.com/questions/14153662 überprüfen/java-https-connection-forwarding –

+1

Sicher ist es richtig. Siehe RFC. Offensichtlich sendet der Browser den CONNECT-Befehl im Klartext, und offensichtlich können Sie daraus schließen, dass er die Antwort im Klartext erwartet, und natürlich, wenn Sie alle anderen Bytes in beide Richtungen unverändert übertragen, müssen alle Probleme bestehen bleiben der Server oder Browser endet. Sie müssen genauer sein als "es hat nicht funktioniert". Die andere Frage, die Sie zitiert haben, liefert auch keine weiteren Informationen. – EJP

+0

Wie ich schon sagte, ich habe genau das versucht, was Sie vorschlagen, und tatsächlich war dies die erste Methode, die mir in den Sinn kam, aber sie scheiterte. Wie in der anderen Frage erwähnt, führt die Weiterleitung der 'CONNECT'-Anfrage des Browsers an den Server immer zu einem' Verbindungsreset'-Fehler, was bedeutet, dass der Server nicht antwortet und die Verbindung schließt ... Dieses Verhalten ist offensichtlich, weil der Server auf 443 auf eine SSL/TLS 'HALLO'-Nachricht wartet, und er erhält eine' CONNECT', die keine erwartete SSL/TLS-Nachricht ist. –

3

Ihr Setup verwendet HTTP-Tunneling, wobei die erste an den Proxy gesendete Anforderung nicht SSL-verschlüsselt ist; Da der SSL-fähige Socket einen SSL-Handshake erwartet, wird eine Ausnahme ausgelöst.

Bei diesem Mechanismus, fragt der Client einen HTTP-Proxy-Server die TCP-Verbindung zu dem gewünschten Ziel unter Verwendung der „CONNECT“ HTTP Verfahren zu übermitteln. Der Server fährt dann fort, die Verbindung im Auftrag von dem Client herzustellen. Sobald die Verbindung vom Server hergestellt wurde, sendet der Proxy-Server weiterhin den TCP-Datenstrom an und von dem -Client . Beachten Sie, dass nur die anfängliche Verbindungsanforderung HTTP ist - nach , dass der Server einfach die aufgebaute TCP-Verbindung verwendet.

Sie können mehr darüber unter HTTP Tunneling Wiki-Seite lesen. Um dies zu sehen in Aktion können Sie einen netcat-Server starten und stellen Sie den Firefox-Proxy auf diesem Port Punkt:

nc -l 8000 

Jetzt in Firefox Typ in https://www.google.com, und untersuchen Sie die NC-Ausgabe:

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 

Und das ist komplett in Klartext. Unten zeigt Diagramm, wie Firefox Proxy erwartet zu kommunizieren.

enter image description here