HTTPS-Verbindungen über Proxyserver

Antworten:

65

TLS / SSL (The S in HTTPS) garantiert, dass sich zwischen Ihnen und dem Server, den Sie kontaktieren, keine Lauscher befinden, dh keine Proxys. Normalerweise CONNECTöffnen Sie eine TCP-Verbindung über den Proxy. In diesem Fall kann der Proxy keine Anforderungen / Antworten zwischenspeichern, lesen oder ändern und ist daher eher nutzlos.

Wenn der Proxy Informationen lesen soll, können Sie folgendermaßen vorgehen:

  1. Der Client startet die HTTPS-Sitzung
  2. Der Proxy fängt die Verbindung transparent ab und gibt ein Ad-hoc-generiertes (möglicherweise schwaches) Zertifikat K a zurück , das von einer Zertifizierungsstelle signiert wurde, der vom Client unbedingt vertraut wird.
  3. Der Proxy startet die HTTPS-Sitzung zum Ziel
  4. Der Proxy überprüft die Integrität des SSL-Zertifikats. Zeigt einen Fehler an, wenn das Zertifikat nicht gültig ist.
  5. Der Proxy überträgt Inhalte, entschlüsselt sie und verschlüsselt sie erneut mit K a
  6. Client zeigt Sachen an

Ein Beispiel ist Squids SSL-Bump . Ebenso kann Burp dafür konfiguriert werden . Dies wurde auch in einem weniger harmlosen Kontext von einem ägyptischen ISP verwendet .

Beachten Sie, dass moderne Websites und Browser HPKP oder integrierte Zertifikat-Pins verwenden können, die diesen Ansatz zunichte machen .

Phihag
quelle
13
Dies könnte im Prinzip funktionieren, aber so kommunizieren Browser nicht mit HTTP-Proxys für HTTPS-Anforderungen. Die hier beschriebene Art impliziert, dass der Proxyserver effektiv ein Man-In-The-Middle ist (daher müsste man ihm entsprechend vertrauen).
Bruno
5
Tintenfisch macht das. Es heißt SSL Bump .
Adam Mackler
3
Funktioniert nicht ohne viel Alarm für den Endbenutzer. "bedingungslos vertrauenswürdig vom Kunden" - so etwas gibt es nicht. Auch wenn das Zertifikat perfekt ist - AAA +++ -, zeigt es immer noch eine andere Domain, die nicht mit dem übereinstimmt, was der Endbenutzer verlangt hat, was jeden vernünftigen Browser (der hier nicht IE bedeutet ...) zum Schreien bringt. Natürlich ist es möglich, wget mit Parametern zu verwenden, die SSL-Prüfungen deaktivieren, aber wissen Sie was? Diese Verbindung kann nicht mehr als "SSL" bezeichnet werden, nachdem die zentralen Sicherheitsüberprüfungen deaktiviert wurden.
Van Jone
1
@ Van Jone Unconditionally trustedbezieht sich auf ein CA-Zertifikat. CA-Zertifikate haben keine Domänen. Ich habe die Antwort mit zwei Beispielen geändert, in denen dies in der Praxis ohne Warnungen an den Benutzer funktioniert / funktioniert hat.
Phihag
6
Meine Antwort basiert auf dem, was Sie als "falsche Zertifizierungsstelle" bezeichnen. Das Zertifikat der Zertifizierungsstelle ist bedingungslos vertrauenswürdig, entweder weil der Benutzer (oder die Software auf seinem Computer, z. B. Unternehmenskonfiguration oder Malware) es auf diese Weise konfiguriert hat, oder weil die Zertifizierungsstelle von einer der Zertifizierungsstellen bezogen wurde, denen die wichtigsten Browser vertrauen, z im MCS-Fall. Der Proxy generiert für jede vom Client angeforderte Domain ein neues gültiges Zertifikat. Ohne die am Ende der Antwort genannten Anti-MITM-Funktionen wird der Client dies nicht bemerken.
Phihag
22

Die kurze Antwort lautet: Es ist möglich und kann entweder mit einem speziellen HTTP-Proxy oder einem SOCKS-Proxy durchgeführt werden.

