Выберите продукт

Debian/Ubuntu: SSH Broken pipe и Connection reset by peer — причины и пошаговая диагностика

Если SSH на Debian или Ubuntu обрывается с Broken pipe, Connection reset by peer или зависает после простоя, причина часто не в самом OpenSSH. Разберём пошаговую диагностику: логи, keepalive, firewall, conntrack, MTU/MSS и сетевой путь.
Debian/Ubuntu: SSH Broken pipe и Connection reset by peer — причины и пошаговая диагностика

Ошибки вида client_loop: send disconnect: Broken pipe, ssh: connect to host ... Connection reset by peer и внезапный обрыв SSH-сессии на Debian или Ubuntu — одна из самых неприятных проблем в администрировании. Особенно когда всё работает нестабильно: утром вход нормальный, вечером сессия обрывается через пару минут простоя, а иногда соединение падает прямо во время копирования файлов или редактирования конфигов.

На практике причина почти никогда не сводится к одной строке в sshd_config. Обрыв может происходить на стороне клиента, сервера, NAT-шлюза, домашнего роутера, VPN-туннеля, stateful firewall с коротким таймаутом, из-за path MTU blackhole или слишком агрессивной очистки неактивных TCP-сессий промежуточным устройством.

Хорошая новость в том, что такие проблемы обычно диагностируются системно. Если не прыгать сразу к случайным «магическим» настройкам, а идти по слоям — SSH, TCP, firewall, conntrack, MTU, — причину чаще всего удаётся локализовать довольно быстро.

Ниже разберём, что означают Broken pipe и Connection reset by peer, чем отличаются ClientAliveInterval и ServerAliveInterval, когда реально нужен keepalive, как проверить гипотезу про MTU/MSS, где смотреть nftables и conntrack, и как использовать tcpdump так, чтобы он действительно помог.

Что именно означают Broken pipe и Connection reset by peer

Хотя с точки зрения пользователя обе ошибки выглядят как «SSH оборвался», технически это разные сценарии.

Broken pipe чаще появляется тогда, когда SSH-клиент пытается отправить данные в соединение, которое уже фактически умерло. Например, промежуточный NAT удалил запись о TCP-сессии, сервер стал недоступен, туннель завис, а клиент узнаёт об этом только в момент следующей передачи.

Connection reset by peer обычно указывает на TCP RST. То есть соединение было сброшено другой стороной или устройством по пути. Это может быть сам сервер, локальный firewall, NAT, балансировщик или иное сетевое устройство, которое разрывает поток жёстко.

Отсюда первый важный вывод: не стоит лечить обе ошибки одной и той же настройкой. ServerAliveInterval помогает далеко не всегда. Если проблема в MTU, packet loss или state timeout на firewall, keepalive только сделает симптом менее заметным, но не устранит первопричину.

Если SSH рвётся строго после простоя, сначала проверяйте keepalive и таймауты stateful-устройств. Если обрыв происходит под нагрузкой, при scp, rsync или выводе большого объёма данных, в первую очередь смотрите MTU/MSS, packet loss и промежуточные firewall/NAT.

Сначала воспроизведите проблему в режиме подробной отладки

Первое, что стоит сделать, — получить максимум диагностических данных с клиентской стороны. Для теста запускайте SSH с тройным -v.

ssh -vvv user@server

Если проблема проявляется не при входе, а спустя несколько минут, оставьте сессию открытой и дождитесь обрыва. В выводе ищите строки, которые показывают момент потери соединения.

  • debug1 client_input_channel_req — это не ошибка сама по себе, а обычное отладочное сообщение;
  • client_loop: send disconnect: Broken pipe;
  • Connection reset by peer;
  • packet_write_wait: Connection to ... Broken pipe;
  • kex_exchange_identification — если обрыв случается очень рано.

Полезно сразу проверить, воспроизводится ли проблема без интерактивной оболочки:

ssh -vvv user@server true
ssh -vvv user@server 'uname -a'
ssh -vvv -o ServerAliveInterval=15 -o ServerAliveCountMax=3 user@server

