Connessioni HTTPS su server proxy


Risposte:


66

TLS / SSL (la S in HTTPS) garantisce che non ci siano intercettatori tra te e il server che stai contattando, ovvero nessun proxy. Normalmente, si utilizza CONNECTper aprire una connessione TCP tramite il proxy. In questo caso, il proxy non sarà in grado di memorizzare nella cache, leggere o modificare alcuna richiesta / risposta e quindi sarà piuttosto inutile.

Se vuoi che il proxy sia in grado di leggere le informazioni, puoi adottare il seguente approccio:

  1. Il client avvia la sessione HTTPS
  2. Il proxy intercetta in modo trasparente la connessione e restituisce un certificato K a generato ad hoc (possibilmente debole) , firmato da un'autorità di certificazione che è incondizionatamente considerata attendibile dal client.
  3. Proxy avvia la sessione HTTPS su destinazione
  4. Il proxy verifica l'integrità del certificato SSL; visualizza un errore se il certificato non è valido.
  5. Il proxy trasmette il contenuto, lo decrittografa e lo crittografa nuovamente con K a
  6. Il cliente mostra cose

Un esempio è il bump SSL di Squid . Allo stesso modo, il rutto può essere configurato per farlo. Questo è stato utilizzato anche in un contesto meno favorevole da un ISP egiziano .

Si noti che i siti Web e browser moderni possono utilizzare HPKP o pin di certificati incorporati che annullano questo approccio.


13
In linea di principio potrebbe funzionare, ma non è così che i browser comunicano con i proxy HTTP per le richieste HTTPS. Il modo in cui è descritto qui implica che il server proxy è effettivamente un Man-In-The-Middle (quindi dovrebbe essere considerato attendibile di conseguenza).
Bruno

5
Squid lo fa. Si chiama SSL Bump .
Adam Mackler

3
Non funzionerà senza molti avvisi per l'utente finale. "incondizionatamente fidato dal cliente" - non esiste una cosa del genere. Anche se il certificato è perfetto-AAA +++, mostra ancora un dominio diverso che non corrisponde a ciò che l'utente finale ha richiesto, il che farà urlare qualsiasi browser sano (non significa IE qui ...) su e giù. Ovviamente è possibile utilizzare wget con parametri che disabilitano i controlli SSL, ma indovina cosa? questa connessione non può più essere denominata "SSL" dopo che i suoi controlli di sicurezza di base sono stati disabilitati.
Van Jone

1
@Van Jone Unconditionally trustedfa riferimento a un certificato CA. I certificati CA non hanno domini. Ho modificato la risposta con due esempi in cui questo funziona / ha funzionato in pratica senza alcun avviso per l'utente.
phihag

6
La mia risposta si basa su ciò che chiamate "CA fasulla". Il certificato della CA è incondizionatamente attendibile, o perché l'utente (o il software sul suo computer, ad esempio configurazione aziendale o malware) lo ha configurato in questo modo, o perché la CA è stata ottenuta da una delle CA attendibili dai principali browser, come nel caso MCS. Il proxy genera un nuovo certificato valido per ogni dominio richiesto dal client, quindi senza le funzionalità anti-MITM menzionate alla fine della risposta il client non se ne accorgerà.
phihag

22

La risposta breve è: è possibile, e può essere fatto con uno speciale proxy HTTP o con un proxy SOCKS.

Innanzitutto, HTTPS utilizza SSL / TLS che in base alla progettazione garantisce la sicurezza end-to-end stabilendo un canale di comunicazione sicuro su uno non sicuro. Se il proxy HTTP è in grado di vedere i contenuti, allora è un intercettatore man-in-the-middle e questo sconfigge l'obiettivo di SSL / TLS. Quindi ci devono essere alcuni trucchi se vogliamo eseguire il proxy attraverso un semplice proxy HTTP.

Il trucco è che trasformiamo un proxy HTTP in un proxy TCP con un comando speciale denominato CONNECT. Non tutti i proxy HTTP supportano questa funzione, ma molti lo fanno ora. Il proxy TCP non può vedere il contenuto HTTP trasferito in testo non crittografato, ma ciò non influisce sulla sua capacità di inoltrare i pacchetti avanti e indietro. In questo modo, client e server possono comunicare tra loro con l'aiuto del proxy. Questo è il modo sicuro per inviare tramite proxy i dati HTTPS.

