2009-02-05 39 views

risposta

38

TLS/SSL (L'S in HTTPS) garantisce che non ci sono intercettazioni tra voi e il server si sta contattando, cioè non proxy. Normalmente, si utilizza CONNECT per aprire una connessione TCP tramite il proxy. In questo caso, il proxy non sarà in grado di memorizzare, leggere o modificare la connessione, e quindi inutile.

Se si desidera che il proxy per essere in grado di leggere le informazioni, si può prendere il seguente approccio:

  1. inizia client HTTPS sessione
  2. Proxy intercetta in modo trasparente la connessione e restituisce un annuncio-hoc generato (possibilmente debole) certificato K a, firmato da un'autorità di certificazione che è incondizionatamente attendibile dal client .
  3. Il proxy avvia la sessione HTTPS verso il target
  4. Il proxy verifica l'integrità del certificato SSL ; visualizza un errore se il certificato non è valido.
  5. Proxy flussi di contenuti, decifra e ri-codifica con K un
  6. Client visualizza roba

Un esempio è Squid di SSL bump. Allo stesso modo, rutto can be configured per fare questo. Questo è stato anche used in a less-benign context by an Egyptian ISP.

Si noti che i siti Web e i browser moderni possono utilizzare HPKP o built-in certificate pins che vanificano questo approccio.

+8

Questo potrebbe lavorare in linea di principio, ma questo non è il modo in cui 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 di conseguenza). – Bruno

+5

Squid fa questo. Si chiama [SSL Bump] (http://wiki.squid-cache.org/Features/SslBump). –

+3

Non funziona senza molti avvisi all'utente finale. "Fiducia incondizionata da parte del cliente" - non esiste una cosa del genere. Anche il certificato è perfetto-AAA +++, mostra ancora diversi domini non corrispondenti a quello richiesto dall'utente finale, il che renderà qualsiasi browser sensato (non intendendo IE qui ...) che salta su e giù urlando. Naturalmente, è possibile utilizzare wget con parametri che disabilitano i controlli SSL, ma indovina cosa? questa connessione non può più essere denominata "SSL" dopo aver disabilitato i controlli di sicurezza di base. –

14

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

quindi è necessario sapere se il server proxy che si utilizza supporta questo protocollo.

+2

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

+0

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

9

Se è ancora di interesse, qui è una risposta a una domanda simile: Convert HTTP Proxy to HTTPS Proxy in Twisted

Per rispondere alla seconda parte della domanda:

Se sì, che tipo di server proxy permette Questo?

Fuori dalla scatola, 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 supportano questo, per esempio.

2

È possibile eseguire questa operazione utilizzando tecniche man-in-the-middle con generazione dinamica di SSL. Dai un'occhiata a mitmproxy - è un proxy MITM basato su Python e compatibile con SSL.

2

tunneling HTTPS tramite SSH (versione per Linux):

1) turn off using 443 on localhost 
2) start tunneling as root: ssh -N [email protected]_server -L 443:target_ip:443 
3) adding 127.0.0.1 target_domain.com to /etc/hosts 

tutto quello che fai su localhost. poi:

target_domain.com is accessible from localhost browser. 
4

Ecco il mio codice Java completo che supporta sia HTTP e HTTPS richieste utilizzando 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); 
     } 
    } 
} 
5

La risposta breve è: È possibile e può essere eseguita con un proxy HTTP speciale o un proxy SOCKS.

In primo luogo, 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 il contenuto, allora è un intercettatore man-in-the-middle e questo sconfigge l'obiettivo di SSL/TLS. Quindi ci devono essere alcuni trucchi in corso se vogliamo proxy attraverso un semplice proxy HTTP.

Il trucco è, trasformiamo un proxy HTTP in un proxy TCP con un comando speciale chiamato 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 chiaro, 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 il proxy dei dati HTTPS.

Esiste anche un modo non sicuro di farlo, in cui il proxy HTTP diventa un man-in-the-middle. Riceve la connessione avviata dal client e quindi avvia un'altra connessione al server reale. In un SSL/TLS ben implementato, al client verrà notificato che il proxy non è il vero server. Quindi il client deve fidarsi del proxy ignorando l'avviso per far funzionare le cose. Dopodiché, il proxy semplicemente decrittografa i dati da una connessione, reencrypt e li alimenta nell'altra.

Infine, possiamo certamente eseguire il proxy HTTPS tramite un proxy SOCKS, perché il proxy SOCKS funziona a un livello inferiore. Si può pensare a un proxy SOCKS sia come proxy TCP che UDP.

+0

L'uso di CONNECT causa avvisi di sicurezza come indicato in https://stackoverflow.com/a/3118759/632951? – Pacerier

+0

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

Problemi correlati