При проектировании сетевой инфраструктуры, систем сбора данных (веб-парсинга) или инфраструктуры для мультиаккаунтинга разработчики сталкиваются с выбором протокола проксирования. На практике базовый выбор сводится к двум технологиям: HTTP CONNECT и SOCKS5.
На поверхностном уровне кажется, что оба протокола делают одно и то же — пробрасывают TCP-пакеты от клиента к целевому серверу через промежуточный узел. Однако на уровнях L5 и L7 модели OSI между ними есть различия в архитектуре рукопожатий (handshake), объеме служебных данных (overhead), методах аутентификации и обработке DNS-запросов.
Давайте разберем как происходит работа протокола HTTP CONNECT и SOCKS5 и какие между ними различия.
- Архитектура и сетевая модель: L5 vs L7
- HTTP CONNECT (RFC 9110)
- SOCKS5 (RFC 1928)
- Сравнение процедур рукопожатия
- Текстовый Handshake HTTP CONNECT
- Бинарный Handshake SOCKS5
- ЭТАП 1: Согласование метода аутентификации
- ЭТАП 2: Запрос на установление соединения
- Анализ оверхеда, задержек (RTT) и производительности
- Байтовый оверхед
- Сравнение RTT и latency
- Поддержка UDP, BIND и DNS-резолвинг
- Работа с UDP и BIND
- Утечка DNS и SOCKS5h
- Безопасность, шифрование и DPI-детекция
- Шифрование канала
- Обнаружение DPI
- Практическая реализация и примеры кода
- Настройка в cURL
- Python: Сравнение requests и httpx
- Использование HTTP CONNECT и SOCKS5 в requests:
- Асинхронная реализация в httpx:
- Go: Реализация SOCKS5 и HTTP CONNECT
- Альтернативный взгляд и эволюция: HTTP/2 CONNECT и MASQUE (HTTP/3)
- Нетривиальный факт: Взаимные блокировки при использовании TCP over TCP
Архитектура и сетевая модель: L5 vs L7
Сетевые прокси-протоколы классифицируются по уровню модели OSI, на котором происходит обработка и коммутация трафика.
HTTP CONNECT (RFC 9110)
Запрос CONNECT был введен в спецификации HTTP/1.1, для организации сквозного туннелирования.
Протокол работает на прикладном уровне (L7). Это означает, что промежуточный прокси-сервер должен быть полноценным HTTP-сервером: он парсит входящие текстовые заголовки, обрабатывает код метода, проверяет заголовки Host и Proxy-Authorization. И только после того, как туннель согласован, прокси-сервер переходит в режим прозрачного бинарного моста, переставая анализировать проходящие байты.
SOCKS5 (RFC 1928)
Протокол SOCKS5 (Sockets Protocol Version 5) функционирует на сеансовом уровне (L5).
SOCKS5 ничего не знает о протоколах прикладного уровня, проходящих через него (HTTP, FTP, SMTP, SSH или сырые бинарные сокеты). Он устанавливает сеанс связи между клиентом и прокси-сервером до того, как начнется обмен данными прикладного уровня. Прокси-сервер считывает только свой бинарный заголовок установления соединения, после чего транслирует TCP-сегменты или UDP-датаграммы напрямую на целевой IP-адрес.
Сравнение процедур рукопожатия
Скорость установления соединения (latency/RTT) напрямую зависит от количества сетевых итераций, необходимых для согласования сессии.

