Протокол 47 против порта TCP 47: два заголовка, два правила
Номер протокола и порт живут в разных заголовках, поэтому одно правило не может заменить другое. PPTP разделяет их, а поле порта не может выразить GRE.
Гостиничные сети и конференц-межсетевые экраны часто показывают пользовательское поле разрешения, и кто-то вводит в него 47 в надежде, что PPTP заработает. Правило создаётся, туннель всё равно не работает, а следующая попытка использует другой номер. Ошибка сидит в самом пакете: у IPv4 есть поле протокола, которое называет то, что идёт после заголовка IP, тогда как у TCP и UDP есть поля порта, существующие только внутри одного из этих заголовков. Это не два написания одного разрешения.
Заголовок IPv4 называет следующий протокол
Поле протокола — это один байт в заголовке IPv4, и в нём хранится число, описывающее полезную нагрузку: 6 для TCP, 17 для UDP, 47 для GRE, 50 для ESP. Всё, что фильтрует пакеты, читает это значение до того, как смотреть глубже, потому что более глубокий заголовок имеет смысл только после того, как тип известен. Смените порт позже в разговоре, и это поле не сдвинулось.
Поэтому правило, написанное против протокола 47, описывает уровень IP. Ни один порт не участвует в решении.
Порты существуют внутри TCP и UDP, больше нигде
Порты — это шестнадцатибитные идентификаторы внутри заголовков TCP и UDP, и их задача — разделять разговоры, использующие один адрес. Заголовок GRE несёт значение типа протокола, часто EtherType, плюс необязательные ключи для мультиплексирования. Поэтому выражение «порт 47» не называет ничего, с чем пакет GRE мог бы совпасть.
Интерфейсы межсетевых экранов различаются тем, насколько это показывают. Одни принимают номер протокола, другие предлагают именованный список, а немногие принимают только TCP или UDP с портами.
PPTP использует оба уровня одновременно
PPTP — самый ясный пример, потому что он намеренно делит работу между двумя уровнями. Управляющее соединение — это сеанс TCP к порту 1723, а путь данных — GRE, протокол 47, без какого-либо порта. Межсетевой экран, разрешающий 1723 и больше ничего, даёт переговорам начаться, а затем отбрасывает полезную нагрузку. Туннель выглядит зависшим после аутентификации, а не не соединяется, и поэтому симптом часто сообщают как проблему с паролем.
| Path | Outer protocol | Port |
|---|---|---|
| Control channel | TCP, protocol 6 | 1723 |
| Data channel | GRE, protocol 47 | None |
Читайте две строки отдельно, когда пишете правило, и проверяйте каждую по синтаксису производителя. Одной строке нужен порт, другой нужен номер протокола, и ни одна запись не покрывает обе.
Почему страница проброса портов не может выразить GRE
Форма проброса, принимающая только TCP и UDP, не может описать GRE, как бы эта форма ни называлась. Трансляция адресов добавляет вторую трудность, потому что у GRE нет портов и транслятору приходится следить за идентификатором вызова. Некоторые домашние маршрутизаторы поставляются с помощником, который это обрабатывает; многие — нет, и никакая дополнительная запись разрешения TCP такого поведения не создаст.
Там, где реальным требованием является современный туннель, выбирайте решение, которое намеренно использует TCP или UDP, вместо надежды на то, что транслятор угадает правильно.
Инкапсуляция определяет, что видит фильтр
Инкапсуляция меняет внешний пакет, а правило сопоставляется именно с внешним пакетом. Нативный ESP — это протокол 50, тогда как прохождение через NAT заворачивает ESP внутрь UDP 4500, чтобы он пережил трансляцию адресов. Фильтр, разрешающий UDP 4500, никогда не видит протокол 50, а фильтр, написанный для протокола 50, никогда не совпадает с завёрнутой формой.
Спросите, на какой инкапсуляции договорились клиент и шлюз, а затем напишите правило именно для этой внешней формы и ничего больше.
Пишите правило так, чтобы кто-то мог его проверить
Выражайте каждое правило как семейство адресов, внешний протокол, транспортные порты при наличии, направление и обе конечные точки. Рецензент может сравнить эту фразу с записью пакетов и прийти к вердикту. Инструкцию открыть 47 никто не может проверить, и именно поэтому она годами живёт в процедурных книгах.
Добавьте проверку, которая это доказывает: подключитесь, одновременно записывая трафик на внешнем интерфейсе, и подтвердите внешний протокол и порт, которые действительно видны в следе.