HTTPS-соединения через прокси-серверы
Возможно ли иметь HTTPS-соединения через прокси-серверы? Если да, то какой прокси-сервер позволяет это?
Дублируется с Как использовать прокси Socks 5 с Apache HTTP Client 4?
8 ответов
TLS/SSL (S в HTTPS) гарантирует, что между вами и сервером, с которым вы обращаетесь, нет перехватчиков, то есть прокси-серверов. Обычно вы используете CONNECT
открыть TCP соединение через прокси. В этом случае прокси не сможет кэшировать, читать или изменять соединение, и, следовательно, бесполезно.
Если вы хотите, чтобы прокси мог читать информацию, вы можете использовать следующий подход:
- Клиент запускает сеанс HTTPS
- Прокси-сервер прозрачно перехватывает соединение и возвращает специальный сгенерированный (возможно, слабый) сертификат K a, подписанный центром сертификации, которому клиент безоговорочно доверяет.
- Прокси-сервер запускает HTTPS-сеанс с целью
- Прокси-сервер проверяет целостность SSL-сертификата; отображает ошибку, если сертификат недействителен.
- Прокси передает поток, расшифровывает и перекодирует его с помощью K a
- Клиент отображает вещи
Примером может служить SSL Squid. Аналогично, для этого можно настроить отрыжку. Это также использовалось в менее благоприятном контексте египетским интернет-провайдером.
Обратите внимание, что современные веб-сайты и браузеры могут использовать HPKP или встроенные контакты сертификатов, которые побеждают этот подход.
Краткий ответ: это возможно и может быть сделано либо с помощью специального 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-прокси.
Насколько я помню, вам нужно использовать HTTP-запрос CONNECT на прокси. это преобразует соединение запроса в прозрачный туннель TCP/IP.
поэтому вам нужно знать, поддерживает ли используемый вами прокси-сервер этот протокол.
Если это все еще интересно, вот ответ на аналогичный вопрос: конвертировать HTTP-прокси в HTTPS-прокси в Twisted
Чтобы ответить на вторую часть вопроса:
Если да, то какой прокси-сервер позволяет это?
Изначально большинство прокси-серверов будут настроены на разрешение HTTPS-подключений только к порту 443, поэтому URI-адреса https с пользовательскими портами не будут работать. Обычно это настраивается в зависимости от прокси-сервера. Squid и TinyProxy поддерживают это, например.
Вот мой полный 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);
}
}
}
Вы можете сделать это, используя методы "человек посередине" с динамической генерацией SSL. Взгляните на http://mitmproxy.org/ - это MITM-прокси с поддержкой SSL на основе Python.
Туннелирование 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.
Я не думаю, что "иметь HTTPS-соединения через прокси-серверы" означает атаку типа "Человек посередине" прокси-сервера. Я думаю, он спрашивает, можно ли подключиться к прокси-серверу http через TLS. И ответ - да.
Возможно ли подключение HTTPS через прокси-серверы?
Да, см. Мой вопрос и ответ здесь. Прокси-сервер HTTPs работает только в SwitchOmega
Если да, то какой прокси-сервер позволяет это?
Прокси-сервер использует сертификаты SSL, как и обычные веб-сайты. Но тебе нуженpac
файл для браузера, чтобы настроить прокси-соединение через SSL.
Я пытался
- начать туннелирование:
ssh -N -D 12345 login@proxy_server
- Установка прокси в настройках Firefox как
localhost:12345
- и отметьте "использовать этот прокси для всех протоколов"
но это приводило к ошибке "Небезопасное соединение" всякий раз, когда я пытался подключиться к веб-сайту https.
Решение было
- "убрать галочку" с "использовать этот прокси для всех протоколов"
- установить прокси "localhost:12345" только как прокси SOCKS
- и оставьте HTTP-прокси, SSL-прокси, FTP-прокси пустым
Ссылка из цифровой океанской документации
Как безопасно маршрутизировать веб-трафик без VPN с использованием туннеля SOCKS