Текстовый Handshake HTTP CONNECT
После того как клиент установил TCP-соединение с прокси-сервером (порт 8080, 3128 и др.), он отправляет ASCII-текстовый HTTP-запрос:
CONNECT target.example.com:443 HTTP/1.1\r\n Host: target.example.com:443\r\n User-Agent: Mozilla/5.0 (X11; Linux x86_64)\r\n Proxy-Authorization: Basic dXNlcjpwYXNzd29yZA==\r\n Proxy-Connection: Keep-Alive\r\n \r\n
Если аутентификация прошла успешно и целевой хост доступен, прокси-сервер отвечает:
HTTP/1.1 200 Connection Established\r\n Proxy-Agent: Squid/6.6\r\n \r\n
После двух символов перевода строки \r\n\r\n (CRLF) канал считается открытым. Начиная со следующего байта, всё, что отправляет клиент (например, TLS ClientHello), транслируется на target.example.com:443.
⚠️ Важно: Если прокси требует аутентификации, он вернет статус
HTTP/1.1 407 Proxy Authentication Required. Клиенту придется закрыть соединение или повторить запрос с заголовкомProxy-Authorization.
Бинарный Handshake SOCKS5
В SOCKS5 обмен данными происходит не текстом, а строго разложенными по байтам структурами (структурами C).
ЭТАП 1: Согласование метода аутентификации
Клиент отправляет пакет выбора метода:
| Смещение (Byte) | Поле | Значение | Описание |
0 |
VER | 0x05 |
Версия протокола SOCKS (5) |
1 |
NMETHODS | 0x01 |
Количество поддерживаемых методов аутентификации |
2 |
METHODS | 0x00 |
Метод: 0x00 (NO AUTH), 0x02 (USER/PASS) |
Сервер отвечает 2 байтами:
-
Byte 0:0x05(Версия) -
Byte 1:0x00(Выбран метод0x00— без аутентификации)
Если выбран метод 0x02 (Username/Password, происходит дополнительный шаг: клиент отправляет байты с версией субпротокола 0x01, длиной логина, логином, длиной пароля и паролем. Это добавляет еще 1 RTT.
ЭТАП 2: Запрос на установление соединения
Клиент отправляет команду подключения:
| Byte | Поле | Значение | Описание |
0 |
VER | 0x05 |
Версия SOCKS5 |
1 |
CMD | 0x01 |
Команда: 0x01 (CONNECT), 0x02 (BIND), 0x03 (UDP) |
2 |
RSV | 0x00 |
Зарезервированный байт (всегда 0x00) |
3 |
ATYP | 0x03 |
Тип адреса: 0x01 (IPv4), 0x03 (Domain), 0x04 (IPv6) |
4 |
DST.ADDR | 0x12 ... |
Длина домена (1 байт) + ASCII-строка домена |
N |
DST.PORT | 0x01 0xBB |
Порт целевого узла в Big-Endian (2 байта, e.g. 443) |
Ответ прокси-сервера при успешном подключении (REP = 0x00):
| Byte | Поле | Значение | Описание |
0 |
VER | 0x05 |
Версия SOCKS5 |
1 |
REP | 0x00 |
Статус: 0x00 (Succeeded / Успешно) |
2 |
RSV | 0x00 |
Зарезервировано |
3 |
ATYP | 0x01 |
Тип привязанного адреса BND.ADDR (IPv4) |
4..7 |
BND.ADDR | 192.0.2.1 |
IP-адрес, выделенный прокси для выходящего соединения |
8..9 |
BND.PORT | 0x1F 0x90 |
Порт, выделенный прокси (Big-Endian) |
Анализ оверхеда, задержек (RTT) и производительности
При проектировании высоконагруженных сетевых систем критично оценивать затраты трафика на служебные заголовки и задержки на фазе открытия сокета.
Байтовый оверхед
Сравним объем служебных данных, передаваемых по сети до момента отправки полезного payload (например, первого байта TLS ClientHello):
HTTP CONNECT Overhead: Req: CONNECT target.com:443 HTTP/1.1\r\nHost: ...\r\nProxy-Auth: ...\r\n\r\n ~ 180-250 bytes Res: HTTP/1.1 200 Connection Established\r\nProxy-Agent: ...\r\n\r\n ~ 60-120 bytes ИТОГО ОВЕРХЕД: ~ 240–370 байт SOCKS5 Overhead (без Auth, ATYP Domain Name): Req1 (Methods): 0x05 0x01 0x00 = 3 bytes Res1 (Method Choice): 0x05 0x00 = 2 bytes Req2 (Connect): 0x05 0x01 0x00 0x03 0x0A target.com 0x01 0xBB = 17 bytes Res2 (Response): 0x05 0x00 0x00 0x01 192.0.2.1 0x1F 0x90 = 10 bytes ИТОГО ОВЕРХЕД: 32 байта
Вывод по оверхеду: На этапе согласования соединения SOCKS5 передает в 7–10 раз меньше служебных байт, чем HTTP CONNECT. На миллионах коротких сессий (при парсинге) SOCKS5 существенно экономит полосу пропускания и снижает нагрузку на CPU прокси-сервера (за счет отсутствия строкового парсинга ASCII-заголовков).

Сравнение RTT и latency
-
HTTP CONNECT: Потребляет 1 RTT после установления TCP-сессии для обмена текстовыми заголовками.
-
SOCKS5: Без аутентификации требует 2 RTT (согласование метода + команда CONNECT). При аутентификации по логину и паролю — 3 RTT.
Хотя у SOCKS5 больше сетевых итераций (RTT) на старте, бинарные пакеты обрабатываются сетевым стеком прокси за микросекунды. HTTP CONNECT требует 1 RTT, но вызов
regexили строкового парсера HTTP-заголовков на стороне прокси под высокой нагрузкой может съесть выигранное на RTT время.
Поддержка UDP, BIND и DNS-резолвинг
Работа с UDP и BIND
Главное функциональное ограничение классического HTTP CONNECT — полное отсутствие поддержки протокола UDP. Через HTTP CONNECT нельзя проксировать DNS over UDP, WebRTC, VoIP-трафик, P2P/Torrent или QUIC (HTTP/3).
SOCKS5 нативно поддерживает UDP с помощью команды UDP ASSOCIATE (CMD = 0x03).
-
Клиент отправляет
UDP ASSOCIATEна SOCKS5-сервер по TCP-каналу. -
Сервер открывает на своей стороне UDP-порт и возвращает его IP и порт клиенту (
BND.ADDR,BND.PORT). -
Клиент инкапсулирует свои UDP-датаграммы в простой SOCKS5 UDP-заголовок (всего 3 байта оверхеда + адрес назначения) и шлет их на выделенный UDP-порт прокси.
Команда BIND (CMD = 0x02) в SOCKS5 позволяет прокси-серверу принимать входящие TCP-соединения из внешнего мира (например, для входящих активных соединений в FTP или P2P-сетях). В HTTP CONNECT аналогов этой функции нет.
Утечка DNS и SOCKS5h
При работе с прокси критически важно, где именно происходит резолвинг доменного имени в IP-адрес: на машине клиента или на прокси-сервере.
Если клиент сначала сам запрашивает IP у своего локального DNS-провайдера, а потом отправляет IP-адрес в прокси — возникает утечка DNS. Локальный провайдер видит, к каким доменам обращается пользователь.
-
HTTP CONNECT: Клиент всегда передает доменное имя в первой строке:
CONNECT target.com:443 HTTP/1.1. Резолвинг домена всегда выполняется на стороне прокси-сервера. -
SOCKS5: Протокол поддерживает два формата. В поле
ATYPможно передать IPv4 (0x01), IPv6 (0x04) или имя домена (0x03).-
Если клиент передает IPv4 (
ATYP = 0x01), значит, он выполнил DNS-запрос локально. -
Если клиент передает доменную строку (
ATYP = 0x03), резолвинг выполняет прокси-сервер. В утилитах и библиотеках этот режим называется SOCKS5h.
-

Безопасность, шифрование и DPI-детекция
Шифрование канала
Ни HTTP CONNECT, ни SOCKS5 не предоставляют встроенного шифрования управляющего трафика между клиентом и прокси-сервером. Данные передаются в открытом виде.
Если вы используете SOCKS5 или HTTP CONNECT без внешнего TLS-оборачивания (например, без проксирования самого прокси через HTTPS), любой промежуточный узел (ISP, фаервол, DPI) видит:
-
Для HTTP CONNECT: заголовки
CONNECT target.com:443и данныеProxy-Authorization. -
Для SOCKS5: факт подключения, методы аутентификации и домен/IP целевого сервера.
Однако, когда внутри сформированного туннеля устанавливается HTTPS-соединение, целевые данные (HTML, JSON, изображения) шифруются конечным ключом TLS между клиентом и целевым сервером (target.com). Прокси-сервер не может расшифровать этот трафик.
Обнаружение DPI
Современные системы глубокого анализа пакетов (DPI) легко идентифицируют оба протокола по их сигнатурам:
-
Сигнатура SOCKS5: DPI ищет в начале TCP-сессии байты
0x05 0x01или0x05 0x02. Поскольку эти байты идут первыми же пакетами послеSYN/ACK, незашифрованный SOCKS5 блокируется провайдерами за доли секунды. -
Сигнатура HTTP CONNECT: Текстовые строки
CONNECTиHTTP/1.1на нестандартных портах (не 80/443) подпадают под фильтры L7-детекции.
Для защиты от DPI прокси-протоколы инкапсулируют в TLS (HTTPS-проксирование) или используют специализированные транспортные протоколы (Shadowsocks, VLESS, Trojan, MASQUE).
Практическая реализация и примеры кода
Настройка в cURL
Подключение через HTTP CONNECT:
curl -v -x http://user:password@proxy.example.com:8080 https://target.example.com
Подключение через SOCKS5 с удаленным DNS-резолвингом (SOCKS5h — предотвращает утечку DNS):
curl -v -x socks5h://user:password@proxy.example.com:1080 https://target.example.com
⚠️ Обратите внимание на схему
socks5h://. Если указатьsocks5://, cURL отрезолвит IP-адресtarget.example.comчерез ваш локальный DNS-сервер и передаст на прокси готовый IP.
Python: Сравнение requests и httpx
Для использования SOCKS5 в стандартной библиотеке requests требуется установить дополнительный модуль PySocks:
pip install "requests[socks]" httpx httpx-socks
Использование HTTP CONNECT и SOCKS5 в requests:
import requests
# 1. HTTP CONNECT прокси
proxies_http = {
"http": "http://user:pass@proxy.example.com:8080",
"https": "http://user:pass@proxy.example.com:8080",
}
response_http = requests.get("https://httpbin.org/ip", proxies=proxies_http)
print("HTTP Proxy IP:", response_http.json())
# 2. SOCKS5h (Remote DNS) прокси
proxies_socks = {
"http": "socks5h://user:pass@proxy.example.com:1080",
"https": "socks5h://user:pass@proxy.example.com:1080",
}
response_socks = requests.get("https://httpbin.org/ip", proxies=proxies_socks)
print("SOCKS5 Proxy IP:", response_socks.json())
Асинхронная реализация в httpx:
import asyncio
import httpx
from httpx_socks import AsyncProxyTransport
async def fetch_via_socks():
# Используем socks5h для удаленного резолвинга DNS
transport = AsyncProxyTransport.from_url('socks5h://user:pass@proxy.example.com:1080')
async with httpx.AsyncClient(transport=transport) as client:
response = await client.get('https://httpbin.org/ip')
print("Async SOCKS5 IP:", response.json())
asyncio.run(fetch_via_socks())
Go: Реализация SOCKS5 и HTTP CONNECT
В языке Go работа с HTTP CONNECT встроена в пакет net/http, а для SOCKS5 используется официальный субмодуль golang.org/x/net/proxy.
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"golang.org/x/net/proxy"
"context"
"net"
)
func main() {
// 1. HTTP CONNECT Proxy
proxyURL, _ := url.Parse("http://user:pass@proxy.example.com:8080")
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
resp, err := httpClient.Get("https://httpbin.org/ip")
if err == nil {
body, _ := io.ReadAll(resp.Body)
fmt.Println("HTTP CONNECT Result:", string(body))
resp.Body.Close()
}
// 2. SOCKS5 Proxy с поддержкой Remote DNS
dialer, err := proxy.SOCKS5("tcp", "proxy.example.com:1080", &proxy.Auth{
User: "user",
Password: "pass",
}, proxy.Direct)
if err != nil {
panic(err)
}
socksTransport := &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return dialer.Dial(network, addr)
},
}
socksClient := &http.Client{Transport: socksTransport}
respSocks, err := socksClient.Get("https://httpbin.org/ip")
if err == nil {
body, _ := io.ReadAll(respSocks.Body)
fmt.Println("SOCKS5 Result:", string(body))
respSocks.Body.Close()
}
}
Альтернативный взгляд и эволюция: HTTP/2 CONNECT и MASQUE (HTTP/3)
Считать SOCKS5 единственным универсальным выбором для сложных задач было бы ошибкой. Протоколы семейства HTTP прошли значительную эволюцию:
-
Extended CONNECT в HTTP/2: Позволяет мультиплексировать множество туннелируемых TCP-потоков внутри одного единственного TLS-соединения с прокси-сервером. Это решает проблему высоких задержек на установление множественных TCP-соединений.
-
MASQUE / UDP proxying over HTTP/3: Позволяет проксировать UDP-датаграммы внутри QUIC-потоков HTTP/3. MASQUE превосходит SOCKS5 по устойчивости к потерям пакетов и обеспечивает встроенное TLS 1.3 шифрование туннеля по умолчанию.
Нетривиальный факт: Взаимные блокировки при использовании TCP over TCP
Использование SOCKS5 или HTTP CONNECT для создания TCP-туннеля, внутри которого затем поднимается еще одно TCP-соединение (например, OpenVPN в режиме TCP или внутренний HTTPS-запрос), создает так называемый феномен TCP Meltdown (TCP over TCP Meltdown).
Если на внешнем сетевом канале между клиентом и прокси происходят потери пакетов, Таймеры Повторной Передачи внешнего TCP-соединения и внутреннего TCP-соединения начинают накладываться друг на друга. Внутренний TCP-стек начинает повторно отправлять пакеты, считая их потерянными, что еще сильнее забивает буферы внешнего сокета. В результате пропускная способность канала падает практически до нуля. Чтобы избежать этого эффекта, для внутренних туннелей предпочтительнее использовать протоколы поверх UDP (что делает SOCKS5 с его UDP ASSOCIATE намного эффективнее).









