Сеть как источник проблем: nftables, conntrack, дропы

Рейтинг: 62.3% · 11 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Сеть как источник проблем: nftables, conntrack, дропы

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы (вы здесь)
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Когда виноват не сервис, а сама сеть

Классическая ситуация: приложение "висит", соединения отваливаются по таймауту, а в логах самого сервиса - тишина. Ты лезешь в код, в базу, в нагрузку на диск - и ничего. А виновата сеть. Точнее, не провод и не свитч, а то, что происходит с пакетом внутри ядра Linux: его может тихо съесть фаервол, может не хватить места в таблице соединений, или пакет не пролезает по размеру и фрагментируется. Самое подлое тут - дропы (drop, отброшенные пакеты) почти всегда молчаливые. Никто тебе не напишет в лог "я выкинул твой SYN". Просто клиент будет ретраить и упираться в таймаут.

Этот урок - про базовую сетевую диагностику без погружения в дебри netfilter. Разберём три самых частых источника боли на шлюзах, прокси и обычных серверах: фаервол (nftables и iptables), таблицу отслеживания соединений conntrack linux, и счётчики дропов. Новичку важно понять одно: прежде чем чинить, надо доказать, что теряются именно пакеты, и найти место потери. Гадать тут нельзя - в сети слишком много слоёв, и наугад ты будешь крутить не те ручки.

Изображение

Как пакет идёт через ядро и где его теряют

Представь конвейер. Пакет приходит на сетевую карту, попадает в кольцевой буфер (ring buffer) и очередь ядра, проходит через netfilter (это и есть фаервол - набор правил nftables или iptables), по пути ядро отмечает его в таблице соединений conntrack, и только потом он доходит до сокета приложения. На каждом этапе пакет может быть потерян, и для каждого этапа есть свой счётчик.
  • Буфер карты/очередь переполнены - приложение или ядро не успевают разгребать. Видно в drop на интерфейсе.
  • Правило фаервола явно дропает пакет. Видно по счётчику конкретного правила.
  • Таблица conntrack заполнена - новые соединения некуда записать. Видно в dmesg и в статистике conntrack.
  • Очередь сокета (backlog) переполнена - приложение принимает слишком медленно. Видно по overflow в статистике TCP.
  • MTU и фрагментация - пакет слишком большой для пути, его режут или отбрасывают. Видно по таймаутам на больших передачах при живых пингах.
Conntrack - это записная книжка ядра (модуль nf_conntrack). На каждое соединение (TCP-сессию, поток UDP, ICMP) заводится строчка: кто, куда, в каком состоянии. Это нужно, чтобы ответные пакеты пропускались автоматически (правило типа "разрешить established") и чтобы работал NAT. Книжка не бесконечна: у неё есть лимит nf_conntrack_max. Когда строчек становится больше лимита - привет, новые соединения дропаются. На нагруженном шлюзе или прокси это беда номер один. Важный нюанс на 2026: начиная с ядра 5.15, по умолчанию nf_conntrack_max приравнивается к числу хеш-бакетов (nf_conntrack_buckets), так что заводская планка нередко ниже, чем кажется, и упереться в неё проще, чем во времена старых ядер.

Практика: смотрим правила, conntrack и счётчики

Шаг 1. Что вообще дропает фаервол. На современных дистрибутивах с systemd (включая Astra Linux и RED OS) бэкенд по умолчанию - nftables, а iptables там обычно лишь обёртка iptables-nft поверх него. Сначала смотрим правила целиком:

Код: Выделить всё

sudo nft list ruleset
Чтобы реально видеть, какое правило срабатывает, нужны счётчики. В nftables они не считаются автоматически - в правило надо явно добавить ключевое слово counter. Тогда счётчики видно так (флаг -a добавляет handle правил, -s печатает компактно):

Код: Выделить всё

sudo nft -a list ruleset
В выводе у правила появляется блок вида

Код: Выделить всё

counter packets 8841 bytes 530112
. Запусти команду дважды с паузой - у растущего дроп-правила packets прыгнет на тысячи, вот оно, узкое место. Удобно следить в реальном времени:

Код: Выделить всё

watch -n 2 "nft list ruleset | grep -A1 drop"
Если хозяйство ещё на классическом синтаксисе iptables, диагностика начинается ровно со счётчиков (тут они есть всегда):

Код: Выделить всё

sudo iptables -L -n -v
Разберём флаги: -L показать правила, -n не резолвить имена (быстрее и честнее, видишь IP и порты), -v показать счётчики. Вывод по колонкам:

Код: Выделить всё

Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out  source       destination
 1532  92K ACCEPT     tcp  --  eth0   *    0.0.0.0/0    0.0.0.0/0   tcp dpt:22
 8841 530K DROP       all  --  eth0   *    10.0.0.0/8   0.0.0.0/0
Колонка pkts - сколько пакетов попало под правило, bytes - сколько байт, target - что сделали (ACCEPT/DROP/REJECT). Главный трюк iptables диагностика: ищи правило с DROP, у которого pkts быстро растёт между двумя замерами. Именно оно режет твой трафик. Не забывай про policy цепочки (в примере INPUT policy DROP): если ни одно правило не подошло, пакет молча падает по умолчанию.

Шаг 2. Таблица соединений. Сначала самое важное - заполненность. Это первое, что надо проверять при странных дропах под нагрузкой:

Код: Выделить всё

sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
Те же значения лежат файлами в

Код: Выделить всё

/proc/sys/net/netfilter/
. Первое число - сколько соединений сейчас в таблице, второе - лимит. Если count подобрался вплотную к max (скажем, 130000 из 131072) - ты в зоне аварии, новые соединения уже дропаются. Норма - когда count держится с хорошим запасом, процентов до 70-80 от max. На 2026 правильнее смотреть не только заполненность, но и счётчики ошибок самого conntrack - они скажут, теряем ли мы соединения прямо сейчас:

Код: Выделить всё

sudo conntrack -S
Это per-CPU статистика. Ключевые поля: insert_failed - не удалось вставить новое соединение в таблицу (явный признак переполнения или гонок), drop - пакеты, отброшенные conntrack, early_drop - ядро выкинуло старую запись, чтобы освободить место под новую (таблица под завязку), invalid - пакеты, не подошедшие ни под одно соединение. Если insert_failed или early_drop растут - диагноз поставлен, дело в conntrack. Теперь смотрим сами соединения:

Код: Выделить всё

sudo conntrack -L
Одна строка выглядит так:

Код: Выделить всё

tcp 6 431999 ESTABLISHED src=10.0.0.5 dst=93.184.216.34 sport=51614 dport=443 src=93.184.216.34 dst=10.0.0.5 sport=443 dport=51614 [ASSURED] mark=0 use=1
Читаем по полям: tcp - протокол, 6 - его номер, 431999 - таймаут записи в секундах (через сколько ядро забудет соединение, если затихнет), ESTABLISHED - состояние. Дальше дважды идут src/dst/sport/dport: первая четвёрка - как соединение пошло (оригинал), вторая - обратное направление (reply), порты местами поменяны (так видно NAT, если адреса отличаются). [ASSURED] значит, трафик шёл в обе стороны, такую запись ядро не выкинет первой при нехватке места. use - счётчик ссылок. Полезный быстрый срез - сколько соединений в каждом состоянии:

Код: Выделить всё

sudo conntrack -L | awk "{print \$4}" | sort | uniq -c | sort -rn
Если десятки тысяч висят в TIME_WAIT или SYN_SENT - это сигнал: либо клиент молотит короткими соединениями, либо до кого-то не достучаться (полуоткрытые сессии).

Шаг 3. Счётчики дропов. Дропы на интерфейсе:

Код: Выделить всё

ip -s link show eth0
В блоке RX (приём) и TX (передача) смотри поля dropped и errors. Если dropped растёт - очередь не успевает, ядро выкидывает пакеты ещё до приложения; частая причина - переполнение ring buffer карты (лечится ethtool -G) или софтовой очереди. Глубже копаем общесистемную статистику. Тут важная актуализация: netstat считается устаревшим (пакет net-tools), на 2026 предпочтительны nstat и ss из пакета iproute2. Они читают те же счётчики, но точнее и без legacy-парсинга:

Код: Выделить всё

nstat -az | grep -iE "Retrans|Drop|Overflow|Prune|ListenDrops"
Старый эквивалент -

Код: Выделить всё

netstat -s | grep -iE "retrans|drop|overflow"
, если nstat недоступен. Что искать: TcpRetransSegs (segments retransmitted) - повторно отправленные сегменты, признак потерь на пути; TcpExtListenOverflows / TcpExtListenDrops - очередь принятых соединений (accept backlog) переполнилась, приложение не успевает звать accept(); TcpExtTCPRcvQDrop и PruneCalled - буфер приёма забит. Грубое правило для сетевых дропов linux: доля ретрансмитов до 0.1 процента - норма, выше 1 процента - уже бьёт по скорости, выше 5 - всё плохо. Чтобы перевести в долю, дели TcpRetransSegs на TcpOutSegs. Текущую загрузку backlog конкретного слушателя удобно глянуть так:
В колонках Recv-Q (сколько соединений ждёт accept) и Send-Q (размер backlog) для слушающего сокета: если Recv-Q упёрся в Send-Q - очередь полна, отсюда и ListenOverflows.

