Представьте медиаприставку на домашнем канале, которая должна выходить в интернет только через туннель. Когда туннель падает, приложение должно остановиться, а не тихо продолжать через физический интерфейс. Получить такое поведение — задача межсетевого экрана, а не маршрутизации, и разница важна, потому что маршрут можно заменить перезапуском демона, а фильтр остаётся там, где вы его поставили. Далее — как путь пакета на самом деле принимает решение и как затем ограничить исключения, которые позволяют туннелю переподключаться.

Локальный выход — это другой хук, чем пересылка

Пакет, покидающий приложение на машине, проходит через выходной хук; пакет, который машина маршрутизирует для другого хоста, проходит через пересылку. Политика, упоминающая только forward, ограничивает второй случай и оставляет первый широко открытым, поэтому многие замки выхода выглядят правильными и ничего не делают. Сопоставление интерфейса относится к тому же правилу: oifname "tun0" accept пропускает трафик, который уже был маршрутизирован через туннель. Маршрутизация и фильтрация также остаются разными решениями, поэтому маршрут к провайдеру может существовать, пока фильтр отвергает пакет. Именно на это разделение вы и полагаетесь.

Шлюзу, который пересылает трафик других устройств, нужны оба хука. Замыкание только выхода защищает саму машину и оставляет каждому клиенту ниже свободу утекать.

Список исключений пишите от конечной точки наружу

Начните с конечной точки туннеля: один адрес назначения или небольшой утверждённый набор, транспортный протокол и порт назначения, например udp dport 1194 ip daddr 203.0.113.7 accept. Если клиент разрешает имя хоста, начальному обмену DNS нужно собственное правило, ограниченное резолвером и портом 53, а не общее разрешение на адрес этого резолвера. Каждое исключение должно называть причину своего существования. Разрешение на весь UDP-трафик к порту VPN покрывает гораздо больше, чем та единственная аутентифицированная служба, которую вы имели в виду.

Начальное разрешение имён — это место, где замки обычно гниют. Набор адресов, обновляемый по таймеру, требует определённого поведения при неудачном обновлении, и этим поведением не может быть открытие канала до успеха. Обновляйте через туннель, пока туннель поднят, иначе возвращайтесь к последней известной исправной конечной точке.

Локальное администрирование требует того же подхода. Управляющая подсеть не заслуживает доверия только потому, что её адреса приватные, а правило, которое ей доверяет, приглашает второй путь вокруг замка.

Сопоставление интерфейса не доказывает исправность туннеля

Правила, которые принимают всё, что выходит из tun0, предполагают, что пакет на этом интерфейсе пришёл из туннеля. Имена интерфейсов пересоздаются, а имя не является криптографической идентичностью. Партнёр тоже может исчезнуть, пока интерфейс остаётся поднятым, и тогда правило превращается в очень убедительное бездействие.

Отслеживание соединений добавляет родственную ловушку. Широкое правило для установленных соединений воспроизводит разрешение, полученное потоком ранее, поэтому сеанс, начатый до падения туннеля, продолжает работать и после. Ограничьте приём по состоянию теми интерфейсами и адресами, которые вы действительно имеете в виду, иначе вы построили замок, который открывается сам. Правила входа и выхода тоже отвечают на разные вопросы, и укрепление одного при игнорировании другого оставляет машину доступной в том направлении, о котором вы не подумали.

Что переживает падение демона

Фильтр, установленный скриптом, который запускается после подъёма туннеля, исчезает вместе с туннелем — именно в тот момент, когда он был нужен. Загружайте замок при загрузке и позвольте демону управлять только его исключениями.

Удаление маршрута по умолчанию тоже не замена. Маршрут — это состояние, которым владеет и которое переписывает демон, и его удаление может отнять путь, нужный для переподключения. IPv6 нужен собственный план, потому что обнаружение соседей и объявления маршрутизатора — это службы канала, которые должны продолжать работать, пока обычный трафик заблокирован. DHCP относится к той же категории. Запишите это как исключения с целью, а не обнаруживайте позже как сбои.

Путь восстановления перед внедрением

Проверьте замок так, как он откажет: загрузка без туннеля, убийство демона, смена конечной точки и переподключение. Каждый случай должен останавливать приложения и оставлять канал восстановления работающим. Делайте это из консоли, потому что удалённая оболочка — это сеанс, который чаще всего запирается вашим же правилом.

Затем проверьте, куда ещё может дотянуться обычное приложение, с безвредным адресом назначения и запросом, который вы можете проверить. Нужный результат — отказ на канале и успех через туннель, а не двусмысленный тайм-аут, который может означать и то и другое. Держите набор правил у того же владельца, что и остальной межсетевой экран, вместо замены всей таблицы из шелл-скрипта. Политика, в которой каждое разрешение может обосновать себя, стоит больше, чем длинный набор правил, который никто не может объяснить.

Похожие статьи