C'è anche un modo insicuro per farlo, in cui il proxy HTTP diventa un man-in-the-middle. Riceve la connessione avviata dal client, quindi avvia un'altra connessione al real server. In un SSL / TLS ben implementato, il client verrà informato che il proxy non è il server reale. Quindi il client deve fidarsi del proxy ignorando l'avvertimento affinché le cose funzionino. Dopodiché, il proxy decrittografa semplicemente i dati da una connessione, ricrittografa e li inserisce nell'altra.

Infine, possiamo sicuramente eseguire il proxy HTTPS tramite un proxy SOCKS , perché il proxy SOCKS funziona a un livello inferiore. Potresti pensare che un proxy SOCKS sia sia un proxy TCP che un proxy UDP.


L'utilizzo di CONNECT causerebbe avvisi di sicurezza come menzionato in stackoverflow.com/a/3118759/632951 ?
Pacerier

@Pacerier non la penso così. In modalità CONNECT il proxy funziona a livello di trasporto.
Cyker

Quindi, con il metodo CONNECT, i dati https dal client non vengono passati al livello di applicazione del proxy intermedio? E appena valutato a livello di proxy TCP e inoltrato direttamente al server remoto ?
zzinny

15

per quanto posso ricordare, è necessario utilizzare una query HTTP CONNECT sul proxy. questo convertirà la connessione richiesta in un tunnel TCP / IP trasparente.

quindi devi sapere se il server proxy che usi supporta questo protocollo.


3
Infatti, i client utilizzano il verbo CONNECT per utilizzare https: // URI tramite server proxy HTTP. In questo caso, la connessione viene trasmessa tramite il proxy, quindi la verifica del certificato viene eseguita come al solito, come se il client stesse parlando direttamente al server finale.
Bruno

1
@chburd, ma i proxy di solito supportano HTTP CONNECT?
Pacerier

9

Se è ancora interessante, ecco una risposta a una domanda simile: Converti proxy HTTP in proxy HTTPS in Twisted

Per rispondere alla seconda parte della domanda:

Se sì, che tipo di server proxy lo consente?

Per impostazione predefinita, la maggior parte dei server proxy sarà configurata per consentire le connessioni HTTPS solo alla porta 443, quindi gli URI https con porte personalizzate non funzionerebbero. Questo è generalmente configurabile, a seconda del server proxy. Squid e TinyProxy lo supportano, ad esempio.


5

Ecco il mio codice Java completo che supporta sia le richieste HTTP che HTTPS utilizzando il proxy SOCKS.

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

3

Puoi farlo utilizzando tecniche man-in-the-middle con generazione SSL dinamica. Dai un'occhiata a mitmproxy : è un proxy MITM basato su Python e compatibile con SSL.


3

Tunneling HTTPS tramite SSH (versione Linux):

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

tutto ciò che fai su localhost. poi:

target_domain.com is accessible from localhost browser.

1

Ci avevo provato

  • inizia il tunneling: ssh -N -D 12345 login@proxy_server
  • Impostando il proxy nelle impostazioni di Firefox come localhost:12345
    • e spuntando "usa questo proxy per tutti i protocolli"

ma questo ha provocato l'errore "Connessione non sicura" ogni volta che ho provato a connettermi a un sito Web https.

La soluzione era

  • "deseleziona" "usa questo proxy per tutti i protocolli"
  • imposta il proxy "localhost: 12345" solo come proxy SOCKS
  • e lascia vuoti il ​​proxy HTTP, il proxy SSL e il proxy FTP

Riferimento dalla documentazione oceanica digitale

Come instradare il traffico Web in modo sicuro senza una VPN utilizzando un tunnel SOCKS


1

Non credo che "avere connessioni HTTPS su server proxy" significhi il tipo di attacco Man-in-the-Middle del server proxy. Penso che si stia chiedendo se è possibile connettersi a un server proxy http tramite TLS. E la risposta è si.


È possibile avere connessioni HTTPS su server proxy?

Sì, vedi la mia domanda e risposta qui. Il server proxy HTTP funziona solo in SwitchOmega

Se sì, che tipo di server proxy lo consente?

Il tipo di server proxy distribuisce i certificati SSL, come fanno i normali siti web. Ma è necessario un pacfile per il browser per configurare la connessione proxy su SSL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.