Conntrack table full и MTU: две классические засады

Если на шлюзе под нагрузкой рвутся соединения - первым делом ищи в журнале ядра. На systemd это journalctl, но dmesg тоже работает:

Код: Выделить всё

sudo journalctl -k --grep="conntrack"
sudo dmesg | grep -i conntrack
Сообщение

Код: Выделить всё

nf_conntrack: table full, dropping packet
- это диагноз conntrack table full. Книжка переполнена, новые соединения отбрасываются, старые работают. Быстрое лечение - поднять лимит (как временную меру, до перезагрузки):

Код: Выделить всё

sudo sysctl -w net.netfilter.nf_conntrack_max=262144
Чтобы пережило перезагрузку - положи строку в файл вроде

Код: Выделить всё

/etc/sysctl.d/10-conntrack.conf
и примени

Код: Выделить всё

sysctl --system
. Имей в виду: каждая запись ест около 300 байт ядерной памяти, так что миллион соединений - это сотни мегабайт RSS у ядра, не безлимит. И учти упомянутый нюанс ядра 5.15+: если просто крутишь nf_conntrack_max, хеш-таблица (nf_conntrack_buckets) сама не растёт, и длина цепочек в бакетах увеличивается - под большие значения буфер стоит увеличивать вместе с лимитом. Но крутить число вверх вслепую - лечить симптом. Сначала пойми, кто наплодил столько соединений: не зациклился ли клиент, не висят ли тысячи TIME_WAIT, не пора ли сократить таймауты. На Astra Linux и RED OS всё это работает так же - ядро generic с netfilter, пути в /proc, sysctl и conntrack идентичны.

Вторая засада - MTU и фрагментация. MTU это максимальный размер полезной нагрузки на интерфейсе (обычно 1500 байт). Если где-то на пути MTU меньше (VPN/WireGuard, туннель GRE/IPsec, PPPoE), большой пакет либо режется на фрагменты, либо отбрасывается, если выставлен флаг DF ("не фрагментировать"). Симптом коварный: пинг ходит (маленькие пакеты), а SSH-сессия виснет на длинном выводе или большой файл не качается - типичная картина MTU blackhole. Проверка - пинг с запретом фрагментации и ростом размера:

Код: Выделить всё

ping -M do -s 1472 8.8.8.8
Здесь 1472 + 8 (заголовок ICMP) + 20 (заголовок IP) = ровно 1500. Если такой пинг проходит, а на байт больше (-s 1473) выдаёт "Frag needed and DF set" - значит реальный MTU пути меньше, ты нашёл причину. На IPv6 фрагментацию делает только отправитель, поэтому путь с заниженным MTU там ещё чувствительнее.

Типичные грабли и заблуждения
  • "В логах сервиса пусто, значит сеть ни при чём". Наоборот. Дроп пакета - это событие ядра, а не приложения. Сервис просто не дождётся данных.
  • "REJECT и DROP - одно и то же". Нет. REJECT шлёт отлуп (RST или ICMP unreachable), и клиент сразу понимает отказ. DROP молчит, и клиент висит до таймаута. По симптому "долгие таймауты" часто виноват именно DROP.
  • "Подниму nf_conntrack_max побольше и забуду". Это отложит проблему, а не решит. Каждая запись ест память, буфер бакетов сам не растёт, и при реальной утечке соединений ты упрёшься снова.
  • "ping проходит - сеть в порядке". ping проверяет только маленькие ICMP-пакеты. MTU, conntrack и TCP-фаервол он не покрывает.
  • "Достаточно посмотреть заполненность count/max". Запас может быть, а соединения всё равно теряться из-за гонок вставки - смотри conntrack -S, поля insert_failed и early_drop.
  • "netstat - наше всё". На 2026 он устарел; привыкай к nstat, ss и ip -s, они точнее и есть в iproute2 из коробки.
Глубже копнуть: eBPF, когда счётчиков мало

