Акция Панель управления ispmanager для VDS — первый месяц бесплатно
до 31.07.2026 Подробнее
Выберите продукт

Linux conntrack и nf_conntrack: TIME_WAIT, NAT и ошибка nf_conntrack table full

Conntrack в Linux — основа stateful firewall и NAT. Под нагрузкой таблица переполняется: nf_conntrack table full, nat drops, таймауты и 502/504. Ниже — диагностика через ss/conntrack, оценка лимитов, buckets и таймаутов, плюс безопасный план тюнинга.
Linux conntrack и nf_conntrack: TIME_WAIT, NAT и ошибка nf_conntrack table full

Conntrack в Linux — это подсистема отслеживания соединений (connection tracking), на которой держится stateful-фильтрация в netfilter и большинство сценариев NAT. Когда таблица conntrack переполняется, вы видите классическую ошибку nf_conntrack table full, а пользователи — «случайные» таймауты, 502/504 на прокси, обрывы запросов и рост ретраев.

Ниже разберём, почему это происходит, при чём здесь TIME_WAIT, почему NAT делает ситуацию хуже, как быстро подтвердить диагноз и как подбирать nf_conntrack_max (conntrack max), nf_conntrack_buckets (conntrack buckets) и таймауты без гаданий.

Что такое conntrack и где он живёт

Conntrack — это таблица записей о потоках (flows), которую ведёт модуль nf_conntrack. Для каждого потока ядро хранит метаданные: направление, протокол, состояние и параметры, по которым netfilter понимает, «свой» это пакет или новый, надо ли применять NAT так же, как на первом пакете, и можно ли пропустить трафик по stateful-правилам firewall.

Важно: conntrack — не список сокетов приложения и не список TCP-состояний в смысле TCP-стека. Это отдельная таблица netfilter. Поэтому «много TIME_WAIT» в ss не равно «переполнится conntrack», но часто коррелирует: оба явления появляются при большом числе коротких соединений.

Когда включён NAT (SNAT/MASQUERADE/DNAT), conntrack становится обязательным звеном. Без записи conntrack ядро не сможет стабильно применять трансляцию адресов/портов для обратного трафика. Отсюда и типичная связка: NAT, рост числа flows и симптомы в виде nat drops и «плавающих» таймаутов.

Conntrack — это «память» netfilter о потоках. NAT и stateful firewall зависят от неё, а переполнение даёт симптомы, похожие на деградацию сети без явной причины.

Симптомы: nf_conntrack table full, nat drops и внезапные таймауты

Чаще всего всё начинается с сообщений ядра вида:

nf_conntrack: table full, dropping packet

Это означает, что достигнут лимит записей таблицы conntrack — параметр net.netfilter.nf_conntrack_max. Новые потоки перестают нормально создаваться, пакеты дропаются, а соединения не устанавливаются или «подвисают».

При NAT последствия обычно заметнее: не создалась запись — не применился NAT или не нашлась обратная трансляция, и вы получаете «плавающие» проблемы, особенно на исходящем трафике с большого числа клиентов за одним адресом.

Типичные внешние проявления:

  • рост ошибок соединения у приложений (connect timeout, read timeout);
  • на прокси/балансировщиках рост 499/502/504;
  • провалы health-check в Kubernetes/ingress из-за невозможности открыть новые соединения;
  • в мониторинге: рост retransmits, рост очередей, падение доли успешных запросов.

Если подобные симптомы проявляются на пограничном узле или на busy-прокси, удобнее разбирать и фиксировать такие инциденты на ресурсе, где вы контролируете ядро и сетевые лимиты: для этого обычно выбирают VDS.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Схема таблицы conntrack и ключевые счётчики nf_conntrack_count и nf_conntrack_max

TIME_WAIT: почему его много и как он связан с conntrack

TIME_WAIT — это TCP-состояние на стороне, которая закрыла соединение активно (часто клиент). Оно нужно, чтобы «дожить» возможные задержанные пакеты старого соединения и не перепутать их с новым соединением с теми же 4-туплами (src/dst ip/port).

