65 лет полету человека в космос! Хостинг и домены со скидкой
до 22.04.2026 Подробнее
Выберите продукт

Linux TCP reset: почему возникает Connection reset by peer и как быстро найти причину

TCP RST и ошибка Connection reset by peer выглядят как «всё сломалось», но чаще всего источник находится за 15–30 минут. Ниже — пошаговый алгоритм: как поймать RST в tcpdump, проверить ss и очереди, оценить conntrack, найти REJECT в nftables/iptables и отделить клиент→прокси от прокси→бэкенд.
Linux TCP reset: почему возникает Connection reset by peer и как быстро найти причину

Что означает Connection reset by peer и откуда берётся TCP RST

Ошибка connection reset by peer появляется на стороне клиента (или промежуточного сервиса), когда TCP-соединение было принудительно сброшено пакетом RST. В прикладных логах это выглядит одинаково — «сокет внезапно умер», но причины бывают разные: от корректного поведения приложения до фаервола и проблем stateful-слоя.

Важно: RST — это не таймаут и не «потеря пакетов». Это явный сигнал «я не хочу/не могу продолжать это соединение». Его может отправить:

  • сам сервер или приложение;
  • reverse proxy (Nginx/HAProxy/Envoy) между клиентом и бэкендом;
  • ядро Linux из-за TCP-политик, локального фаервола или conntrack;
  • сетевое устройство по пути (stateful firewall, NAT, фильтрация).

Практический смысл диагностики всегда один: понять, кто именно отправил RST, и почему он решил, что соединение нелегитимно или нежелательно.

Быстрый алгоритм: как за 10 минут локализовать источник RST

Этот «скелет» проверки помогает не гадать и быстро сузить круг поиска.

  1. Поймайте RST в трафике на нужном хосте и убедитесь, что действительно летит RST, а не разрыв по таймауту.

  2. Определите отправителя по направлению (src/dst) в строке tcpdump. RST «уходит с вашего сервера» — ищите причину на сервере/прокси/фаерволе. RST «приходит на ваш сервер от клиента» — чаще клиент закрыл соединение (или его прокси/фаервол).

  3. Посмотрите состояния сокетов и очереди: ss, много ли FIN_WAIT/CLOSE_WAIT, есть ли давление по Send-Q/Recv-Q.

  4. Проверьте conntrack: заполнение таблицы, ошибки, несостыковки state, признаки INVALID.

  5. Проверьте фаервол (nftables/iptables): правила с REJECT, обработка ct state, особенно invalid.

  6. Если есть reverse proxy, разделите проблему на два TCP-участка: клиент→прокси и прокси→бэкенд. RST может происходить на одном сегменте, а ошибку вы увидите на другом.

Если вы отлаживаете это на публичном сервисе, удобнее делать диагностику на отдельной машине или в отдельном контуре. Для продакшена часто выбирают VDS, чтобы иметь полный контроль над сетевым стеком, фаерволом и сбором дампов.

Вывод tcpdump с TCP RST для определения стороны, отправившей reset

tcpdump: как увидеть TCP RST и понять, кто его отправил

Начинайте с точечного захвата по порту и флагу RST. Обычно этого достаточно, чтобы понять направление.

sudo tcpdump -ni any 'tcp port 443 and (tcp[tcpflags] & tcp-rst != 0)'

Для конкретного клиента добавьте фильтр host:

sudo tcpdump -ni any 'host 203.0.113.10 and tcp port 443 and (tcp[tcpflags] & tcp-rst != 0)'

Если нужно больше контекста (seq/ack, опции), включите подробный режим:

sudo tcpdump -ni any -vv 'tcp port 443 and (tcp[tcpflags] & tcp-rst != 0)'

Как читать вывод:

  • Видите «server.443 > client.51512: Flags [R]» — RST отправил сервер (или то, что работает на сервере и формирует ответы, включая фаервол с REJECT).

  • Видите «client.51512 > server.443: Flags [R]» — клиент сбросил соединение (или его промежуточный узел).