Счётчики говорят "сколько" и "на каком слое", но не всегда "почему именно тут". На 2026 зрелый инструмент для точечной охоты за дропами - eBPF: ядро экспортирует tracepoint skb:kfree_skb с причиной удаления пакета (поле reason появилось в ядре 5.17+ и стало по-настоящему информативным). Готовые утилиты, которые стоит знать: классический dropwatch (показывает место в коде ядра, где умер пакет), pwru от Cilium (трассирует путь конкретного пакета по стеку) и retis от netfilter. Самый быстрый разовый срез - через bpftrace:

Код: Выделить всё

sudo bpftrace -e "tracepoint:skb:kfree_skb { @[args->reason] = count(); }"
Это покажет распределение причин дропов (например NF_DROP от фаервола, TCP_INVALID, переполнение очереди) без перебора десятков счётчиков. Для новичка вывод - не пугаться: сначала простые счётчики (nft, conntrack -S, nstat), и только если они не дают однозначного ответа - eBPF-трассировка причины.

Мини-лаба: повтори руками прямо сейчас
  • Глянь свои правила:

    Код: Выделить всё

    sudo nft -a list ruleset
    или

    Код: Выделить всё

    sudo iptables -L -n -v
    . Найди строки с DROP и запомни их счётчики.
  • Повтори команду через 10 секунд. Сравни packets/pkts у дроп-правил - что-нибудь растёт?
  • Проверь conntrack по двум осям: заполненность

    Код: Выделить всё

    sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
    и ошибки

    Код: Выделить всё

    sudo conntrack -S | grep -E "insert_failed|early_drop|drop"
    .
  • Посмотри

    Код: Выделить всё

    sudo conntrack -L | head
    и найди в строках state, sport, dport, флаг [ASSURED].
  • Сними дропы интерфейса:

    Код: Выделить всё

    ip -s link show
    и статистику TCP

    Код: Выделить всё

    nstat -az | grep -iE "Retrans|Overflow"
    .
  • Глянь backlog слушателей: (колонки Recv-Q/Send-Q).
  • Проверь MTU пути:

    Код: Выделить всё

    ping -M do -s 1472 8.8.8.8
    . Подними размер до 1473 и посмотри на разницу.
Контрольные вопросы
  • Чем отличается DROP от REJECT и почему по симптому "долгий таймаут" подозревают именно DROP?
  • Какие команды/поля сравнить, чтобы понять, что таблица conntrack близка к переполнению, и почему одной заполненности count/max мало (что добавляет conntrack -S)?
  • Какое сообщение в журнале ядра прямо указывает на conntrack table full и что оно означает для новых соединений? Какой нюанс ядра 5.15+ важен при подъёме лимита?
  • Почему ping может проходить, а большая передача по TCP - виснуть, и при чём тут MTU и флаг DF?
Что запомнить

Сеть рвётся тихо: дропы не пишут в лог приложения, их надо искать по счётчикам. Алгоритм короткий: правила фаервола (nft -a list ruleset / iptables -L -n -v, ищем растущий DROP) - состояние conntrack (count против max плюс conntrack -S на insert_failed/early_drop, journalctl на table full) - счётчики дропов и ретрансмитов (ip -s, nstat, ss) - проверка MTU пингом с запретом фрагментации. Где счётчиков не хватает - eBPF (bpftrace по skb:kfree_skb, dropwatch, pwru). На 2026 привыкай к iproute2-стеку вместо устаревшего netstat. И главное правило: не гадай и не крути лимиты вслепую - сначала докажи место потери цифрами, потом чини причину, а не симптом.
👍3 ❤️4 🔥1 😄 🤔
Аватара пользователя
envoydev
Сообщения: 1
Зарегистрирован: 03 июн 2026, 09:14

Re: Сеть как источник проблем: nftables, conntrack, дропы

Сообщение envoydev »

Спасибо, наконец дошло почему сервис молчит а клиенты висят. Сегодня нашёл у себя дроп-правило с растущим pkts, реально светилось. Раньше бы полез в код приложения и убил час.
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
Spanky6235
Сообщения: 1
Зарегистрирован: 03 июн 2026, 16:26

Re: Сеть как источник проблем: nftables, conntrack, дропы

Сообщение Spanky6235 »

А я думал хватит посмотреть count vs max, а оно норм было. Запустил conntrack -S и там early_drop тикает как бешеный. Без этого совета так бы и крутил max вслепую.
👍1 ❤️ 🔥1 😄 🤔1
Ответить
← Предыдущая глава
Задержки и потери в сети: ping, mtr, диагностика латентности
Следующая глава →
Что такое системный вызов и зачем его трассировать

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
Похожие запросы: ss как посмотреть открытые сокеты и соединенияНастройка сети на Mac

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость