Клон из офиса работает, тот же клон через точку доступа телефона работает, а тот же клон из гостиничной сети висит, пока не включат VPN. Рукопожатие SSH завершается, и сеанс замолкает на первой настоящей передаче. Одна строка, добавленная в конфигурацию клиента, лечит git и ssh вместе. Когда одна настройка клиента исправляет несколько инструментов сразу, неисправность в том, что клиент отправляет, а не в канале, по которому он это отправляет.

Читайте симптом как разницу в маршрутизации

Туннель, который лечит проблему, редко бывает ремонтом. Он меняет маршрут, оператора и промежуточные устройства, а ноутбук продолжает создавать те же самые пакеты. Если один маршрут неправильно обрабатывает заголовок, а другой пропускает его без изменений, разница в политике промежуточного устройства, а не в клиенте. Здесь туннель — свидетель, а не решение.

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

Клиент ставит байт QoS на каждый сокет SSH

Каждое соединение OpenSSH начиная с 7.8 несёт в заголовке IP значение, которое маршрутизаторы могут использовать для приоритизации трафика. Терминальным сеансам достаётся одно значение, а массовым копиям другое, по теории, что человек, набирающий текст, заслуживает лучшего обращения, чем передача файла. Большинство сетей полностью игнорируют эту подсказку, поэтому она годами остаётся незамеченной. Меньшинство драйверов Wi-Fi, мобильных операторов и VPN-концентраторов реагирует на неё, и некоторые реагируют плохо.

Когда это значение переписывают или отбрасывают посреди потока, соединение не разрывается, оно перестаёт продвигаться. Повторы растут, окно рушится, а приложение ничего не сообщает, потому что ничего не вернуло ошибку. Именно это молчание заставляет людей описывать симптом как зависание, а не как сбой.

Сначала подтвердите версию клиента командой ssh -V. Любая версия начиная с 7.8 несёт такое поведение по умолчанию.

Три команды, которые отделяют это от MTU и DNS

Две похожие причины стоит исключить, прежде чем править любой файл конфигурации. Неисправность MTU пропускает мелкие обмены и замирает на первом крупном пакете, а неисправность имён вообще не создаёт сеанс.

ssh -o IPQoS=none -v [email protected]
ssh -G [email protected] | grep -i ipqos
sudo tcpdump -ni any -vv "tcp port 22"

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

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

Поместите исключение в один файл, по одному хосту за раз

Исключение должно стоять рядом с хостом, к которому относится, с комментарием, объясняющим, зачем оно существует.

Host gitlab.example.internal
    IPQoS none
    # direct route rewrites the marking; the tunnel route passes it

Область действия важнее самого значения. Запись с подстановочным знаком отключает поведение везде, выбрасывает подсказку, которая помогает в благополучных сетях, и не оставляет никому возможности сказать, когда она появилась. Запись для одного хоста читаема, обратима и легко удаляется после починки сети. Используйте пользовательский файл для личного обхода и управляемый файл, когда то же исключение нужно целому парку машин.

Чётко скажите, что исключение не покрывает. Оно относится к SSH, поэтому удалённый репозиторий HTTPS, зеркало пакетов и браузер остаются вне его, и сбой любого из них требует собственного доказательства. В цепочке через бастион каждый переход использует конфигурацию клиента, и застревающий переход — тот, который стоит ограничить.

Замкните круг с владельцем сети

Передайте находку как четыре факта: версия клиента, проверенный маршрут, используемый клиент VPN и какое направление несло метку. Этих четырёх достаточно владельцу сети, чтобы воспроизвести обращение и решить, намеренное ли оно.

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

Изменение на клиенте — это временное решение со сроком годности. Запишите этот срок в комментарий.

Похожие статьи