2009-02-05 4 views
63

Возможно ли иметь HTTPS-соединения через прокси-серверы? Если да, то какой прокси-сервер разрешает это?HTTPS-соединения через прокси-серверы

Дублированный с How to use Socks 5 proxy with Apache HTTP Client 4?

+0

Я думаю, что это не дублируется http://stackoverflow.com/questions/22937983/how-to-use-socks-5-proxy-with-apache-http-client-4 – Uri

ответ

38

TLS/SSL (The S в HTTPS) гарантирует, что нет перехватчики между вами и сервером вы контактирующие, то есть нет прокси. Обычно вы используете CONNECT, чтобы открыть TCP-соединение через прокси-сервер. В этом случае прокси не сможет кэшировать, читать или изменять соединение и, следовательно, бесполезно.

Если вы хотите, чтобы прокси-сервер, чтобы иметь возможность читать информацию, вы можете принять следующий подход:

  1. запускает клиент HTTPS сеанса
  2. Proxy прозрачно перехватывает соединение и возвращает одноранговой генерироваться (возможно слабый) сертификат K a, , подписанный центром сертификации , которому безусловным доверяет клиент.
  3. Прокси запускает сеанс HTTPS для целевого
  4. Прокси проверяет целостность SSL сертификат; отображается ошибка, если сертификат недействителен.
  5. Proxy потоков контента, расшифровывает его и повторно шифрует его с помощью K а
  6. Клиентские дисплеи вещи

Примером может служить Сквидом в SSL bump. Аналогично, отрыжка can be configured для этого. Это также было used in a less-benign context by an Egyptian ISP.

Обратите внимание, что современные веб-сайты и браузеры могут использовать HPKP или built-in certificate pins, которые нарушают этот подход.

+8

Это может работать в принципе, но это не значит, что браузеры общаются с HTTP-прокси для HTTPS-запросов. Способ, описанный здесь, подразумевает, что прокси-сервер - это Man-In-The-Middle (поэтому для этого нужно было бы доверять). – Bruno

+5

Squid делает это. Он называется [SSL Bump] (http://wiki.squid-cache.org/Features/SslBump). –

+3

Не будет работать с множеством предупреждений для конечного пользователя. «безоговорочно доверенный клиентом» - такой вещи нет. Даже если сертификат совершенен - ​​AAA +++, он по-прежнему показывает, что другой домен не соответствует тому, что запрашивал конечный пользователь, что сделает любой здравомыслящий браузер (не означает IE здесь ...), прыгая вверх и вниз, крича. Конечно, можно использовать wget с параметрами, отключающими проверку SSL, но угадайте, что? это соединение не может быть названо «SSL» больше после того, как его основные проверки безопасности будут отключены. –

14

Насколько я помню, вам нужно использовать запрос HTTP CONNECT на прокси-сервере. это преобразует соединение запроса в прозрачный туннель TCP/IP.

, так что вам нужно знать, поддерживает ли прокси-сервер этот протокол.

+2

Действительно, клиенты используют глагол CONNECT для использования https: // URI через HTTP-прокси-серверы. В этом случае соединение туннелируется через прокси-сервер, поэтому проверка сертификата выполняется как обычно, как если бы клиент разговаривал напрямую с конечным сервером. – Bruno

+0

@chburd, но ведь прокси обычно поддерживают HTTP CONNECT? – Pacerier

9

Если это все-таки интерес, вот ответ на аналогичный вопрос: Convert HTTP Proxy to HTTPS Proxy in Twisted

Чтобы ответить на вторую часть вопроса:

Если да, то какого рода прокси-сервер позволяет это?

Из-за большого количества прокси-серверов будет настроено разрешение HTTPS-соединений только на порт 443, поэтому https URI с пользовательскими портами не будут работать. Обычно это настраивается в зависимости от прокси-сервера. Например, Squid и TinyProxy поддерживают это.

2

Вы можете выполнить это, используя методы «человек-в-середине» с динамическим генерированием SSL. Взгляните на mitmproxy - это прокси-сервер MITM, основанный на Python.

2

туннелирования HTTPS через SSH (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 

все, что вы делаете на локальном хосте. затем:

target_domain.com is accessible from localhost browser. 
4

Вот мой полный Java код, который поддерживает как HTTP и HTTPS запросов с использованием 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

Короткий ответ: это возможно и может быть выполнено либо с помощью специального HTTP-прокси, либо прокси-сервера SOCKS.

В первую очередь HTTPS использует SSL/TLS, который по дизайну обеспечивает сквозную защиту, устанавливая безопасный канал связи по небезопасной. Если прокси-сервер HTTP способен видеть содержимое, то это подслушивающее устройство «человек в середине», и это побеждает цель SSL/TLS. Поэтому, если мы хотим проксировать через простой HTTP-прокси, должны быть сыграны некоторые трюки.

Фокус в том, что мы превращаем прокси-сервер HTTP в прокси-сервер TCP с помощью специальной команды с именем CONNECT. Не все HTTP-прокси поддерживают эту функцию, но многие делают это сейчас. Прокси-сервер TCP не может видеть HTTP-контент, передаваемый в ясном тексте, но это не влияет на его способность пересылать пакеты туда и обратно. Таким образом, клиент и сервер могут взаимодействовать друг с другом с помощью прокси. Это безопасный способ проксирования данных HTTPS.

Существует также небезопасный способ сделать это, в котором прокси-сервер HTTP становится человеком по середине. Он получает инициированное клиентом соединение, а затем инициирует другое подключение к реальному серверу. В хорошо реализованном SSL/TLS клиент будет уведомлен о том, что прокси-сервер не является реальным сервером. Таким образом, клиент должен доверять прокси, игнорируя предупреждение о том, что все работает. После этого прокси просто расшифровывает данные из одного соединения, повторно расшифровывает и передает его в другой.

Наконец, мы можем прокси-сервер HTTPS через прокси-сервер SOCKS, поскольку прокси-сервер SOCKS работает на более низком уровне. Вы можете считать прокси SOCKS как TCP, так и прокси UDP.

+0

Использует ли CONNECT причины предупреждений о безопасности, как указано в https://stackoverflow.com/a/3118759/632951? – Pacerier

+0

@ Pacerier Я так не думаю. В режиме CONNECT прокси работает на транспортном уровне. – Cyker

Смежные вопросы