Почему TIME_WAIT выстреливает на серверах:

  • много коротких HTTP-запросов без keep-alive;
  • микросервисы открывают TCP на каждый вызов;
  • неправильно настроенные пулеры (или их отсутствие) к БД/кэшам;
  • частые health-check, которые создают новые соединения.

Как это пересекается с conntrack: при большом числе коротких соединений растёт количество conntrack-записей в «короткоживущих» состояниях. Даже если сокеты уже в TIME_WAIT и приложение отпустило ресурсы, conntrack-запись может ещё жить по своим таймаутам и занимать слот в таблице.

Нужно помнить и обратное: лечить переполнение conntrack только «борьбой с TIME_WAIT» — плохая стратегия. Если у вас NAT-шлюз или узел с большим east-west трафиком, conntrack может упереться в лимит даже при умеренном TIME_WAIT — просто из-за количества параллельных потоков.

Диагностика: как понять, что упираемся именно в conntrack

1) Быстрая проверка лимита и текущей загрузки

Начните с двух чисел: сколько записей сейчас и какой максимум.

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

Если nf_conntrack_count близок к nf_conntrack_max (условно 80–95% под нагрузкой) и параллельно есть сообщения nf_conntrack table full — диагноз почти подтверждён.

Посмотреть сообщения ядра:

dmesg -T | grep -E "nf_conntrack|conntrack"

2) Сколько у вас TIME_WAIT на самом деле (ss и conntrack рядом, но отдельно)

Для TCP-состояний используйте ss. Это не conntrack, но даёт полезный индикатор профиля нагрузки:

ss -tan state time-wait | wc -l

Срез по локальным портам (помогает быстро найти «виноватый» сервис/клиентскую роль):

ss -tan state time-wait | awk '{print $4}' | sed 's/.*://' | sort | uniq -c | sort -nr | head

По запросу “ss conntrack” часто ждут команду «покажи conntrack через ss». Прямого просмотра conntrack через ss нет: ss показывает сокеты, а conntrack — отдельная таблица. Но совместный анализ (ss для TCP состояний и conntrack для flows) даёт полноценную картину.

3) Просмотр conntrack-таблицы и топов по источникам

Удобнее всего использовать пакет conntrack (conntrack-tools). Список текущих записей может быть огромным, поэтому чаще нужны счётчики и «топы».

conntrack -S

Быстрый топ по источникам (кто создаёт больше всего flows):

conntrack -L | awk '{for(i=1;i<=NF;i++) if ($i ~ /^src=/) {split($i,a,"="); print a[2]}}' | sort | uniq -c | sort -nr | head

Топ по назначениям (куда уходит больше всего flows):

conntrack -L | awk '{for(i=1;i<=NF;i++) if ($i ~ /^dst=/) {split($i,a,"="); print a[2]}}' | sort | uniq -c | sort -nr | head

Если всплеск идёт из одного источника/подсети, это может быть легитимный пик (прокси, очередь, массовый деплой), а может быть «петля ретраев» или внешняя активность. В обоих случаях важно быстро ответить на вопрос «кто забивает таблицу».

4) NAT-аспект: когда кончаются порты и появляются nat drops

На SNAT/MASQUERADE узлах есть отдельная боль: даже если conntrack ещё не «полон», можно упереться в доступный диапазон исходящих портов для трансляции на одном публичном IP. Тогда симптомы похожи на conntrack-проблему: новые исходящие соединения не создаются, растут таймауты и повторы.

Косвенные признаки: очень много коротких исходящих соединений к одному/нескольким внешним сервисам, множество клиентов за NAT, «пила» в ошибках на пиках. В таких случаях думайте не только о conntrack: часто нужно увеличивать пул SNAT-адресов или снижать количество новых соединений (keep-alive, HTTP/2, reuse).

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Параметры: conntrack max, conntrack buckets и таймауты

nf_conntrack_max (conntrack max)

net.netfilter.nf_conntrack_max — жёсткий максимум количества записей. Увеличение лимита почти всегда первое, что делают, но важно учитывать RAM и реальную потребность.

Проверить значение:

sysctl net.netfilter.nf_conntrack_max

Установить временно (до перезагрузки):

sysctl -w net.netfilter.nf_conntrack_max=262144

Постоянно — через файл в /etc/sysctl.d/:

cat > /etc/sysctl.d/99-conntrack.conf <<'EOF'
net.netfilter.nf_conntrack_max = 262144
EOF
sysctl --system

nf_conntrack_buckets (conntrack buckets)

nf_conntrack_buckets — размер хеш-таблицы (количество «корзин»). Он влияет на скорость операций поиска/вставки (коллизии) и CPU-профиль. Частая ошибка: поднять только nf_conntrack_max в разы и оставить маленькие buckets, после чего таблица становится «тяжёлой» по CPU.

Посмотреть текущее значение:

cat /proc/sys/net/netfilter/nf_conntrack_buckets

Практическое правило: buckets часто выбирают примерно как nf_conntrack_max / 4 или / 8. На высоких PPS обычно выгоднее ближе к / 4, на умеренной нагрузке — / 8 может быть достаточно.

Нюанс: на многих системах nf_conntrack_buckets нельзя безопасно менять «на лету» (зависит от ядра/дистрибутива). Часто требуется выставлять размер хеша при загрузке модуля nf_conntrack параметром hashsize. Планируйте это на окно обслуживания.

Пример конфигурации параметра модуля:

cat > /etc/modprobe.d/nf_conntrack.conf <<'EOF'
options nf_conntrack hashsize=65536
EOF

После этого обычно нужна перезагрузка, чтобы параметр применился.

Таймауты conntrack и «мусор» в таблице

Даже с большим nf_conntrack_max таблица может быстро заполняться, если записи живут слишком долго относительно вашей модели трафика (например, много half-open, много UDP без ответов, много коротких TCP). Тогда помогает настройка таймаутов, но делать это нужно осторожно: агрессивное уменьшение может ломать «долгие» соединения (VPN, WebSocket, некоторые API), особенно при NAT.

Посмотреть текущие таймауты (набор параметров зависит от ядра):

sysctl -a | grep -E '^net\.netfilter\.nf_conntrack_' | head -n 80

Обычно полезно понимать смысл следующих параметров:

  • net.netfilter.nf_conntrack_tcp_timeout_established — сколько держать долгоживущие TCP-сессии;
  • net.netfilter.nf_conntrack_tcp_timeout_time_wait — сколько держать TIME_WAIT именно в conntrack (это не то же самое, что TIME_WAIT в ss);
  • net.netfilter.nf_conntrack_udp_timeout и net.netfilter.nf_conntrack_udp_timeout_stream — критично для DNS и «псевдо-стримовых» UDP-сценариев;
  • net.netfilter.nf_conntrack_tcp_timeout_syn_sent и net.netfilter.nf_conntrack_tcp_timeout_syn_recv — важны при большом числе недоустановленных TCP.

Если проблема — именно «много коротких TCP и быстрый churn», то чаще выигрывают не таймауты, а снижение количества новых соединений (keep-alive/пулинг) плюс правильная связка nf_conntrack_max и hashsize.

Пример настройки sysctl и параметра hashsize для nf_conntrack

Практический план: что делать при переполнении conntrack

Шаг 1. Зафиксировать факт и профиль нагрузки

Соберите минимум (идеально — прямо в момент инцидента):

  • nf_conntrack_count и nf_conntrack_max под нагрузкой;
  • логи ядра с nf_conntrack table full;
  • conntrack -S и несколько «топов» по src/dst;
  • срез ss по time-wait и established для понимания churn vs long-lived.

Шаг 2. Быстро убрать «пожар» корректным увеличением лимита

