Conntrack: коли перевірки проходять, а трафік зупиняється
Stateful firewall вирішує шлях з’єднання один раз, при його створенні, тому тривалий потік може тримати застаріле рішення, поки кожна свіжа проба проходить успішно.
У цій статті 5 розділів
- Stateful firewall ухвалює рішення про пересилання та NAT для з’єднання на його першому пакеті і зберігає його в таблиці станів на весь час життя потоку. Зміни маршрутизації та політики не застосовуються до потоків, які вже існують.
- Безперервний потік, як-от syslog через TCP, реплікація бази даних, форвардер метрик або тунель, може тримати одне з’єднання тижнями. Якщо мережа під ним змінюється, цей потік зберігає старе рішення, тоді як ping і нові з’єднання отримують нове, тому кожна перевірка проходить.
- Моніторте те, що надходить, а не те, що працює: лічильники байтів відносно очікуваного обсягу, заповненість таблиці станів і наскрізну перевірку того, що дані дійшли. Застиглий потік виправляється видаленням його запису стану, а не перезавантаженням firewall.
Рішення ухвалюється один раз
Відстеження з’єднань існує для того, щоб firewall оцінював політику один раз на потік, а не один раз на пакет. Перший пакет зіставляється з правилами, результат пересилання та NAT записується в таблицю станів, і кожен наступний пакет цього потоку є пошуком за хешем. netfilter conntrack, таблиця станів pf в OPNsense і таблиця з’єднань у Cisco Firepower працюють саме так. Запис живе, доки потік не закриється або не спливе його таймаут простою, а для встановленого TCP-з’єднання цей таймаут вимірюється днями.
Наслідок легко пропустити: зміна маршрутизації, правила NAT або інтерфейсу впливає на наступний потік, а не на потоки, що вже є в таблиці.
Два способи, якими це тихо губить трафік
Застарілий шлях. Змінюється маршрут, переїжджає інтерфейс, редагується пул NAT. Нові з’єднання йдуть новим шляхом. Тривалий потік зберігає свій початковий вихідний інтерфейс або прив’язку NAT, тому його пакети виходять старим шляхом: до наступного вузла, який їх більше не пересилає, або без трансляції, якої тепер очікує інша сторона. TCP-стек відправника терпляче повторює передачу по з’єднанню, яке він усе ще вважає встановленим, отримувач нічого не бачить, і жоден процес з обох боків не відмовив.
Повна таблиця. Досягнуто nf_conntrack_max, зазвичай через сканер, клієнта за NAT з тисячами коротких потоків або довгі таймаути на завантаженій машині. Ядро записує один рядок у лог і починає відкидати перший пакет нових з’єднань, тоді як наявні потоки тривають. Перевірка працездатності, яка повторно використовує відкрите з’єднання, і далі проходить. Користувачі, які відкривають нові, отримують таймаути.
Жодне з цього не з’являється в моніторингу процесів. Демон працює, listener прив’язаний, правило на місці.
Чому перевірки працездатності проходять
Ping, проба TCP connect і симулятор шляху firewall кожен створює новий потік або оцінює політику наново, тому кожен отримує поточне, правильне рішення. Зелене показання є правдивим, але про неправильний об’єкт. Запитання, яке треба поставити firewall, не в тому, що він зробив би з новим пакетом, а в тому, що він робить з потоками, які вже тримає.
# the live flows from one source, with their state and NAT binding
conntrack -L -s <source>
# how full the table is
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
# the kernel's own report of a full table
journalctl -k | grep -i 'nf_conntrack: table full'Потік, який передує останній зміні маршрутизації і показує вихід або трансляцію, яких не дало б жодне поточне правило, і є записом, на який треба дивитися.
Що моніторити
Надходження, а не живучість. Рядки за хвилину, що лягають у базу даних колектора, повідомлення за хвилину на приймачі syslog, позиція реплікації, яка просувається. Пласка лінія і є тривогою, що б не казав стан процесу.
Лічильники відносно очікування. Лічильник байтів на правилі, яке несе потік, зростає приблизно зі швидкістю потоку. Правило, яке має бути завантаженим, а майже пласке, означає, що пакети збігаються з іншим правилом або не надходять зовсім.
Заповненість таблиці станів. Налаштуйте тривогу на nf_conntrack_count як частку від nf_conntrack_max задовго до заповнення, а також на повідомлення ядра про повну таблицю, яке інакше лежить у лозі непрочитаним.
Синтетичні перевірки, схожі на справжній трафік. Проба, яка тримає тривале з’єднання і проштовхує через нього запис через інтервали, з перевіркою на іншому кінці, тестує те, що ламається. Свіжий ping тестує те, що не ламається.
Після кожної зміни маршрутизації або NAT перелічіть потоки, старші за зміну, і свідомо вирішіть, чи скидати їх.
Виправлення є скальпелем
Видаліть стан для ураженого джерела. Наступний пакет створить свіжий запис з поточним рішенням, і потік відновиться.
conntrack -D -s <source>Перезавантаження або повне скидання теж працює і кладе разом із собою кожне інше живе з’єднання. Для повної таблиці виправлення полягає в тому, щоб підняти nf_conntrack_max разом з розміром хешу, скоротити таймаут established там, де дні не потрібні, і знайти клієнта, який створює потоки.
Прямі відповіді
Чому firewall каже allow, а трафік не проходить?+
Симулятор шляху обчислює те, що отримав би новий пакет. Наявний потік прив’язаний до рішення, ухваленого при його створенні, а симулятор не читає таблицю станів. Вивантажте живі потоки для цього джерела і порівняйте їхній вихід і трансляцію з тим, що дали б поточні правила.
Чому ping працює, а потік застосунку ні?+
Ping створює короткочасні потоки, які спливають за секунди, тому кожен отримує свіже рішення. Потік тримає одне тривале з’єднання і зберігає те рішення, з яким народився.
Як знайти з’єднання, що застрягло на неправильному інтерфейсі?+
conntrack -L з фільтром за джерелом на netfilter, перегляд таблиці станів на pf або Firepower. Шукайте потоки, старші за останню зміну мережі, чий вихід або прив’язку NAT не дало б їм жодне поточне правило.
Як це виправити без перезавантаження firewall?+
Видаліть записи стану для цього джерела через conntrack -D. Наступний пакет оцінюється наново. Усе інше в таблиці залишається недоторканим.
Потік замовк, поки кожна перевірка зелена?
Поговоріть з інженером, який читає таблицю станів, а не симулятор.
Поговоріть з інженером (shell cta.talkToEngineer)Ви дійшли до кінця.
Застосуйте прочитане на практиці
Що ви запускаєте?
Розкажіть нам про навантаження, трафік і вимоги до відновлення. Почніть з конструктора сервера або обговоріть деталі з інженером.
Написано інженерами, які будують і експлуатують інфраструктуру, про яку йдеться.Поговоріть з інженером