Нюанс: на хосте с NAT/прокси вы видите трафик уже после трансляции. Чтобы не ошибиться, сравнивайте захват на входящем и исходящем интерфейсе (например, eth0 и lo/docker0) и, по возможности, на второй стороне (бэкенд/прокси).

Паттерн: RST сразу после SYN

Если клиент отправляет SYN, а в ответ почти мгновенно прилетает RST, чаще всего это одно из трёх:

  • порт закрыт (нет слушающего сокета);
  • фаервол настроен на reject вместо drop и шлёт RST;
  • reverse proxy не слушает нужный IP/порт или слушает только IPv6/IPv4.

С этого места удобно сразу перейти к проверке слушающих сокетов через ss -lntp.

Паттерн: RST в середине сессии

Если RST приходит после обмена данными, типовые причины такие:

  • приложение/прокси закрыло сокет «жёстко» (краш, рестарт, лимиты, аварийное завершение);
  • сеть убивает «долгие простои» (idle): помогают keepalive и согласованные таймауты;
  • conntrack потерял состояние (переполнение таблицы или агрессивные таймауты), и фаервол начал считать трафик INVALID;
  • асимметричная маршрутизация: туда и обратно пакеты идут разными путями, stateful firewall видит только половину.
FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

ss: что смотреть в состояниях TCP и очередях

ss — самый быстрый способ понять, что происходит с сокетами прямо сейчас. Сначала посмотрите общую сводку:

ss -s

Дальше — соединения по нужному порту с очередями, таймерами и PID/процессом (если доступно):

ss -ntpi sport = :443

На что смотреть в первую очередь:

  • Много FIN_WAIT1/FIN_WAIT2 — соединения закрываются, но закрытие «не дожимается» второй стороной. При стабильном росте ищите таймауты, keepalive, балансировку, фильтрацию ответных пакетов.

  • Много CLOSE_WAIT — удалённая сторона закрыла соединение, а ваше приложение не закрывает сокет. Это почти всегда прикладная проблема (утечка дескрипторов, зависшие воркеры), и RST может быть вторичным эффектом перегруза.

  • Send-Q/Recv-Q — если очереди не нулевые постоянно и растут, вероятна перегрузка приложения или проблемы с чтением/записью (backpressure).

Проверка слушающих портов

Когда RST «сразу», сначала убедитесь, что кто-то реально слушает порт и слушает на нужном адресе:

ss -lntp | sed -n '1p;/(:443)/p'

Частый промах: сервис привязан только к 127.0.0.1 или к одному IP, а клиенты приходят на другой адрес; или слушает IPv6, а клиенты ходят по IPv4 (и наоборот).

conntrack: как stateful-слой приводит к reset

Если у вас NAT и stateful-фильтрация (почти любой хост с nftables/iptables, особенно шлюз/прокси), трафик проходит через подсистему conntrack. И две категории проблем там встречаются чаще всего:

  • Переполнение таблицы при высокой нагрузке, сканировании или большом числе коротких соединений. Итог — дропы новых соединений и «случайные» сбои текущих.

  • Несовпадение ожидаемого state с реальным трафиком из-за асимметричной маршрутизации, слишком коротких таймаутов, особенностей прокси и балансировщиков.

Проверяем заполнение conntrack

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

Если nf_conntrack_count регулярно подходит вплотную к nf_conntrack_max, это весомая причина нестабильности (включая разрывы и неожиданные RST), особенно на узлах с NAT или большим числом источников.

Быстро посмотреть статистику:

sudo conntrack -S

И, если нужно, выборку по порту (на загруженных системах будет шумно):

sudo conntrack -L -p tcp --dport 443 | head

Что с INVALID: ядро и фаервол

Если фаервол «рубит» ct state invalid, вы можете терять легитимные пакеты при асимметрии или расхождении таймаутов, а приложение видеть последствия как обрывы и reset. Проверьте, нет ли уже подсказок в логах ядра:

sudo dmesg -T | grep -i conntrack | tail -n 50

Отдельная практичная тема — правильно писать правила stateful-фильтрации и не ловить легитимный трафик как INVALID. Если у вас смешаны контейнеры, bridge-интерфейсы и внешний доступ, полезно свериться с разбором: как не сломать сеть Docker правилами iptables/nftables.

nftables и iptables: правила, которые реально порождают RST

Фаервол может порождать RST напрямую, если используется reject with tcp reset. Это не всегда плохо (иногда так быстрее сообщить «порт закрыт»), но при ошибках в матчах превращается в загадочный connection reset by peer.

nftables: где искать REJECT с reset

sudo nft list ruleset

Ищите конструкции вида reject with tcp reset, а также правила на ct state invalid или слишком широкие матчинг-условия, которые могут срабатывать на легитимный трафик после NAT/прокси.

Если у вас включены счётчики (counter), смотрите их рост на подозрительных правилах. Если счётчиков нет, добавлять их «в проде» стоит только понимая контур фильтрации и план отката.

iptables: быстрый поиск REJECT

sudo iptables -S
sudo iptables -nvL

В iptables RST обычно появляется при цели REJECT с параметром --reject-with tcp-reset. Если счётчики на таком правиле растут синхронно с жалобами клиентов — источник reset найден.

Сценарий: reverse proxy и «не тот» state

Частая причина при reverse proxy: трафик клиент→прокси проходит, но прокси→бэкенд ходит через другой интерфейс/маршрут/таблицу, и stateful firewall видит «обрывки» соединений. Симптом: часть запросов работает, часть заканчивается reset; в tcpdump видны внезапные RST/ACK.

Проверка: убедиться, что ответный трафик возвращается тем же путём (policy routing, несколько uplink, floating IP). Здесь очень помогает параллельный tcpdump на прокси и бэкенде и сравнение seq/ack.

Reverse proxy: почему reset видит клиент, хотя виноват бэкенд (и наоборот)

С reverse proxy вы всегда имеете минимум два независимых TCP-соединения:

  • клиент ↔ прокси;
  • прокси ↔ бэкенд (upstream).

Если бэкенд отвалился или сбросил соединение, прокси может отдать клиенту 502/504 на HTTP-уровне (идеальный вариант) или сам сбросить клиентское соединение, если уже начал стримить ответ или работает в особом режиме.

И наоборот: если клиент оборвал соединение (таймаут, мобильная сеть, пользователь закрыл вкладку), прокси закрывает upstream, и в логах бэкенда это выглядит как reset «от прокси».

Правило диагностики: при наличии reverse proxy всегда проверяйте tcpdump и состояния сокетов на обоих сегментах. Иначе легко обвинить не ту сторону.

Keepalive и idle-timeout между сегментами

TCP keepalive (L4) и HTTP keep-alive (L7) — разные механизмы, но оба влияют на число соединений и вероятность упереться в NAT/conntrack. Если upstream-соединения живут долго, а по пути есть NAT с маленьким idle-timeout, то простои заканчиваются обрывом и иногда RST при следующей попытке отправить данные.

Признак почти железный: reset случается «ровно через N секунд/минут» простоя.

Схема двух TCP-сегментов при reverse proxy: клиент-прокси и прокси-бэкенд

FIN_WAIT, TIME_WAIT и «полуразрывы»: когда кажется, что виноват TCP

Много записей в ss по состояниям часто пугает, но важно отделить «много соединений» от «плохих соединений».

  • TIME_WAIT — нормальное состояние после корректного закрытия. Большое число TIME_WAIT обычно означает много коротких соединений и может давить на conntrack и локальные порты, но само по себе не ошибка.

  • FIN_WAIT1/FIN_WAIT2 — одна сторона начала закрытие, но не завершила рукопожатие закрытия. Если это массово и долго держится, ищите, кто «не отвечает»: приложение, фаервол, асимметрия.

  • CLOSE_WAIT — красный флаг для приложения: оно не закрывает сокеты после FIN. Дальше возможны исчерпание файловых дескрипторов и косвенные reset.