Если вы упёрлись в лимит, временно увеличьте net.netfilter.nf_conntrack_max с запасом в 2–4 раза от пика nf_conntrack_count. Это даст системе «дышать», пока вы ищете первопричину. Делайте это только если есть доступная RAM и вы понимаете, что рост таблицы не бесконечный (например, нет бесконтрольной петли ретраев).

Шаг 3. Привести в соответствие conntrack buckets

После увеличения nf_conntrack_max проверьте, не стал ли узким местом CPU из-за коллизий. Если nf_conntrack_buckets слишком мал, планируйте изменение hashsize при следующем окне обслуживания.

Шаг 4. Уменьшить количество новых соединений (самый недооценённый пункт)

Чтобы TIME_WAIT и conntrack churn не росли:

  • включайте keep-alive на клиентах и балансировщиках, используйте HTTP/2 там, где это уместно;
  • для внутренних сервисов включайте пулы соединений (к БД, к Redis, к upstream API);
  • ограничьте слишком частые health-check, которые создают новые TCP;
  • проверьте ретраи: часто именно лавина «ретраи на таймаут» добивает conntrack.

Если узкое место — пул к БД, полезно настроить отдельный пулер (например, pgbouncer): см. гайд по pgbouncer и пулу подключений к PostgreSQL.

Шаг 5. NAT-архитектура: масштабируйте SNAT, если упираетесь в один IP

Если это NAT-шлюз для множества клиентов, технически правильное решение часто архитектурное: добавить несколько публичных адресов для SNAT (распределить исходящие соединения), либо сегментировать трафик, либо уменьшить churn соединений. Простое увеличение conntrack может лишь отложить проблему.

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

Частые ошибки при тюнинге sysctl nf_conntrack

  • Поднять только net.netfilter.nf_conntrack_max и забыть про buckets. Итог: таблица перестаёт «кончаться», но CPU растёт, появляются задержки и дропы на пиках.

  • Слишком агрессивно уменьшить таймауты. NAT начнёт «забывать» трансляции, долгие соединения рвутся, отладка становится крайне неприятной.

  • Путать TIME_WAIT в TCP и таймауты conntrack. Это разные сущности. Лечить одно параметрами другого — прямой путь к побочным эффектам.

  • Списывать всё на «DDoS» без измерений. Переполнение conntrack бывает и на легитимной нагрузке: микросервисы, кривые ретраи, отсутствие keep-alive.

Мини-чеклист для продакшена

Порядок действий, который обычно срабатывает и не требует гаданий:

  1. Проверить nf_conntrack_count/nf_conntrack_max и наличие nf_conntrack table full в логах.
  2. Снять conntrack -S и топы по src/dst в момент проблемы.
  3. Снять ss -tan по time-wait/established для понимания churn.
  4. Временно поднять net.netfilter.nf_conntrack_max, если прямо сейчас идёт дроп трафика.
  5. Запланировать корректный hashsize (buckets) и применить в окно обслуживания.
  6. Уменьшить количество новых соединений: keep-alive, пулеры, ретраи, health-check.
  7. Для NAT-шлюзов отдельно оценить лимит исходящих портов и необходимость нескольких SNAT IP.

Заключение

Conntrack — один из тех компонентов Linux, который обычно «просто работает», пока вы не упираетесь в масштаб. Ошибка nf_conntrack table full почти всегда означает, что изменилась нагрузка: стало больше коротких соединений, вырос NAT-трафик, появились ретраи или сервер получил новую роль (прокси, балансировщик, шлюз).

Правильный подход — не только увеличить nf_conntrack_max, но и выстроить диагностику (ss для TCP-состояний и conntrack для flows), подобрать hashsize (buckets) и, по возможности, снизить churn соединений на уровне приложений и архитектуры. Если у вас подобные проблемы на фронтенде с Nginx, отдельно посмотрите материал про балансировку TCP/UDP: настройка Nginx stream для TCP/UDP и типовые грабли.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...