Попробовать
Назад к блогу

TCP-прокси: как работает, чем отличается от HTTP-прокси и где применяется

TCP-прокси: как работает, чем отличается от HTTP-прокси и где применяется

TCP-прокси принимает соединение на одном адресе и порту, открывает второе соединение до адресата и копирует байты между ними, не пытаясь их разобрать. Он работает на транспортном, четвёртом уровне модели OSI, поэтому передаёт любой протокол поверх TCP: PostgreSQL и MySQL, SSH, SMTP и IMAP, MQTT, Redis, игровые протоколы и любой TLS.

По сути, это универсальный переходник для сетей. TCP-прокси стоит перед кластерами баз данных, на SSH-шлюзах, внутри балансировщиков нагрузки и — под другим названием — в каждом арендованном SOCKS5-прокси. Ниже разберём, как устроена ретрансляция, чем TCP-прокси отличается от HTTP-прокси, что происходит с TLS и с IP-адресом клиента, и приведём рабочие конфигурации для nginx, HAProxy и SSH.

Прокси дата-центров

Быстрые прокси дата-центров по SOCKS5 для любых TCP-приложений

Попробовать

Как TCP-прокси передаёт соединение

Каждая сессия через прокси — это на самом деле два TCP-соединения, склеенных между собой:

  1. Клиент проходит TCP-рукопожатие с прокси, например на 198.51.100.20:15432.
  2. Прокси решает, куда направить сессию: на фиксированный бэкенд из конфигурации или на адрес, который назвал клиент.
  3. Прокси открывает собственное соединение с адресатом, скажем db.internal:5432.
  4. Байты, прочитанные из одного сокета, записываются в другой, пока одна из сторон не закроет соединение.

Для клиента прокси — это сервер, для адресата — клиент. Поэтому адресат видит IP прокси, а не исходный, и ниже это ещё понадобится.

Статические пересыльщики и динамические TCP-прокси

TCP-прокси бывают двух видов, и разница в том, кто выбирает адресата.

  • Статические пересыльщики связывают прослушиваемый порт с бэкендом, заданным в конфигурации. Так работают nginx с модулем stream, HAProxy в mode tcp, Envoy, socat и ssh -L. Клиенту даже не обязательно знать о прокси.
  • Динамические прокси позволяют клиенту называть цель для каждого соединения. SOCKS5-сервер делает это командой CONNECT, HTTP-прокси — одноимённым методом. После того как цель задана, оба ведут себя как обычная TCP-ретрансляция. Именно такой тип продают провайдеры прокси — подробнее в статье о том, что такое SOCKS5-прокси.

TCP-прокси и HTTP-прокси: сравнение

TCP-прокси (уровень 4)HTTP-прокси (уровень 7)
Что понимаетАдреса, порты, поток байтовМетоды, URL, заголовки, cookie
ПротоколыЛюбые поверх TCPHTTP, а HTTPS через CONNECT
На чём основана маршрутизацияПорт, IP клиента, имя сервера из TLSХост, путь, заголовки, cookie
Кэширование и правка контентаНетДа, для незашифрованного трафика
Передача IP клиентаPROXY protocolЗаголовки X-Forwarded-For, Forwarded
Единица балансировкиВсё соединениеОтдельный запрос
Накладные расходыМинимальныеРазбор каждого запроса
ЛогиБайты, длительность, адресаПолные данные запроса

HTTP-прокси нужен, когда маршрут зависит от URL, требуется переписывать заголовки или кэшировать ответы. TCP-прокси — когда протокол не HTTP, когда данные нельзя трогать или когда нужны просто скорость и прозрачность. Прикладной уровень подробно разобран в статье о том, что такое HTTP-прокси.

Прямой и обратный TCP-прокси

Прямой TCP-прокси стоит на стороне клиента и выпускает исходящие соединения наружу — чаще всего чтобы дать им другой выходной IP или провести через границу сети. Обратный стоит перед серверами: принимает входящие соединения из интернета, распределяет их по пулу бэкендов и скрывает их настоящие адреса. Программы часто одни и те же, меняется только направление.

TLS через TCP-прокси

У прокси четвёртого уровня три способа обращаться с зашифрованным трафиком:

  • Сквозная передача. Прокси пересылает зашифрованный поток как есть, сертификат хранится на бэкенде. При этом прокси всё равно может прочитать имя сервера из TLS ClientHello (SNI) и маршрутизировать по нему: в nginx для этого есть ssl_preread, в HAProxy — выборка req.ssl_sni.
  • Терминирование. Сертификат хранится на прокси: он расшифровывает поток и передаёт на бэкенд обычный TCP. Удобно, чтобы добавить TLS старому сервису, который его никогда не поддерживал.
  • Повторное шифрование. Прокси расшифровывает трафик и открывает к бэкенду новую TLS-сессию. Нужно, когда шифрование должно сохраняться и во внутренней сети.

Расшифровка на промежуточном узле — отдельная тема; терминирование и SSL bridging подробнее описаны в статье про SSL/HTTPS-прокси.

Как сохранить IP клиента: PROXY protocol