Быстрые счётчики по состояниям:

ss -ant state time-wait | wc -l
ss -ant state fin-wait-1 | wc -l
ss -ant state fin-wait-2 | wc -l
ss -ant state close-wait | wc -l

Привязка к процессам (где доступно):

sudo ss -antp | grep -E 'FIN-WAIT|CLOSE-WAIT' | head
Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Типовые причины TCP reset в проде и что делать

1) Порт не слушается или слушается не там

Симптом: RST сразу после SYN, обычно 100% воспроизводимо с конкретного IP или протокола (IPv4/IPv6).

Проверки:

ss -lntp
ss -lntp | grep ':443'

Что делать: исправить привязку (0.0.0.0 vs 127.0.0.1), добавить отдельные listen для IPv4/IPv6, корректно опубликовать порт в контейнерах и на балансировщике.

2) Фаервол делает REJECT с tcp reset

Симптом: reset «как будто от сервера», при этом приложение живо. В правилах растут счётчики на REJECT.

Проверки:

sudo nft list ruleset
sudo iptables -nvL

Что делать: сузить матчинг правил, убедиться, что ct state established,related пропускается до «жёстких» правил, а с invalid действовать осторожно (часто сначала логировать и разбирать причину).

3) conntrack table full

Симптом: проблемы усиливаются на пиках, много коротких коннектов, «плавает» доступность, растут дропы и ошибки.

Проверки:

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
sudo conntrack -S

Что делать: уменьшить число новых соединений (keepalive/пулинг), увеличить лимиты conntrack с пониманием потребления RAM, по возможности разгрузить NAT/stateful-функции, ограничить мусорный входящий трафик на периметре.

4) Reverse proxy режет соединения по таймаутам

Симптом: reset на длинных запросах, стриминге, больших аплоадах; в error-log прокси — таймауты и ошибки upstream.

Проверки: корреляция времени между логами прокси и выводом tcpdump; ss на прокси и бэкенде.

Что делать: привести таймауты к реальной длительности операций, настроить keepalive и лимиты, вынести долгие операции в асинхронные очереди.

Если проксирование TCP/UDP сделано через Nginx stream, полезно свериться с практикой настройки и диагностики: балансировка TCP/UDP в Nginx stream и типовые проблемы.

5) Нет keepalive, сеть убивает idle

Симптом: соединение «жило», потом простояло, и следующий пакет приводит к reset. Особенно часто — мобильные сети, корпоративные фаерволы, NAT.

Что проверить в sysctl:

sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_intvl
sysctl net.ipv4.tcp_keepalive_probes

Что делать: включить и подстроить keepalive на уровне приложения (предпочтительно) и/или на уровне ОС (аккуратно, влияет на весь хост), согласовать таймауты с балансировщиками и прокси.

Мини-чеклист для инцидента: что собрать в тикет

Чтобы не повторять диагностику по кругу, фиксируйте минимальный набор фактов:

  • время инцидента и IP/порт клиента;
  • фрагмент tcpdump с RST (кто отправил);
  • вывод ss -s и ss -ntpi по порту;
  • nf_conntrack_count/nf_conntrack_max и conntrack -S в момент проблемы;
  • фрагмент ruleset (nft list ruleset или iptables -S) с упором на reject, ct state, invalid;
  • если есть reverse proxy — его error-log вокруг события и понимание, на каком из двух TCP-сегментов случился reset.

Итог

connection reset by peer — это не диагноз, а симптом. В Linux почти всегда можно быстро найти источник TCP RST, если идти от факта (RST в tcpdump) к состояниям (ss), затем к stateful-слою (conntrack) и политике фильтрации (nftables/iptables).

Самые частые причины в проде: неверные правила фаервола (включая REJECT с reset), переполнение conntrack под нагрузкой и несогласованные таймауты/keepalive в связке reverse proxy ↔ backend.

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

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

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, сетью, зеркалом, прокси, временем ...