Нищо в сокета не помни кой интерфейс е пренесъл заявката, затова маршрут по подразбиране през VPN с пълен тунел може да прихване отговор, който принадлежи на WAN. Услугата не игнорира входящия интерфейс; Linux маршрутизира локално генериран отговор по дестинация и политика по източник. Правило, базирано на източника, може вместо това да изпраща само отговорите на услугата през пълна WAN таблица, оставяйки обичайния изход в тунела. Портът остава отворен, докато отговорът излиза по грешния път, поради което симптомът изглежда едностранен.

Погрешното схващане: отговорите следват интерфейса, по който са пристигнали

Изглежда логично пакет, пристигнал на eth0, да излезе на eth0. Филтри на пакети без състояние могат да се напишат така, а tcpdump от входящата страна показва заявката точно там, където се очаква. Маршрутизацията не работи така за трафик, който хостът сам създава.

Щом услугата приеме връзката, отговорът ѝ е нов локално генериран пакет. Ядрото проверява правилата за маршрутизация за дестинацията и източника на отговора, а маршрутът по подразбиране на VPN е напълно валиден отговор. Нищо в сокета не помни кой интерфейс е пренесъл заявката.

Затова симптомът изглежда едностранен: заявките пристигат, отговорите изчезват. Затова и добавянето на firewall правило за входящия порт не променя нищо. Пакетът не се блокира по пътя навътре; той се маршрутизира другаде по пътя навън. Проследете отговора с търсене, уточнено по източник, и отклонението става видимо.

Какво всъщност маршрутизира ядрото: адресът на източника

Ключът, който ви трябва, е локалният адрес, който услугата използва за отговори. На хост с илюстративен eth0 адрес 192.0.2.10/24 и шлюз 192.0.2.1 този адрес присъства на интерфейса. На облачна VM публичният адрес може да е транслатиран горе по веригата и да липсва в госта, затова използвайте адреса, който хостът действително притежава.

Прегледайте текущото състояние, преди да резервирате номер на таблица или приоритет на правило. Съществуващите правила по политика могат да засенчат ново, а стара таблица със същия номер може вече да носи несвързани маршрути:

ip -4 addr show dev eth0
ip -4 rule show
ip -4 route show table all

След това изберете таблица по източник. Правилото съвпада с отговори, които вече носят 192.0.2.10, точно локално прекратения трафик, който искате да изключите. Препращаният трафик и пакетите от други локални адреси не съвпадат.

Изградете пълна таблица за връщане, а не половин маршрут по подразбиране

Таблица само с маршрут по подразбиране не е достатъчна. Ядрото все още трябва да резолвне шлюза, а тази резолюция изисква свързания префикс в същата таблица. Таблица без този префикс се проваля при резолюцията на шлюза дори когато маршрутът ѝ по подразбиране изглежда правилен. Добавете и двете, след което насочете правилото по източник към таблицата:

ip -4 route add table 100 192.0.2.0/24 dev eth0 src 192.0.2.10
ip -4 route add table 100 default via 192.0.2.1 dev eth0
ip -4 rule add priority 1000 from 192.0.2.10/32 lookup 100

Използвайте истинския префикс и шлюз, вместо да копирате примера. Облачен интерфейс, конфигуриран като /32 с шлюз на линка, изисква различен свързан маршрут, а таблица, изградена от грешен префикс, се проваля на първия хоп. Атрибутът src указва предпочитания източник за този маршрут; той не замества правилото по източник.

Редът също има значение. Широко правило с по-нисък номер на приоритет се оценява първо, затова правилото по източник трябва да бъде достигнато преди всяко правило, което би върнало този трафик в основната таблица. Проверете приоритетите с ip rule show след добавянето, не само при зареждане.

Проверете с търсене, уточнено по източник

Помолете ядрото да маршрутизира тестова дестинация от адреса на услугата. Отговорът трябва да посочи eth0 и WAN шлюза, а не тунела:

ip -4 route get 198.51.100.25 from 192.0.2.10

След това направете нова разрешена връзка и наблюдавайте двете посоки. Търсене, което избира правилната таблица, докато живата връзка все още се проваля, сочи към филтриране на обратния път или firewall правило, а не към таблицата. Проверете тези контроли, преди да изключите нещо глобално.

Поставете окончателните маршрути и правилото под мрежовия мениджър, който притежава интерфейса. Промените на адреса, подновяването на DHCP и повторните връзки на VPN пренаписват състоянието на ядрото, а добавено на ръка правило изчезва или сочи към остарял шлюз след следващото събитие.

Къде спира това изключение

Правилото изключва локално прекратен трафик от един адрес на източник. То не покрива портове, публикувани от Docker, DNAT или услуги, препращани през хоста, защото тези пакети се маршрутизират като препращан трафик и никога не носят локалния източник на хоста по същия начин. Такива схеми обикновено изискват маркировка, поставена при входа, и правило, което съвпада с маркировката.

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

Документирайте изключението с неговия номер на таблица, приоритет на правилото и точния адрес на източника. Следващата промяна във VPN или интерфейса може тихо да го счупи, а бележка, която назовава трите стойности, се проверява по-бързо от преоткриване на симптома от доклад на клиент.

Ако услугата все още отговаря по грешния път, след като търсенето по източник мине, сравнете адреса на източника на живия сокет с този в правилото. Услуга, вързана към wildcard адрес, може да избере различен източник от тествания адрес, и това разминаване е оставащата празнина.

Подобни статии