Если короткая команда почти всегда отрабатывает, а интерактивная сессия рвётся только при простое, это сильный признак idle timeout где-то по пути.

Если же даже короткие подключения иногда заканчиваются Connection reset by peer, дальше уже нужно смотреть серверные логи, firewall и сетевой тракт.

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

Проверяем серверные логи OpenSSH в Debian и Ubuntu

На Debian и Ubuntu журнал sshd удобнее всего смотреть через journalctl. В старых конфигурациях часть сообщений может попадать и в классические файлы логов, но начинать лучше с systemd-журнала.

sudo journalctl -u ssh -n 100 --no-pager
sudo journalctl -u ssh --since '1 hour ago' --no-pager
sudo journalctl -f -u ssh

На этих системах unit часто называется именно ssh, а не sshd — это нормально.

При анализе обращайте внимание на несколько вещей:

  • есть ли запись о нормальном логине и последующем disconnect;
  • пишет ли сервер что-то про timeout, reset, PAM, session close;
  • нет ли рестартов службы ssh в момент обрыва;
  • не совпадает ли проблема по времени с перезагрузкой сети или обновлением правил firewall.

Если клиент пишет Connection reset by peer, а в журнале сервера вообще нет соответствующего завершения сессии, это сильный признак того, что соединение теряется не в самом sshd, а между клиентом и сервером.

Если сервер работает за собственным firewall на Linux, дополнительно пригодится материал про отладку правил iptables и nftables: часто проблема оказывается не в SSH, а в логике обработки состояний соединений.

Подробный вывод SSH-клиента в режиме отладки

Когда реально помогают ServerAliveInterval и ClientAliveInterval

Здесь часто возникает путаница: параметры похожи по названию, но работают в разные стороны.

ServerAliveInterval на клиенте

Это настройка клиента OpenSSH. Она заставляет клиент периодически отправлять служебные сообщения по уже открытому SSH-каналу. Если по пути есть NAT или firewall, который убивает неактивные соединения, такой трафик может поддерживать сессию живой.

Host *
    ServerAliveInterval 15
    ServerAliveCountMax 3

Обычно эти параметры добавляют в ~/.ssh/config или в /etc/ssh/ssh_config, если поведение нужно для всех пользователей системы.

Логика простая: клиент шлёт keepalive каждые 15 секунд, а после трёх неудачных попыток считает соединение мёртвым. Это не чинит сеть, но помогает избежать зависших сессий.

ClientAliveInterval на сервере

Это уже параметр сервера в /etc/ssh/sshd_config. Он заставляет сервер посылать проверочные сообщения клиенту. Обычно он полезен для очистки умерших сессий и в некоторых сценариях с серверным idle timeout.

ClientAliveInterval 30
ClientAliveCountMax 3

После изменения конфигурации обязательно проверяйте синтаксис, и только потом делайте reload:

sudo sshd -t
sudo systemctl reload ssh

Если это удалённый production-сервер, держите вторую активную SSH-сессию, чтобы не потерять доступ из-за ошибки в конфиге.

ServerAliveInterval чаще помогает, когда рвётся клиентская сессия из-за простоя. ClientAliveInterval полезен для серверного контроля зависших соединений, но не заменяет клиентский keepalive.

И важное ограничение: если соединение рушится из-за MTU blackhole, packet loss, RST от firewall или рестарта интерфейса, keepalive проблему не исправит. Он только поможет точнее понять, что причина именно в idle timeout.

Типовой сценарий: SSH рвётся через 5–15 минут простоя

Это очень частая история. Администратор входит на сервер, ничего не делает несколько минут, возвращается в терминал — а там зависший prompt или после первой же команды появляется Broken pipe.

Чаще всего в таком случае виноваты домашний роутер, офисный firewall, CGNAT, VPN-туннель, облачный firewall или мобильная сеть с агрессивными таймаутами TCP state.

  1. Проверьте, исчезает ли проблема с ServerAliveInterval 15.
  2. Сравните поведение из другой сети: например, через мобильный hotspot.
  3. Если используется VPN, протестируйте соединение без него.
  4. Если сервер за NAT или firewall, проверьте таймауты established-состояний.
  5. Убедитесь, что на сервере нет политики, закрывающей idle-сессии.

Если включение ServerAliveInterval сразу стабилизировало работу, это почти прямое указание на idle timeout вне OpenSSH.

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

Если обрывы происходят во время передачи данных: MTU, MSS и PMTUD

Отдельный класс проблем — когда SSH login проходит нормально, оболочка открывается, но при выполнении тяжёлой команды, вставке большого буфера, работе через туннель, scp или rsync сессия зависает или падает. Тогда стоит думать про MTU/MSS и path MTU discovery.

Типичный симптом: мелкие пакеты проходят, а более крупные начинают теряться. Из-за этого SSH выглядит как «иногда живой, иногда мёртвый». Особенно часто это проявляется поверх VPN, PPPoE, GRE, VXLAN, WireGuard, IPsec и различных облачных оверлеев.

ip link show
ip addr show
ip route get SERVER_IP

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

Ещё один полезный приём — MSS clamping на маршрутизаторе или firewall, если вы контролируете этот узел. Но сначала лучше подтвердить диагноз дампом трафика, а не лечить вслепую.

Если соединение идёт через туннель, пригодится и материал про настройку site-to-site WireGuard на VDS: в таких схемах проблемы MTU и MSS встречаются особенно часто.

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

Как использовать tcpdump для SSH-обрывов

tcpdump — один из самых полезных инструментов в этой задаче. Он позволяет увидеть, кто первым закрывает соединение, есть ли RST, наблюдаются ли ретрансляции, и пропадают ли ответы одной из сторон.

На сервере для порта 22 достаточно начать с такого захвата:

sudo tcpdump -ni any tcp port 22

Если SSH слушает на нестандартном порту, подставьте его явно.

В выводе стоит искать:

  • TCP RST от сервера или промежуточного узла;
  • множественные retransmission;
  • полное исчезновение ответного трафика после определённого момента;
  • асимметрию, когда клиент что-то шлёт, а сервер не видит, или наоборот.

Для более подробного анализа удобнее писать дамп в файл:

sudo tcpdump -ni any -w /tmp/ssh-drop.pcap tcp port 22

Идеальный вариант — снять дамп одновременно и на клиенте, и на сервере. Тогда сразу видно, где именно исчезают пакеты: до сервера, на сервере или уже на обратном пути.

  • Если сервер отправляет ответы, а клиент их не получает — проблема в сети по пути назад.
  • Если сервер сам шлёт RST — смотрим локальный firewall, sshd, policy routing, conntrack.
  • Если после крупного сегмента начинаются повторы и затем тишина — очень вероятен сценарий с MTU или PMTUD.

Анализ сетевого дампа при обрыве SSH-соединения

Проверяем nftables и conntrack

На Debian и Ubuntu с современным сетевым стеком нередко встречается сценарий, в котором ломается не сам SSH как сервис, а stateful firewall теряет состояние соединения или очищает его слишком рано.

Сначала посмотрите активные правила:

sudo nft list ruleset

Ищите цепочки с политиками drop или reject, stateful-фильтрацию и любые нестандартные таймауты, если они заданы явно.

Дальше имеет смысл проверить сам conntrack. Если таблица состояний переполнена или записи вытесняются слишком агрессивно, длительные SSH-сессии могут рваться без заметных ошибок в sshd.

sudo conntrack -S
sudo sysctl net.netfilter.nf_conntrack_count
sudo sysctl net.netfilter.nf_conntrack_max
sudo sysctl net.netfilter.nf_conntrack_tcp_timeout_established

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

Если проблема появилась после внедрения новых правил, временное упрощение набора правил часто очень быстро подтверждает гипотезу. В этом случае полезно сравнить текущую политику с типовыми сценариями маршрутизации и NAT, например при работе с несколькими адресами и SNAT через nftables с несколькими IP и управлением SNAT.

Проверка, не ломает ли SSH сам сервер или PAM-обвязка

Иногда кажется, что виновата сеть, но сессию на самом деле закрывает локальная логика сервера: PAM-модули, ограничение по времени, нестандартный ForceCommand, wrapper для shell, timeout в служебной обвязке или рестарт сети.

Проверьте следующие точки:

  • нет ли в /etc/ssh/sshd_config директив ClientAliveInterval, ClientAliveCountMax, ForceCommand и блоков Match с частными правилами;
  • не включены ли PAM-модули, ограничивающие длительность сессии;
  • не рестартуется ли служба ssh;
  • не меняется ли IP, маршрут или активный интерфейс;
  • не перезагружаются ли правила firewall в момент обрыва.

Если обрываются только интерактивные shell-сессии, а одноразовые команды работают стабильно, отдельно проверьте пользовательские startup-файлы: .bashrc, .profile, вызовы внешних утилит, DNS-запросы и обращения к недоступным ресурсам.

Минимальный runbook диагностики

Если нужно быстро локализовать проблему без лишней теории, придерживайтесь такого порядка:

  1. Подключитесь с ssh -vvv и зафиксируйте момент обрыва.
  2. Параллельно смотрите journalctl -f -u ssh на сервере.
  3. Проверьте, помогает ли ServerAliveInterval 15.
  4. Сравните поведение из другой сети или без VPN.
  5. Снимите tcpdump на сервере во время воспроизведения.
  6. Проверьте nft list ruleset и состояние conntrack.
  7. Если обрывы под нагрузкой — проверьте гипотезу MTU/MSS.
  8. Убедитесь, что сам sshd не рестартуется и не закрывает сессию по политике.

Такой порядок почти всегда выводит либо на idle timeout, либо на firewall/state, либо на MTU/PMTUD.

Практичные настройки, которые чаще всего помогают

Если задача — сначала стабилизировать SSH-сессию, а уже потом докопаться до первопричины, начните с умеренных keepalive-параметров на клиенте:

Host *
    ServerAliveInterval 15
    ServerAliveCountMax 3
    TCPKeepAlive yes

На сервере настройки имеет смысл менять только если это действительно нужно:

ClientAliveInterval 30
ClientAliveCountMax 3

И обязательно проверяйте сетевую инфраструктуру, если:

  • сессия рвётся строго по таймеру;
  • обрыв возникает только через VPN;
  • проблема есть на одном провайдере и исчезает на другом;
  • в tcpdump видны RST или зависания после крупных сегментов.

Если вы часто администрируете серверы через нестабильные сети, полезно сочетать это с мультиплексором терминала вроде tmux. Он не чинит SSH, но спасает рабочую сессию, когда транспорт уже подвёл.

Главная мысль простая: Broken pipe и Connection reset by peer — это не диагноз, а симптом. На Debian и Ubuntu он чаще всего сводится к одной из трёх групп причин: idle timeout, stateful firewall или проблемы MTU/PMTUD. Если идти по этим веткам методично, реальная причина обычно находится довольно быстро.

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

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

Debian/Ubuntu: как размонтировать busy mount — lsof, fuser, lazy umount и bind mount OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как размонтировать busy mount — lsof, fuser, lazy umount и bind mount

Если umount в Debian или Ubuntu отвечает target is busy или device or resource busy, причина обычно в процессе, текущем каталоге, ...
Debian/Ubuntu: как исправить APT Hash Sum mismatch и File has unexpected size OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить APT Hash Sum mismatch и File has unexpected size

Ошибки APT Hash Sum mismatch, File has unexpected size и packages.gz mismatch обычно связаны не с поломкой apt, а с рассинхроном з ...
Debian/Ubuntu: как исправить apt update с ошибкой Release file changed OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить apt update с ошибкой Release file changed

Если при apt update появляется Release file changed, repository changed its suite или codename, это не всегда сбой. Разберём, как ...