Skip to content
Эта страница переведена с помощью ИИ и может содержать неточности. Помогите улучшить перевод на GitHub.

Маршрутизация по протоколу ​

Несколько служб делят один публичный порт (например, сайт, VPN, SSH и удалённый рабочий стол одновременно используют 443). Gately определяет протокол по первым данным, которые отправляет клиент, затем смотрит домен (SNI) и ALPN в TLS-рукопожатии или Host в HTTP и передаёт всё соединение без изменений подходящему бэкенду. Здесь ничего не расшифровывается и не терминируется, поэтому TLS-сертификаты остаются на бэкендах. Модуль выполняет ту же задачу, что правила req_ssl_sni в haproxy вместе с sslh.

Маршрутизация по домену (маршрутизация по SNI) — один из её случаев: добавьте маршрут TLS и укажите в нём домены.

Правило содержит:

  • прослушивание: протокол (только TCP; tcp — двойной стек, tcp4 / tcp6 — одно семейство адресов), адрес и порты прослушивания (443, 443,8443 или диапазон);
  • маршруты: у каждого маршрута есть протокол, имя, адреса целей (несколько адресов пробуются по очереди, с переключением при отказе), необязательный порт цели (пусто означает порт прослушивания) и настройка протокола PROXY (выключен, v1 или v2). Настройка PROXY относится к маршруту, потому что одним бэкендам она необходима, а другие её отвергают;
  • цель по умолчанию: собственные адреса целей, порты целей и настройка протокола PROXY самого правила; используется, если ни один маршрут не подошёл или протокол не распознан;
  • тайм-аут распознавания: сколько секунд ждать от клиента данных, по которым можно определить протокол; 0 означает значение по умолчанию, 5 секунд.

Распознаваемые протоколы ​

Протокол маршрутаПризнакДополнительное сопоставление
TLSЗапись TLS-рукопожатия (ClientHello)Домен (SNI), ALPN
HTTPМетод и версия HTTP/ в строке запроса, включая CONNECT, методы WebDAV и HTTP/2 с предварительным знанием (h2c)Домен (заголовок Host)
SSHСтрока версии клиента SSH-—
RDP (удалённый рабочий стол)Заголовок TPKT и запрос подключения X.224—
SOCKS4 / SOCKS5Запросы SOCKS4 и SOCKS4a и согласование метода SOCKS5—
OpenVPN (TCP)Пакет жёсткого сброса (hard reset) от клиента, включая tls-auth, tls-crypt и tls-crypt-v2—
XMPPXML-декларация или <stream:stream—
MQTTПакет CONNECT (3.1, 3.1.1, 5.0)—
PostgreSQLСтартовое сообщение, SSLRequest и GSSENCRequest—
Minecraft (Java Edition)Пакет рукопожатия; запрос списка серверов в версиях 1.6 и более раннихАдрес сервера
RTSPВерсия RTSP/1.0 или RTSP/2.0 в строке запроса (IP-камеры, видеорегистраторы)—
SIPВерсия SIP/2.0 в строке запроса (TCP)—
RedisКоманды, отправленные массивами RESP—
AMQPЗаголовок протокола AMQP (0-9-1 и 1.0, RabbitMQ и др.)—
SMBЗапросы согласования SMB1, SMB2 и SMB3 в сообщении сеанса NetBIOS—
GitПервая pkt-line протокола git:// (git daemon)—
IRCКоманда CAP, PASS, NICK или USER, которую клиент отправляет первой—
ADBСообщение CNXN протокола Android Debug Bridge (adb connect)—
BitTorrentНешифрованное рукопожатие между пирами—
ОжиданиеКлиент ничего не отправил за время тайм-аута распознавания—

Сопоставление ​