Бэкенд видит только адрес прокси, поэтому логи, ограничения частоты запросов и белые списки теряют реальных клиентов. В HTTP это решают заголовками, но в сыром TCP-потоке их некуда положить. PROXY protocol, придуманный в проекте HAProxy, добавляет в начало соединения один короткий заголовок:

PROXY TCP4 203.0.113.7 198.51.100.20 51234 5432

Версия 1 — это одна такая текстовая строка, версия 2 — компактный двоичный аналог. Стороны должны договориться заранее: если прокси отправляет заголовок, а бэкенд его не ждёт, бэкенд прочитает мусор и закроет соединение. PROXY protocol поддерживают nginx, HAProxy, Envoy, Postfix и большинство облачных балансировщиков.

Примеры конфигураций

nginx: балансировка PostgreSQL

stream {
    upstream pg_pool {
        server 10.0.4.11:5432;
        server 10.0.4.12:5432 backup;
    }
    server {
        listen 15432;
        proxy_pass pg_pool;
        proxy_connect_timeout 3s;
        proxy_timeout 30m;
    }
}

Блок stream располагается на верхнем уровне nginx.conf, рядом с http, а не внутри него. Длинный proxy_timeout не даёт обрывать простаивающие сессии базы данных.

HAProxy: SSH-шлюз

frontend ssh_gateway
    mode tcp
    bind :2222
    timeout client 2h
    default_backend bastion_hosts

backend bastion_hosts
    mode tcp
    timeout server 2h
    server bastion_a 10.0.7.5:22 check

SSH: проброс порта одной командой

ssh -L 15432:db.internal:5432 admin@bastion.example.net

Пока сессия открыта, клиент базы данных, настроенный на localhost:15432, попадает в базу через шлюз. Если заменить -L на -D 1080, SSH станет динамическим SOCKS-прокси.

Где применяют TCP-прокси

  • Базы данных. Одна постоянная точка входа для PostgreSQL, MySQL или Redis с переключением между репликами.
  • Балансировка нагрузки. Распределение соединений почтовых серверов, MQTT-брокеров и собственных сервисов по множеству узлов.
  • SSH и администрирование. Шлюзы-бастионы, которые открывают наружу один порт вместо десятков серверов.
  • Игровые и чат-серверы с протоколами поверх TCP. Для игр на UDP нужен другой инструмент — о нём рассказывает статья про UDP-прокси.
  • Интернет вещей. Устройства, которые общаются с центральным брокером по MQTT или собственным двоичным протоколам.
  • Исходящие соединения с другого IP. Парсеры, торговые терминалы, мессенджеры и другие программы, которым нужно выходить в интернет из определённой страны, используют динамические TCP-прокси, обычно по SOCKS5. Быстрый вариант для площадок, которые не требуют резидентских адресов, — прокси дата-центров Node Proxy.

Ограничения

  • Нет доступа к содержимому. Нельзя маршрутизировать по URL, блокировать тип запроса или кэшировать ответы.
  • Балансировка по соединениям. Одно долгое соединение всегда попадает на один бэкенд, и нагрузка может распределяться неравномерно.
  • Теряется IP клиента, если PROXY protocol не настроен с обеих сторон.
  • Тайм-ауты. Простаивающие сессии баз данных и SSH обрываются, если тайм-ауты прокси короче, чем keep-alive приложения.
  • Только TCP. DNS, IP-телефония и многие игры используют UDP, и им нужен прокси, который умеет передавать датаграммы.

Когда выбирать TCP-прокси

TCP-прокси подходит, когда трафик не HTTP, когда данные должны пройти без изменений (например, сквозной TLS до бэкенда со своим сертификатом) или когда нужна тонкая и быстрая прослойка для баз данных, SSH и брокеров сообщений. HTTP-прокси нужен, когда решения зависят от URL и заголовков. А если задача — просто заставить программу выходить в сеть с другого IP, самый короткий путь — SOCKS5, то есть динамический TCP-прокси с авторизацией.

Частые вопросы о TCP-прокси

Чем TCP-прокси отличается от SOCKS5-прокси?

SOCKS5-прокси — разновидность TCP-прокси, в которой клиент называет адресата в начале каждого соединения и может авторизоваться. Обычный TCP-пересыльщик отправляет все соединения на бэкенд, заданный в конфигурации.

Может ли TCP-прокси работать с HTTPS?

Да. Он может пропускать зашифрованный поток без изменений, маршрутизировать его по имени сервера из TLS-рукопожатия или сам завершать TLS, если у него есть сертификат.

Скрывает ли TCP-прокси мой IP-адрес?

От адресата — да: сервер видит адрес прокси. Исключение — схема с PROXY protocol, которая намеренно передаёт бэкенду ваш исходный адрес.

TCP-прокси быстрее HTTP-прокси?

Обычно немного быстрее, потому что не разбирает запросы. Разница заметна при большом числе соединений, а для одного пользователя гораздо важнее расстояние до прокси.

Может ли TCP-прокси передавать UDP?

Нет. В UDP нет соединений, которые можно было бы так же ретранслировать, поэтому нужен прокси с поддержкой UDP — например, SOCKS5 с UDP ASSOCIATE или специальный балансировщик UDP.