HTTPS-соединения через прокси-серверы

103

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

Дублировано с Как использовать прокси Socks 5 с HTTP-клиентом Apache 4?

Сообщество
источник
Я думаю, что это не дублируется с stackoverflow.com/questions/22937983/…
Ури,
Да, это возможно. См. Практические примеры здесь stackoverflow.com/questions/56981993/…
Рик

Ответы:

66

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

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

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

Примером может служить удар SSL Squid . Точно так же для этого можно настроить отрыжку . Это также использовалось в менее благоприятном контексте египетским интернет-провайдером .

Обратите внимание, что современные веб-сайты и браузеры могут использовать HPKP или встроенные контакты сертификатов, что не позволяет использовать этот подход.

Phihag
источник
13
В принципе это может сработать, но браузеры не так взаимодействуют с HTTP-прокси для запросов HTTPS. То, как это описано здесь, подразумевает, что прокси-сервер фактически является Man-In-The-Middle (поэтому ему следует доверять соответственно).
Bruno
5
Squid делает это. Это называется SSL Bump .
Adam Mackler
3
Не будет работать без большого количества предупреждений для конечного пользователя. «безоговорочно доверяет клиент» - такого не бывает. Даже если сертификат идеален - AAA +++, он по-прежнему показывает другой домен, не соответствующий тому, что запрашивал конечный пользователь, что заставит любой нормальный браузер (не IE здесь ...) прыгать вверх и вниз с криком. Конечно, можно использовать wget с параметрами, отключающими проверки SSL, но знаете что? это соединение больше не может называться "SSL" после того, как его основные проверки безопасности отключены.
Van Jone
1
@Van Jone Unconditionally trustedссылается на сертификат CA. Сертификаты CA не имеют доменов. Я изменил ответ двумя примерами, где это работает / работает на практике без каких-либо предупреждений для пользователя.
phihag
6
Мой ответ основан на том, что вы называете «фиктивным ЦС». Сертификат ЦС будет безоговорочно доверять, либо потому , что пользователь (или программное обеспечение на своем компьютере, для конфигурации примера предприятия или вредоносных программ) сконфигурировано это таким образом, или потому , что СА была получена от одного из центров сертификации доверяют основные браузеры, как в случае MCS. Прокси-сервер генерирует новый действительный сертификат для каждого домена, запрашиваемого клиентом, поэтому без средств защиты от MITM, упомянутых в конце ответа, клиент не заметит.
phihag
23

Краткий ответ: это возможно и может быть выполнено с помощью специального 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.

Cyker
источник
Будет ли использование CONNECT вызывать предупреждения системы безопасности, как указано в stackoverflow.com/a/3118759/632951 ?
Pacerier
@Pacerier Я так не думаю. В режиме CONNECT прокси работает на транспортном уровне.
Cyker
Итак, с помощью метода CONNECT любые данные https от клиента не передаются на уровень приложения промежуточного прокси? И просто оценивается на уровне TCP прокси и напрямую передается на удаленный сервер ?
zzinny
15

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

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

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

Если это все еще интересно, вот ответ на аналогичный вопрос: Преобразование HTTP-прокси в HTTPS-прокси в Twisted

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

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

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

Бруно
источник
5

Вот мой полный код 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);
        }
    }
}
машина души
источник
3

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

Зорайр
источник
3

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

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

target_domain.com is accessible from localhost browser.
Славомир Ленарт
источник
1

Я пробовал

  • начать туннелирование: ssh -N -D 12345 login@proxy_server
  • Установка прокси в настройках Firefox как localhost:12345
    • и отметьте "использовать этот прокси для всех протоколов"

но это приводило к ошибке «Небезопасное соединение» всякий раз, когда я пытался подключиться к веб-сайту https.

Решение было

  • "снимите галочку" с "использовать этот прокси для всех протоколов"
  • установите прокси "localhost: 12345" только как прокси SOCKS
  • и оставьте поля HTTP-прокси, SSL-прокси, FTP-прокси пустыми.

Ссылка из цифровой документации по океану

Как безопасно маршрутизировать веб-трафик без VPN с помощью туннеля SOCKS

Шади
источник
1

Я не думаю, что «иметь HTTPS-соединения через прокси-серверы» означает атаку типа «Человек посередине» прокси-сервера. Я думаю, он спрашивает, можно ли подключиться к прокси-серверу http через TLS. И ответ - да.


Возможно ли подключение HTTPS через прокси-серверы?

Да, см. Мой вопрос и ответ здесь. Прокси-сервер HTTPs работает только в SwitchOmega

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

Прокси-сервер использует сертификаты SSL, как и обычные веб-сайты. Но вам нужен pacфайл для браузера, чтобы настроить прокси-соединение через SSL.

Рик
источник