2009-02-05 18 views

Respuesta

38

TLS/SSL (El S en HTTPS) garantiza que no hay fisgones entre usted y el servidor que está en contacto, es decir, no hay proxies. Normalmente, usa CONNECT para abrir una conexión TCP a través del proxy. En este caso, el proxy no podrá almacenar en caché, leer o modificar la conexión y, por lo tanto, será inútil.

Si desea que la representación sea capaz de leer la información, se puede tomar el siguiente enfoque:

  1. comienza cliente HTTPS sesión
  2. Proxy intercepta de forma transparente la conexión y devuelve una red ad-hoc generada (posiblemente débil) certificado K a, firmado por una autoridad certificadora que es incondicionalmente confiable por el cliente.
  3. Proxy inicia la sesión HTTPS al destino
  4. Proxy verifica la integridad del certificado SSL ; muestra error si el certificado no es válido.
  5. proxy transmite contenido, lo descifra y lo vuelve a cifrar con K un
  6. pantallas de clientes rellenan

Un ejemplo es el calamar de SSL bump. Del mismo modo, eructar can be configured para hacer esto. Esto también ha sido used in a less-benign context by an Egyptian ISP.

Tenga en cuenta que los sitios web y los navegadores modernos pueden emplear HPKP o built-in certificate pins, lo que anula este enfoque.

+8

Esto podría funcionar en principio, pero esa no es la forma en que los navegadores hablan con proxies HTTP para solicitudes HTTPS. La forma en que se describe aquí implica que el servidor proxy es efectivamente un Man-In-The-Middle (por lo que debería confiarse en consecuencia). – Bruno

+5

Squid hace esto. Se llama [SSL Bump] (http://wiki.squid-cache.org/Features/SslBump). –

+3

No funcionará sin mucha alerta para el usuario final. "incondicionalmente confiado por el cliente" - no existe tal cosa. Incluso el certificado es perfecto: AAA +++, todavía muestra diferentes dominios que no coinciden con los que el usuario final solicitó, lo que hará que cualquier navegador en su sano juicio (lo que no signifique IE aquí ...) brinque y chille. Por supuesto, es posible usar wget con parámetros que deshabilitan las comprobaciones SSL, pero ¿adivinen qué? esta conexión ya no se puede llamar "SSL" después de que se hayan deshabilitado las comprobaciones de seguridad del núcleo. –

14

por lo que puedo recordar, necesita utilizar una consulta HTTP CONNECT en el proxy. esto convertirá la conexión de solicitud a un túnel TCP/IP transparente.

por lo que debe saber si el servidor proxy que utiliza es compatible con este protocolo.

+2

De hecho, los clientes usan el verbo CONNECT para usar https: // URI a través de servidores proxy HTTP. En este caso, la conexión se tuneliza a través del proxy, por lo que la verificación del certificado se realiza de la forma habitual, como si el cliente estuviera hablando directamente con el servidor final. – Bruno

+0

@chburd, pero ¿los proxies generalmente son compatibles con HTTP CONNECT? – Pacerier

9

Si sigue siendo de interés, aquí es una respuesta a una pregunta similar: Convert HTTP Proxy to HTTPS Proxy in Twisted

responder a la segunda parte de la pregunta:

En caso afirmativo, ¿qué tipo de servidor proxy permite ¿esta?

Al salir de la caja, la mayoría de los servidores proxy se configurarán para permitir conexiones HTTPS solo al puerto 443, por lo que los URI https con puertos personalizados no funcionarían. Esto es generalmente configurable, dependiendo del servidor proxy. Squid y TinyProxy apoyan esto, por ejemplo.

2

Puede lograr esto usando técnicas man-in-the-middle con generación SSL dinámica. Eche un vistazo a mitmproxy - es un proxy MITM basado en Python y con capacidad SSL.

2

túnel HTTPS a través de SSH (versión para 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 

todo lo que haces en el servidor local. a continuación:

target_domain.com is accessible from localhost browser. 
4

Aquí es mi completa código Java que es compatible tanto con peticiones HTTP y HTTPS usando 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 respuesta breve es: Es posible, y se puede hacer con un proxy HTTP especial o un proxy SOCKS.

En primer lugar, HTTPS utiliza SSL/TLS que, por diseño, garantiza la seguridad de extremo a extremo estableciendo un canal de comunicación seguro en lugar de uno inseguro. Si el proxy HTTP puede ver los contenidos, entonces se trata de un hombre a escondidas y esto frustra el objetivo de SSL/TLS. Entonces, debe haber algunos trucos que se juegan si queremos hacer un proxy a través de un proxy HTTP simple.

El truco es que convertimos un proxy HTTP en un proxy TCP con un comando especial llamado CONNECT. No todos los proxies HTTP admiten esta función, pero muchos lo hacen ahora. El proxy TCP no puede ver el contenido HTTP que se transfiere en texto claro, pero eso no afecta su capacidad de reenviar paquetes hacia adelante y hacia atrás. De esta manera, el cliente y el servidor pueden comunicarse entre sí con la ayuda del proxy. Esta es la forma segura de transmitir datos HTTPS.

También hay una manera insegura de hacerlo, en la que el proxy HTTP se convierte en un hombre en el medio. Recibe la conexión iniciada por el cliente y luego inicia otra conexión con el servidor real. En un SSL/TLS bien implementado, se notificará al cliente que el proxy no es el servidor real. Entonces, el cliente tiene que confiar en el proxy al ignorar la advertencia de que las cosas funcionen. Después de eso, el proxy simplemente descifra los datos de una conexión, los vuelve a cifrar y los envía a la otra.

Finalmente, podemos proxy HTTPS a través de un proxy SOCKS, porque el proxy SOCKS funciona en un nivel inferior. Puede pensar en un proxy SOCKS como un proxy TCP y UDP.

+0

¿El uso de CONNECT causaría advertencias de seguridad como se menciona en https://stackoverflow.com/a/3118759/632951? – Pacerier

+0

@Pacerier No lo creo. En modo CONNECT, el proxy funciona en la capa de transporte. – Cyker

Cuestiones relacionadas