Новые соединения не устанавливаются: заполнена ли таблица conntrack?

Новые соединения не устанавливаются: заполнена ли таблица conntrack?

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

В статье используется Debian 13; все проверки выполняются в сетевом пространстве имён хоста. После оплаты сервера CloudUDP данные для доступа можно посмотреть в панели управления. Подключение к Linux выполняется по SSH; если адресов несколько, используйте первый. Приведённые ниже действия не изменяют сетевые правила и не удаляют состояния существующих соединений.

1. Убедитесь, что проблемный трафик проходит через conntrack

Механизм отслеживания соединений (conntrack) хранит сведения о протоколе, адресах, состоянии и тайм-ауте потоков трафика. Эти данные используются для сопоставления по состоянию и для NAT. Одно соединение приложения не соответствует одному его потоку выполнения, а запись в таблице может сохраняться некоторое время после закрытия соединения приложением. Частое создание коротких соединений, аномальное сканирование или пересылаемый трафик могут повышать заполнение таблицы.

Сначала установите инструменты диагностики и прочитайте конфигурацию:

sudo apt-get update
sudo apt-get install conntrack
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
sudo conntrack -S
sudo nft list ruleset

Наличие ct state или NAT в правилах — повод проверить ёмкость таблицы conntrack. Однако отсутствие таких правил не доказывает, что отслеживание вообще не выполняется. Если при чтении параметров сообщается, что они не существуют, сначала проверьте модули и фактический путь трафика. Не загружайте модули вслепую лишь ради того, чтобы получить ожидаемый вывод.

Результаты внутри контейнера не могут напрямую заменять результаты на хосте. Пересылка трафика хостом и обработка внутри контейнера могут происходить в разных сетевых пространствах имён, поэтому обязательно фиксируйте, где выполнялись команды. Иначе низкое заполнение таблицы в контейнере легко принять за объяснение потерь пакетов на хосте.

Не используйте conntrack -F как штатный способ восстановления. Очистка таблицы удаляет существующие состояния и может нарушить сеансы, зависящие от сопоставления по состоянию или NAT. Кроме того, она уничтожает диагностические данные, которые следовало сохранить.

2. Соберите данные о заполнении и приросте ошибок за один период

nf_conntrack_count — текущее число записей, а nf_conntrack_max — верхний предел их количества. Приближение к пределу означает уменьшение запаса, но само по себе не доказывает, что именно поэтому запросы завершаются неудачно. Команда conntrack -S выводит статистику по процессорам. Для каждого показателя нужно суммировать значения по всем процессорам и сравнивать разницу между двумя замерами, а не считать отдельную строку итогом по всему серверу.

umask 077
out=$(mktemp -d /var/tmp/ct-check.XXXXXX)
for sample in 1 2; do
  {
    date -Is
    sysctl net.netfilter.nf_conntrack_count
    sysctl net.netfilter.nf_conntrack_max
    sudo conntrack -S
  } > "$out/sample-$sample.txt"
  if [ "$sample" -eq 1 ]; then
    sleep 10
  fi
done
sudo journalctl -k --since "-10 min" --no-pager \
  > "$out/kernel.txt"
printf '%s\n' "$out"

Интервал между замерами здесь приведён только как пример. Замеры должны охватывать период, в котором возникают отказы приложения. В первую очередь проверяйте, продолжают ли расти insert_failed, drop и early_drop, а также появляются ли в журнале ядра сообщения о заполнении таблицы соединений. Набор полей может различаться между версиями ядра; отсутствие отдельного поля не означает, что система работает нормально.

Одновременно сохраните число неудачных попыток приложения установить новые соединения, объём запросов и исходные сообщения об ошибках. Если сервер недавно перезагружался, точка отсчёта накопительных счётчиков уже изменилась: не вычитайте напрямую значения до и после перезагрузки. То, что в часы низкой нагрузки счётчики ошибок перестали расти, также не подтверждает достаточную ёмкость при пиковой нагрузке.

3. Определите, почему накапливаются записи

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

Не начинайте с выгрузки всей таблицы

На загруженном хосте полный вывод записей сам по себе увеличивает затраты на диагностику, а также раскрывает адреса участников обмена. Сначала изучите сводные счётчики. Если подробный вывод действительно нужен, ограничьте протокол и объём:

sudo timeout 5s conntrack -L -p tcp -o extended 2>/dev/null \
  | head -n 100

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