Маршруты TLS, HTTP и Minecraft сопоставляются по домену (для Minecraft это адрес сервера, который ввёл клиент, из пакета рукопожатия; данные, добавленные Forge, BungeeCord или TCPShield, игнорируются): сначала точные домены (vpn.example.com), затем самый длинный шаблон (*.example.com, любой глубины), затем * (любое соединение, содержащее домен) и в конце маршруты без домена (все соединения этого протокола, включая соединения без SNI или Host). Регистр доменов не учитывается. При сохранении домены приводятся к нижнему регистру, интернационализированные преобразуются в punycode; значения с портом, путём или @ отклоняются.

В маршрутах TLS можно также указать значения ALPN: маршрут подходит, только если клиент предлагает одно из них. Для одного домена приоритет у маршрутов с ALPN, а если ALPN не совпал, поиск продолжается по более общим доменам. Например, acme-tls/1 можно отправить программе, которая отвечает на проверку сертификата TLS-ALPN-01, а postgresql — на прямые TLS-соединения PostgreSQL 17. В пределах протокола домен (с данным ALPN) может принадлежать только одному маршруту; для остальных протоколов допускается по одному маршруту.

«Ожидание» предназначено для протоколов, где сервер отправляет данные первым: VNC, MySQL, FTP, SMTP, POP3, IMAP. Их клиенты подключаются и ждут сервер, поэтому Gately ничего не получает и не может определить, какой это протокол. Значит, на каждом порту маршруту «Ожидание» можно отдать только один из них, и такие соединения перенаправляются после истечения тайм-аута распознавания. Тайм-аут распознавания можно задать с одним знаком после запятой: клиенты TLS, SSH, HTTP и подобные отправляют первый пакет через миллисекунды после рукопожатия, поэтому при наличии маршрута «Ожидание» достаточно 0,3–1 секунды — столько же ждут VNC и подобные соединения.

На цель по умолчанию отправляются соединения, если: ни один маршрут не подошёл; данные не относятся ни к одному протоколу из таблицы (например, протоколы без сигнатуры, такие как Shadowsocks, VMess или BitTorrent с шифрованием, а также протоколы, первый пакет которых состоит только из поля длины и легко путается с другими, такие как MongoDB или DNS over TCP); ClientHello не удаётся разобрать; клиент ничего не отправляет, а маршрута «Ожидание» нет. Без цели по умолчанию такие соединения закрываются и учитываются как «разорвано». Клиент, который отключился до завершения распознавания, отбрасывается.

Примечания ​

  • Только TCP. UDP-трафик, например HTTP/3 (QUIC) или WireGuard, не маршрутизируется, для него создайте отдельное правило;
  • зашифрованные варианты SIP, Redis, AMQP, IRC и подобных протоколов работают поверх TLS; направляйте их маршрутами TLS по домену или ALPN;
  • ClientHello может быть разбит на несколько TLS-записей и достигать 64 КБ; строка запроса HTTP, RTSP и SIP может занимать до 8 КБ, а для HTTP читается до 32 КБ заголовков запроса, чтобы найти Host;
  • каждое соединение распознаётся один раз, поэтому последующие запросы в том же keep-alive-соединении HTTP идут на бэкенд, выбранный в первый раз;
  • на карточке правила показано, сколько соединений получили каждый маршрут и цель по умолчанию; отладочные записи журнала работы фиксируют для каждого соединения распознанный протокол, SNI, ALPN или Host;
  • при горячем обновлении правила (примечание, маршруты, цель по умолчанию, список IP источников и т. п.) маршруты с прежними протоколом, доменами и ALPN сохраняют счётчики попаданий, в том числе при перемещении, переименовании или смене цели; новые маршруты и маршруты с изменённым протоколом, доменами или ALPN начинают с 0; после отключения и повторного включения или перезапуска правила все счётчики начинаются с 0;
  • изменения маршрутов, цели по умолчанию и тайм-аута распознавания применяются сразу, без остановки прослушивания, а открытые соединения сохраняются.
  • Для каждого правила можно задать белый или чёрный список IP источника (в том числе по подписанным спискам IP веб-служб); проверка выполняется до определения протокола: не прошедшее её соединение закрывается без чтения данных и не считается попаданием маршрута; блокировки защиты от вторжений имеют приоритет. Правка списка не прерывает прослушивание, карточка правила показывает число отказов. Работает так же, как в пробросе портов.