In erster Linie verwendet HTTPS SSL / TLS, das die End-to-End-Sicherheit gewährleistet, indem ein sicherer Kommunikationskanal über einen unsicheren eingerichtet wird. Wenn der HTTP-Proxy den Inhalt sehen kann, handelt es sich um einen Lauscher, der das Ziel von SSL / TLS verfehlt. Es müssen also einige Tricks gespielt werden, wenn wir einen Proxy über einen einfachen HTTP-Proxy durchführen möchten.

Der Trick ist, wir verwandeln einen HTTP-Proxy in einen TCP-Proxy mit einem speziellen Befehl namens CONNECT. Nicht alle HTTP-Proxys unterstützen diese Funktion, aber viele tun dies jetzt. Der TCP-Proxy kann den übertragenen HTTP-Inhalt nicht im Klartext sehen, dies hat jedoch keine Auswirkungen auf seine Fähigkeit, Pakete hin und her weiterzuleiten. Auf diese Weise können Client und Server mithilfe des Proxys miteinander kommunizieren. Dies ist die sichere Methode zum Proxying von HTTPS-Daten.

Es gibt auch eine unsichere Methode, bei der der HTTP-Proxy zu einem Mann in der Mitte wird. Es empfängt die vom Client initiierte Verbindung und initiiert dann eine weitere Verbindung zum realen Server. In einem gut implementierten SSL / TLS wird der Client benachrichtigt, dass der Proxy nicht der echte Server ist. Der Client muss dem Proxy also vertrauen, indem er die Warnung ignoriert, damit die Dinge funktionieren. Danach entschlüsselt der Proxy einfach Daten von einer Verbindung, verschlüsselt sie erneut und speist sie in die andere ein.

Schließlich können wir HTTPS sicherlich über einen SOCKS- Proxy vertreten, da der SOCKS-Proxy auf einer niedrigeren Ebene arbeitet. Sie können sich einen SOCKS-Proxy sowohl als TCP- als auch als UDP-Proxy vorstellen.

Cyker
quelle
Würde die Verwendung von CONNECT Sicherheitswarnungen verursachen, wie unter stackoverflow.com/a/3118759/632951 erwähnt ?
Pacerier
@ Pacerier Ich glaube nicht. Im CONNECT-Modus arbeitet der Proxy auf der Transportschicht.
Cyker
Bei der CONNECT-Methode werden also keine https-Daten vom Client an die Anwendungsebene des zwischengeschalteten Proxys übergeben. Und gerade auf TCP-Proxy-Ebene ausgewertet und direkt an den Remote-Server weitergeleitet ?
Zzinny
15

Soweit ich mich erinnern kann, müssen Sie eine HTTP CONNECT-Abfrage auf dem Proxy verwenden. Dadurch wird die Anforderungsverbindung in einen transparenten TCP / IP-Tunnel konvertiert.

Sie müssen also wissen, ob der von Ihnen verwendete Proxyserver dieses Protokoll unterstützt.

chburd
quelle
3
In der Tat verwenden Clients das Verb CONNECT, um https: // URIs über HTTP-Proxyserver zu verwenden. In diesem Fall wird die Verbindung über den Proxy getunnelt, sodass die Zertifikatsüberprüfung wie gewohnt durchgeführt wird, als würde der Client direkt mit dem Endserver sprechen.
Bruno
1
@chburd, Aber unterstützen Proxys normalerweise HTTP CONNECT?
Pacerier
9

Wenn es immer noch von Interesse ist, finden Sie hier eine Antwort auf eine ähnliche Frage: Konvertieren Sie den HTTP-Proxy in Twisted in den HTTPS-Proxy

Um den zweiten Teil der Frage zu beantworten:

Wenn ja, welche Art von Proxyserver erlaubt dies?

Standardmäßig werden die meisten Proxyserver so konfiguriert, dass HTTPS-Verbindungen nur zu Port 443 zugelassen werden, sodass https-URIs mit benutzerdefinierten Ports nicht funktionieren. Dies ist im Allgemeinen abhängig vom Proxyserver konfigurierbar. Squid und TinyProxy unterstützen dies beispielsweise.