Параллельно проверяйте процессы, принимающие соединения, ошибки приложения и ответы вышестоящих сервисов. Если в таблице есть запас, а соответствующие счётчики не растут, переходите к поиску блокировок приложения, проблем маршрутизации или потерь пакетов на других участках. Не продолжайте настройку conntrack без подтверждающих данных.

Не начинайте с сокращения тайм-аутов для всех протоколов. Тайм-аут определяет, как долго сохраняется состояние неактивного соединения; чрезмерное сокращение может нарушить работу длительных соединений. Отсутствие повторного использования соединений в пуле, неконтролируемые повторные попытки после ошибок и подобные проблемы нужно исправлять на вызывающей стороне.

4. Вносите обратимые изменения с учётом доступной памяти

Увеличение лимита лишь разрешает хранить больше записей и не устраняет источник аномального трафика. Записи потребляют память ядра; конкретные затраты зависят от расширений протоколов, конфигурации ядра и других факторов. Поэтому точный бюджет нельзя рассчитать по фиксированной норме «столько-то байт на запись».

Перед изменением сохраните вывод free -h и содержимое /proc/meminfo, а затем изучите кеши объектов ядра с помощью sudo slabtop -o. Slab — механизм кеширования, которым ядро пользуется для управления объектами. Даже статистика объектов conntrack в этих кешах не охватывает все связанные затраты памяти.

Если данные подтверждают нехватку ёмкости и имеется запас памяти, проверяйте результат небольшими изменениями. Следующий пример увеличивает исходный лимит на четверть. Это только размер пробного изменения, а не рекомендуемая фиксированная настройка:

old=$(sysctl -n net.netfilter.nf_conntrack_max) || exit 1
case "$old" in
  ''|*[!0-9]*) exit 1 ;;
esac
new=$((old + old / 4))
printf 'old=%s new=%s\n' "$old" "$new"
sudo sysctl -w net.netfilter.nf_conntrack_max="$new"

Не закрывайте этот сеанс и сохраните исходное значение. Повторите замеры при сопоставимом объёме запросов. Если отказы не сократились, не увеличивайте параметр снова и снова. Верните исходное значение и проверьте другие диагностические данные:

sudo sysctl -w net.netfilter.nf_conntrack_max="$old"

Перед откатом проверьте текущее число записей. Если оно уже превышает исходный лимит, сначала снизьте интенсивность создания новых соединений, иначе откат может снова вызвать нехватку ёмкости. Не меняйте одновременно число хеш-корзин, тайм-ауты протоколов и правила межсетевого экрана: для проверки нужно изменять только один фактор.

5. Решайте, сохранять ли настройку, по результатам работы приложения

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

После подтверждения результата запишите проверенное числовое значение в /etc/sysctl.d/90-conntrack-capacity.conf. Перед записью проверьте, не определён ли тот же параметр в других конфигурационных файлах, чтобы порядок загрузки не привёл к его перезаписи. Загрузите только этот файл, не применяя заодно другие непроверенные настройки сервера:

sudo sysctl -p /etc/sysctl.d/90-conntrack-capacity.conf
sysctl net.netfilter.nf_conntrack_max

Файл должен содержать строку net.netfilter.nf_conntrack_max = проверенное_целое_число, где поясняющий текст необходимо заменить фактическим числом. После следующей перезагрузки, запланированной эксплуатационной командой, снова проверьте действующее значение и ошибки загрузки. Не перезагружайте рабочий сервер немедленно только ради проверки параметра.

В завершение сохраните исходное и новое значения, период замеров, объём запросов, разницы счётчиков и условия отката. Цель управления ёмкостью conntrack — не получить более высокое число, а объяснить отказы соединений, доказать эффективность изменения и иметь возможность повторно проверить те же данные при изменении нагрузки.

Часто задаваемые вопросы

Почти полная таблица conntrack доказывает исчерпание ёмкости?

Нет. Нужно сопоставить прирост insert_failed, drop и early_drop с сообщениями ядра и ошибками новых соединений за тот же период. Высокая загрузка указывает на риск, но ни она, ни отдельный счётчик не доказывают причину.

Стоит ли очистить conntrack для быстрого восстановления?

Это не штатный способ восстановления. Очистка удаляет состояния действующих соединений и может нарушить сеансы, зависящие от NAT или проверки состояния. Сначала следует сохранить счётчики и журналы, затем устранить аномальный источник соединений либо изменить лимит с учётом памяти.

Выделенный сервер EPYC 7543P от $454 в месяц

Выделенные серверы с помесячной арендой

Перед оплатой проверьте конфигурацию и итоговую сумму. Все цены указаны в долларах США.