Ноутбук перебуває в /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

Від чого відмовляється м'який режим, і де

М'який режим усе ще відхиляє джерело, до якого не дістався б жоден маршрут, і перестає відхиляти підроблене джерело, яке випадково маршрутизується. На ноутбуці це вузька поступка. На пристрої, що пересилає чужий трафік, той самий вибір значно ширший. Тому одне й те саме налаштування несе два дуже різні значення залежно від того, де воно працює.

Повністю вимикати перевірку на хості, який пересилає трафік інших людей, — єдине виправлення, якого слід уникати. Нуль відкидає перевірку, яку м'який режим дбайливо зберігає. Якщо хост пересилає за інших, відстоюйте натомість варіант із правилом політики з попереднього розділу.

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

Схожі статті