З'єднання HTTPS через проксі-сервери


103

Чи можливе з'єднання HTTPS через проксі-сервери? Якщо так, то який проксі-сервер дозволяє це?

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


Я думаю, що це не дублюється з stackoverflow.com/questions/22937983/…
Uri

Так, можливо. Дивіться практичні приклади тут 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-удари кальмарів . Аналогічно, для цього можна налаштувати відрижку . Це також використовувало єгипетський Інтернет-провайдер у менш доброякісному контексті .

Зауважте, що сучасні веб-сайти та веб-переглядачі можуть використовувати HPKP або вбудовані шпильки сертифікатів, які заперечують такий підхід.


13
Це може працювати в принципі, але це не спосіб, коли браузери спілкуються з HTTP-проксі для запитів HTTPS. Спосіб, описаний тут, означає, що проксі-сервер фактично є людиною в середині (тому слід довіряти відповідно).
Бруно

5
Кальмар це робить. Це називається SSL Bump .
Адам Маклер

3
Не працюватиме без багато попередження для кінцевого користувача. "безумовно довіряється клієнтові" - такого немає. Незважаючи на те, що cert є ідеальним - AAA +++, він все ще показує різний домен, який не відповідає тому, про що просив кінцевий користувач, що змусить будь-який розумний браузер (не маючи на увазі IE тут ...) стрибати вгору і вниз кричати. Звичайно, можна використовувати wget з параметрами, що вимикають перевірку SSL, але здогадуйтесь, що? це з'єднання не може бути названо "SSL" після відключення перевірок основного рівня безпеки.
Ван Джоне

1
@Van Jone Unconditionally trustedпосилається на сертифікат CA. Сертифікати CA не мають доменів. Я змінив відповідь на двох прикладах, коли це працює / робиться на практиці без будь-яких сповіщень користувача.
Фігаг

6
Моя відповідь покладається на те, що ви називаєте "фіктивним КА". Сертифікат ЦС буде беззастережно довіряти, або тому , що користувач (або програмне забезпечення на своєму комп'ютері, для конфігурації прикладу підприємства або шкідливих програм) налаштоване це таким чином, або тому , що СА була отримана від одного з центрів сертифікації довіряють основні браузери, як у випадку MCS. Проксі-сервер генерує новий дійсний сертифікат для кожного домену, який запитує клієнт, тому без засобів проти MITM, зазначених в кінці відповіді, клієнт не помітить.
фігаг

22

Коротка відповідь: Це можливо, і це можна зробити за допомогою спеціального проксі 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-проксі.


Чи може використання CONNECT викликати попередження про безпеку, як зазначено в stackoverflow.com/a/3118759/632951 ?
Pacerier

@Pacerier Я так не думаю. У режимі CONNECT проксі працює на транспортному шарі.
Cyker

Отже, методом CONNECT будь-які дані https від клієнта не передаються на рівень програми посередника-посередника? А щойно оцінювали на рівні TCP проксі і безпосередньо передавались на віддалений сервер ?
zzinny

15

наскільки я пам'ятаю, вам потрібно використовувати запит HTTP CONNECT на проксі. це перетворить з'єднання запиту в прозорий TCP / IP тунель.

тому вам потрібно знати, чи підтримує проксі-сервер, який ви використовуєте, цей протокол.


3
Дійсно, клієнти використовують дієслово CONNECT для використання https: // URI через HTTP проксі-сервери. У цьому випадку з'єднання тунелюється через проксі, тому перевірка сертифікатів проводиться як зазвичай, як якщо б клієнт спілкувався безпосередньо з кінцевим сервером.
Бруно

1
@chburd, але як правило проксі підтримують HTTP CONNECT?
Pacerier

9

Якщо це все ще цікавить, ось відповідь на аналогічне запитання: Перетворити HTTP-проксі в HTTPS-проксі у скрученому вигляді

Щоб відповісти на другу частину питання:

Якщо так, то який проксі-сервер дозволяє це?

У вікні більшості проксі-серверів буде налаштовано так, щоб дозволити HTTPS-з’єднання лише до порту 443, тому https URI з користувацькими портами не працюватиме. Це, як правило, настроюється, залежно від проксі-сервера. Скажімо, це підтримують кальмари та 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.


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 через проксі-сервери" означає проксі-сервер типу атаки Man-in-the-Middle. Я думаю, що це питання, чи можна підключитися до проксі-сервера http через TLS. І відповідь - так.


Чи можливе з'єднання HTTPS через проксі-сервери?

Так, дивіться моє запитання та відповідь тут. Проксі-сервер HTTPs працює лише в SwitchOmega

Якщо так, то який проксі-сервер дозволяє це?

Проксі-сервер використовує SSL-сертифікати, як, наприклад, звичайні веб-сайти. Але вам потрібен pacфайл для браузера, щоб налаштувати проксі-з'єднання через SSL.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.