Ноутбук находится в /24 офиса через Ethernet и одновременно подключается к серверу OpenVPN, который живёт в той же /24. Коллега пингует адрес туннеля; запрос явно приходит, но ничего не возвращается. Журнал туннеля чист, а просмотр сайтов всё ещё работает, значит туннель — неверный подозреваемый. Проверка источника IPv4 на принимающей машине отбрасывает пакет раньше, чем что-либо его прочитает.

Отбрасывание происходит раньше, чем что-либо прочитает пакет

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

Клиент здесь держит 10.66.0.9 на своём туннеле, а сервер OpenVPN отвечает с 192.168.80.10 внутри офисного префикса. Коллега с 192.168.80.25 пингует адрес туннеля, поэтому запрос проходит через локальную сеть, сервер направляет его в туннель, и он приходит на туннельный интерфейс клиента с офисным адресом источника. В таблице маршрутизации этой машины офисный префикс принадлежит устройству Ethernet, а не туннелю. Проверка сравнивает интерфейс поступления с маршрутом, находит несоответствие и отбрасывает пакет, поэтому коллега видит полную потерю, пока оба конца сообщают об исправном туннеле.

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

Докажите действующий режим, прежде чем трогать любой sysctl

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

tcpdump -ni tun0 icmp and host 192.168.80.25
ip route get 192.168.80.25
sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.tun0.rp_filter

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

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

Что на самом деле принимает каждый режим rp_filter

Ядро показывает три значения на интерфейс, и это не три оттенка одного правила. Ноль отключает проверку. Единица строгая и требует, чтобы источник маршрутизировался обратно через интерфейс поступления. Двойка мягкая и требует лишь, чтобы в таблице существовал какой-нибудь маршрут к источнику, куда бы он ни указывал.

ValueNameAcceptsStill rejects
0offany source at allnothing on this check
1stricta source routed back out the arrival interfacea source whose route points elsewhere
2loosea source with any route in the tablea source with no route at all

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

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

Выберите наименьшее изменение, которое снимает неоднозначность

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

Там, где офисный префикс нужен только через Ethernet, уберите его из маршрутов, которые тянет профиль, и адрес станет доступен по одному пути. Когда оба пути действительно должны сосуществовать, закрепите источник и устройство правилом политики вместо того, чтобы ослаблять проверку на каждом интерфейсе. Это сохраняет строгую фильтрацию для всего остального на машине и документирует исключение там, где следующий инженер будет его искать.

Какой бы путь вы ни выбрали, запишите его в drop-in-файл sysctl, а не в живую команду. Задайте ключи all и default вместе, чтобы переподключение не могло тихо вернуть строгий режим.

# /etc/sysctl.d/99-rp-filter.conf
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.all.rp_filter = 2
sysctl --system

От чего отказывается мягкий режим, и где

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

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

Оставьте заметку, в которой названы два интерфейса, пересекающийся префикс и точная проба, которая теперь проходит. Это полезнее следующему инженеру, чем строка о том, что фильтрация была настроена.

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