ESP — это IP-протокол 50, а не TCP-порт 50: что разрешать
Номера протоколов и номера портов — разные пространства имён. Правило для TCP-порта 50 ничего не разрешает, а NAT traversal переносит ESP в UDP 4500.
Формы настройки межсетевого экрана запрашивают TCP-порт, и очевидный ответ — 50. Этот ответ ничего не разрешает, потому что ESP — это IP-протокол номер 50, а номера протоколов не являются портами. Эти два пространства имён разделяют только малые целые числа и ничего больше, и ошибка остаётся невидимой, пока IKE не завершится, а защищённый трафик так и не придёт.
Два пространства имён, которые делят малые числа
В заголовке IP есть поле протокола, которое называет следующее: 6 для TCP, 17 для UDP, 1 для ICMP, 50 для ESP, 51 для AH. В заголовке TCP или UDP есть номера портов, которые выбирают процесс на хосте назначения. Протокол 50 и TCP-порт 50 — несвязанные значения, но диалоговое окно может показать их как взаимозаменяемые.
Именно поэтому правило перенаправления портов не может выразить нативный ESP. Портов назначения ESP для перенаправления не существует, а устройство, которое понимает только правила портов, вообще не имеет словаря для такого пакета. Правильное правило называет IP-протокол. Любое диалоговое окно портов — неправильный инструмент для этого пакета.
У путаницы есть и вторая половина. Когда пакет зашифрован, всё внутри него непрозрачно, включая заголовок TCP исходного соединения. Межсетевой экран, который проверяет порты в этом пакете, смотрит на внешний заголовок, в котором в нативном случае нет портов для проверки.
Нативный ESP, затем инкапсулированная альтернатива
Нативный ESP передаётся напрямую как IP-протокол, что одинаково эффективно и неудобно. Эффективно, потому что нет дополнительного заголовка, и неудобно, потому что ни одно устройство, выполняющее трансляцию адресов и портов, не может его отследить. NAT traversal существует именно для этого: он заворачивает пакет ESP в UDP, чтобы у транслятора были порты для перезаписи.
| Form on the wire | How it is identified | What the firewall must permit |
|---|---|---|
| IKE negotiation | UDP with a destination port | UDP 500, and 4500 once traversal is detected |
| Native ESP | IP protocol 50 in the outer header | The protocol itself, with no port to name |
| ESP inside UDP | UDP 4500 carrying an ESP payload | The UDP port pair, which translation devices can track |
Две формы — это альтернативные варианты развёртывания одного и того же канала данных, а не уровни одного. Разрешение нативного ESP не разрешает инкапсулированную форму, а разрешение UDP 4500 не разрешает нативный трафик, поэтому набор правил должен соответствовать развёртыванию, а не случайно покрывать оба варианта.
Обнаружение здесь тоже важно. Конечные точки выбирают форму во время согласования, и переключение обычно происходит, когда между ними обнаруживается NAT. Поэтому маршрут, который изменился после установки туннеля, может перенести трафик в пространство имён, которое ваши правила никогда не покрывали.
Прочитайте, какую форму соединение действительно использует
Спросите конечную точку, а не гадайте по межсетевому экрану. В Linux запись состояния сообщает, использует ли связка инкапсуляцию UDP и какие порты задействованы. Захват пакетов отвечает на тот же вопрос с линии, и оба способа быстрее, чем читать набор правил и надеяться.
ip xfrm state | grep -A3 encap
tcpdump -ni any 'ip proto 50 or udp port 4500'
Первая команда показывает тип инкапсуляции, когда используется NAT traversal, и ничего, когда нет. Вторая показывает, какая из двух форм действительно проходит через интерфейс, и это прекращает споры о конфигурации, которая на бумаге выглядит правильной.
Контрдоказательство относится к тому же шагу. Правило, сообщающее о нуле совпадений, говорит вам, что пакет до него не дошёл, и это вопрос маршрутизации или селектора, а не межсетевого экрана.
Затем отдельно подтвердите канал управления. У IKE свои порты и свои журналы, и завершённое согласование без данных — это ровно то разделение, о котором эта статья.
Запишите правило в правильном пространстве имён
Правило протокола и правило порта — разные инструкции, поэтому инструмент должен выражать именно то, что вы имеете в виду. В nftables совпадение по протоколу задаётся явно, а инкапсулированная альтернатива получает собственное правило UDP. Держите два правила рядом, чтобы пара была видна при проверке.
nft add rule inet filter input ip protocol esp accept
nft add rule inet filter input udp dport { 500, 4500 } accept
Не расширяйте ни одно из правил, чтобы компенсировать неверную диагностику. Разрешение всего для протокола ESP на каждом интерфейсе или разрешение UDP откуда угодно куда угодно исправляет симптом и убирает контроль, который вы пытались настроить. Узкий поддерживаемый поток почти всегда достаточен, когда форма известна.
Наконец, держите уровни врозь, когда туннель работает, а приложение нет. Пакетам, приходящим на шлюз, по-прежнему нужны пересылка, обратный маршрут и политика, которая их пропускает, и ничто из этого не выражается правилом ESP. Отсутствующий порт объясняет конкретный сбой, а не каждый сбой IPsec. Держите исправление правила и проверку маршрутизации как два отдельных вывода.
Запишите форму, которую вы наблюдали, добавленное правило протокола и счётчик, который увидели после. Три строки, и следующий человек отличит ошибку пространства имён от ошибки маршрутизации за минуту, а не за полдня.