Bruno
quelle
5

Hier ist mein vollständiger Java-Code, der sowohl HTTP- als auch HTTPS-Anforderungen mit dem SOCKS-Proxy unterstützt.

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;

/**
 * How to send a HTTP or HTTPS request via SOCKS proxy.
 */
public class ClientExecuteSOCKS {

    public static void main(String[] args) throws Exception {
        Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new MyHTTPConnectionSocketFactory())
            .register("https", new MyHTTPSConnectionSocketFactory(SSLContexts.createSystemDefault
                ()))
            .build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg);
        try (CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(cm)
            .build()) {
            InetSocketAddress socksaddr = new InetSocketAddress("mysockshost", 1234);
            HttpClientContext context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);

            HttpHost target = new HttpHost("www.example.com/", 80, "http");
            HttpGet request = new HttpGet("/");

            System.out.println("Executing request " + request + " to " + target + " via SOCKS " +
                "proxy " + socksaddr);
            try (CloseableHttpResponse response = httpclient.execute(target, request, context)) {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity(), StandardCharsets
                    .UTF_8));
            }
        }
    }

    static class MyHTTPConnectionSocketFactory extends PlainConnectionSocketFactory {
        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }
    }

    static class MyHTTPSConnectionSocketFactory extends SSLConnectionSocketFactory {
        public MyHTTPSConnectionSocketFactory(final SSLContext sslContext) {
            super(sslContext);
        }

        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }
    }
}
Seelenmaschine
quelle
3

Sie können dies mithilfe von Man-in-the-Middle-Techniken mit dynamischer SSL-Generierung erreichen. Schauen Sie sich mitmproxy an - es ist ein Python-basierter, SSL-fähiger MITM-Proxy.

Zorayr
quelle
3

Tunneln von HTTPS über SSH (Linux-Version):

1) turn off using 443 on localhost
2) start tunneling as root: ssh -N login@proxy_server -L 443:target_ip:443
3) adding 127.0.0.1 target_domain.com to /etc/hosts

alles was du auf localhost machst. dann:

target_domain.com is accessible from localhost browser.
Sławomir Lenart
quelle
1

Ich hatte es versucht

  • Tunnelbau starten: ssh -N -D 12345 login@proxy_server
  • Festlegen des Proxys in den Firefox-Einstellungen als localhost:12345
    • und ankreuzen "Diesen Proxy für alle Protokolle verwenden"

Dies führte jedoch zu dem Fehler "Unsichere Verbindung", wenn ich versuchte, eine Verbindung zu einer https-Website herzustellen.

Die Lösung war zu

  • "Deaktivieren" Sie die Option "Diesen Proxy für alle Protokolle verwenden".
  • Setzen Sie den Proxy "localhost: 12345" nur als SOCKS-Proxy
  • und lassen Sie den HTTP-Proxy, den SSL-Proxy und den FTP-Proxy leer

Referenz aus der digitalen Ozeandokumentation

So leiten Sie den Webverkehr ohne VPN mithilfe eines SOCKS-Tunnels sicher weiter

Shadi
quelle
1

Ich glaube nicht, dass "HTTPS-Verbindungen über Proxyserver haben" den Man-in-the-Middle-Angriffstyp eines Proxyservers bedeutet. Ich denke, es wird gefragt, ob man über TLS eine Verbindung zu einem http-Proxyserver herstellen kann. Und die Antwort lautet ja.


Ist es möglich, HTTPS-Verbindungen über Proxyserver herzustellen?

Ja, siehe meine Frage und Antwort hier. Der HTTP-Proxyserver funktioniert nur in SwitchOmega

Wenn ja, welche Art von Proxyserver erlaubt dies?

Die Art des Proxyservers stellt SSL-Zertifikate bereit, wie dies bei normalen Websites der Fall ist. Sie benötigen jedoch eine pacDatei, damit der Browser die Proxy-Verbindung über SSL konfigurieren kann.

Rick
quelle