Пример: замена haproxy ​

Такая конфигурация haproxy:

text
frontend https
    bind 192.0.2.10:443
    mode tcp
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }
    use_backend ocserv if { req_ssl_sni -i tz.example.com }
    default_backend web
backend ocserv
    server ocserv 127.0.0.1:443 send-proxy-v2
backend web
    server web 127.0.0.1:8443 send-proxy-v2

превращается в одно правило Gately:

ПараметрЗначение
ПротоколTCP
Адрес / порт прослушивания192.0.2.10 / 443
Маршрут ocservпротокол TLS, домен tz.example.com, цель 127.0.0.1, порт 443, PROXY v2
Цель по умолчанию127.0.0.1, порт цели 8443, PROXY v2

Укажите в качестве адреса прослушивания публичный адрес сервера, чтобы не возникало конфликта с бэкендами, которые слушают 127.0.0.1:443. Чтобы раздавать сайты средствами самого Gately, добавьте прослушивание веб-служб на 127.0.0.1:8443 с включённым «Принимать протокол PROXY» и 127.0.0.0/8 в доверенных источниках PROXY. Перед включением правила остановите haproxy: порт может слушать только одна программа.

Пример: замена sslh ​

Такие аргументы sslh:

text
sslh --listen 0.0.0.0:443 --timeout 2 \
     --ssh 127.0.0.1:22 --openvpn 127.0.0.1:1194 --tls 127.0.0.1:8443

соответствуют одному правилу Gately:

ПараметрЗначение
ПротоколTCP
Адрес / порт прослушиванияпусто / 443
Тайм-аут распознавания2
Маршрут sshпротокол SSH, цель 127.0.0.1, порт 22
Маршрут vpnпротокол OpenVPN, цель 127.0.0.1, порт 1194
Маршрут webпротокол TLS, без доменов, цель 127.0.0.1, порт 8443
Маршрут vnc (необязательно)протокол «Ожидание», цель 127.0.0.1, порт 5900

По умолчанию sslh после тайм-аута отправляет соединения на SSH. Gately распознаёт SSH сразу по строке версии SSH-, поэтому тайм-аут можно отдать службе, где сервер отправляет данные первым, например VNC. Можно добавить маршруты для RDP, SOCKS и HTTP или распределить TLS между бэкендами по доменам.

Переход с проброса портов ​

Раньше маршрутизация по протоколу была режимом «Маршрутизация по SNI» в правилах проброса портов. При первом запуске после обновления правила маршрутизации по SNI из проброса портов автоматически переносятся в модуль «Маршрутизация по протоколу»: каждое правило сохраняет ключ, имя, состояние включения, группу и все маршруты, а старые маршруты становятся маршрутами TLS. Если модуль проброса портов был отключён, маршрутизация по протоколу тоже отключается, а API-токены с доступом к пробросу портов получают такой же уровень доступа к маршрутизации по протоколу.

После переноса управляйте этими правилами через /api/protoroute/rules: поле маршрутов переименовано из sniRoutes в routes, поле mode больше не используется; правила маршрутизации, отправленные в /api/portforward/rules, отклоняются. Метрики теперь называются gately_protoroute_*, см. Мониторинг.

Рекомендации по развёртыванию ​

Маршрутизация по протоколу слушает порты непосредственно на хосте, поэтому для Docker рекомендуется --network host.

Группы и порядок ​

Правилам можно задать «Группу». Группы, сортировка и поиск работают так же, как в пробросе портов; поле поиска фильтрует по имени, группе, порту прослушивания, цели, домену или протоколу маршрута.

Распространяется по лицензии Apache-2.0.