Ситуация знакомая: вы подключаетесь по ssh, а в ответ — Connection timed out или «port 22 timed out». В отличие от Connection refused, таймаут почти всегда означает, что TCP SYN не получает ответа: пакет где-то теряется, дропается файрволом или уходит не туда по маршрутизации.
Ниже — практичный чеклист для админа/DevOps: от самых частых причин (cloud firewall и локальный firewall) до «подлых» (policy routing, rp_filter, fail2ban, прослушивание не на том адресе). Команды рассчитаны на Debian/Ubuntu/RHEL-подобные системы; где-то потребуется sudo.
Быстрая развилка: что именно происходит
Перед тем как лезть в конфиги, зафиксируйте симптомы — это экономит время:
- Таймаут (
Connection timed out) — чаще всего фильтрация/маршрутизация/ACL. - Отказ (
Connection refused) — порт закрыт или сервис не слушает. - Сразу разрыв — иногда активный reject в firewall, TCP RST от сервиса, либо промежуточное устройство.
Важно: таймаут на 22 порту — это не «ошибка SSH». Это TCP-уровень: не дошли пакеты или не вернулся ответ.
Шаг 1. Проверяем с клиентской стороны: DNS, IP и базовый коннект
Начните с машины, с которой подключаетесь: убедитесь, что вы идёте на правильный адрес и понимаете, какой стек (IPv4/IPv6) используется.
Проверяем, куда резолвится имя и какой IP вы используете
getent ahosts your-hostname
Если видите и IPv6, и IPv4 — проверьте оба. Частая история: клиент первым пробует IPv6, а на сервере SSH слушает только IPv4 (или наоборот).
Смотрим отладку SSH и таймаут подключения
ssh -vvv -o ConnectTimeout=5 user@server
В выводе -vvv будет видно, на какой IP пытается подключиться клиент и на каком этапе всё «зависает».
Быстрый тест TCP-порта без SSH
nc -vz -w 3 server-ip 22
Этот тест не заменяет диагностику на сервере, но помогает быстро понять, что именно «не сходится» на TCP-уровне.
Проверяем маршрут (актуально при VPN/нескольких интерфейсах)
ip route get server-ip
Если у вас несколько uplink, активный VPN или split-tunnel, маршрут может уходить не туда. Для общей картины пригодится трассировка:
traceroute -n server-ip

Шаг 2. Cloud firewall и правила провайдера
Если у вас есть «облачный» firewall/группы безопасности, он может молча дропать вход на 22. В таком случае на сервере вы не увидите входящих SYN в tcpdump — потому что пакеты даже не доходят.
Проверьте на стороне панели/провайдера:
- Разрешён ли входящий TCP 22 на нужный публичный IP.
- Нет ли allowlist по источникам (например, разрешён доступ только с офисного IP).
- Нет ли правила «deny all» выше нужного allow.
- Если меняли IP/переносили инстанс — не остались ли правила привязаны к старому адресу/инстансу.
Отдельный кейс: если доступ по SSH разрешён только через VPN/приватную сеть, то с публичного интернета таймаут будет «нормальным» поведением.
Шаг 3. На сервере: sshd запущен и слушает нужный адрес
При таймауте по сети вам часто нужен альтернативный доступ: провайдерская консоль, out-of-band, rescue mode. Дальше команды выполняйте на сервере.
Проверяем, что sshd работает
systemctl status ssh
systemctl status sshd
В зависимости от дистрибутива юнит может называться ssh или sshd.
Проверяем, что порт действительно слушается
ss -lntp | grep ':22 '
Обратите внимание на Local Address:
0.0.0.0:22— слушает на всех IPv4.:::22— слушает на IPv6 (иногда это также означает dual-stack, но зависит от настроек).127.0.0.1:22— слушает только localhost; снаружи будет таймаут/отказ (по ситуации).192.0.2.10:22— слушает только на конкретном IP; если адрес сменился, порт для внешнего мира «пропал».
Если SSH у вас на другом порту, проверьте /etc/ssh/sshd_config параметр Port, провалидируйте конфиг и перезапустите сервис:
sshd -t
systemctl restart ssh
systemctl restart sshd
sshd -t полезен тем, что сразу покажет ошибку, если синтаксис конфига повреждён.
Шаг 4. Локальный firewall: nftables, iptables, firewalld, ufw
Таймаут на 22 порту очень часто вызван тем, что локальный firewall молча дропает вход. Задача — понять, кто именно управляет правилами, и найти, где вы теряете трафик.
nftables
nft list ruleset
Ищите таблицы inet и цепочки input. Типичный признак проблемы — политика drop и отсутствие allow для tcp dport 22 (или вашего кастомного порта).
nft list chain inet filter input
Минимум, который обычно должен быть в логике: разрешение ct state established,related, разрешение loopback и явный allow на SSH (иногда с ограничением по IP-источнику).
iptables (включая совместимость через iptables-nft)
iptables -S
iptables -L -n -v
Смотрите цепочку INPUT, политику по умолчанию и счётчики. Если растут счётчики на DROP/REJECT для tcp/22 или для вашего IP — вы нашли причину.
Если у вас Docker/контейнеры, правила могут быть «размазаны» по цепочкам (DOCKER-USER и т.д.). На эту тему полезно держать под рукой разбор: как Docker влияет на iptables/nftables и где теряется входящий трафик.
firewalld / ufw
systemctl status firewalld
firewall-cmd --state
firewall-cmd --list-all
ufw status verbose
Если ufw активен и нет правила allow для OpenSSH или 22/tcp, возможен и таймаут (drop), и отказ (reject) — зависит от политики.
Симптом «вход есть, ответа нет»: rp_filter и асимметричная маршрутизация
На серверах с несколькими интерфейсами, policy routing или несколькими шлюзами входящий пакет может прийти по одному интерфейсу, а ответ уйти по другому. Тогда клиент видит таймаут, хотя сервис живой.
Проверьте rp_filter:
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.conf.default.rp_filter
Значение 1 (strict) может ломать асимметрию. Если у вас осознанно сложная маршрутизация, часто используют 2 (loose), но менять это стоит только понимая схему и риски.
Шаг 5. Fail2ban: не забанил ли он ваш IP
fail2ban обычно блокирует брутфорс, но в реальной жизни админ легко ловит бан сам: ошибся ключом, прокси меняет IP, NAT выдал общий адрес, или вы тестировали авторизацию.
Проверяем статус и jail для SSH
fail2ban-client status
fail2ban-client status sshd
Если jail называется иначе (например, sshd-ddos), это будет видно в общем статусе.
Проверяем, есть ли ваш IP в бане, и разбаниваем
fail2ban-client get sshd banip
fail2ban-client set sshd unbanip 203.0.113.10
И обязательно посмотрите логи, почему сработало:
journalctl -u fail2ban --no-pager -n 200
journalctl -u ssh --no-pager -n 200
journalctl -u sshd --no-pager -n 200
Если тема fail2ban у вас «болит» регулярно, пригодится отдельный разбор про типовые ошибки и усиление защиты: как подружить fail2ban с логами и не забанить себя (и что делать с 2FA).

Шаг 6. «Живая» картина: ss и состояния TCP
Пока клиент пытается подключиться, на сервере можно увидеть полуоткрытые соединения. Это помогает отличить «пакеты не доходят» от «доходят, но ответ не возвращается».
SYN-RECV и ESTABLISHED на 22 порту
ss -ant state syn-recv sport = :22
ss -ant state established sport = :22
Интерпретация:
- Нет записей вообще — SYN не приходит (cloud firewall/маршрут/локальный drop до стека) или клиент стучится не туда.
- Много
SYN-RECV— сервер видит SYN, отвечает SYN-ACK, но ACK не возвращается (асимметрия, фильтр на обратном пути, проблемы маршрута, защитные системы). ESTABLISHEDесть, но SSH «висит» — это уже не таймаут порта; ищите проблемы в авторизации/интеграциях (PAM, reverse DNS, GSSAPI и т.д.).
Шаг 7. tcpdump: подтверждаем, где пропадают пакеты
tcpdump — самый честный инструмент: он отвечает на вопрос «пакеты приходят на интерфейс сервера или нет».
Снимаем трафик на 22 порту
tcpdump -ni any 'tcp port 22'
Дальше повторите попытку подключения с клиента и наблюдайте:
- Если вы не видите входящий SYN — проблема до сервера: cloud firewall, upstream ACL, неверный IP, неверная маршрутизация, блокировка у провайдера.
- Если видите SYN и SYN,ACK, но не видите финальный ACK — ответ не доходит до клиента (асимметрия/обратный фильтр/проблемы на обратном пути).
- Если видите полный 3-way handshake и дальше пакеты SSH — порт открыт; ищите причину «зависания» уже в настройках SSH и авторизации.
Точечный захват по конкретному клиентскому IP
tcpdump -ni any 'tcp port 22 and host 203.0.113.10'
Шаг 8. Маршрутизация на сервере: route, ip rule, policy routing
Если вы администрируете сервер с несколькими IP, несколькими uplink, VPN, GRE/WireGuard, балансировкой или нестандартной схемой — обязательно проверьте policy routing. Она часто становится причиной таймаутов на вход, особенно если ответы уходят не тем интерфейсом.
Проверяем маршруты
ip route
ip -6 route
Проверяем правила маршрутизации
ip rule
ip -6 rule
Если видите правила по fwmark, по from, отдельные таблицы — проверьте, что для входящего адреса (destination IP сервера) ответ действительно выбирает нужный gateway.
Проверяем маршрут «как ядро отправит ответ»
ip route get 203.0.113.10
Если сервер отвечает через другой интерфейс/шлюз, чем тот, через который клиент приходит, а где-то на пути есть фильтрация по состоянию, клиент получит Connection timed out.
Частые нестандартные причины таймаута на SSH
SSH слушает только на приватном интерфейсе
Проверьте адрес привязки в ss -lntp. В sshd_config также есть ListenAddress, который может ограничивать интерфейс.
Порт перенесли, а вы по привычке идёте на 22
Тогда на 22 будет таймаут или отказ (в зависимости от firewall), а реальный порт другой. Проверьте Port в конфиге и документацию окружения.
NAT/проброс порта настроен неверно
Если SSH доступен через проброс с другого адреса, убедитесь, что DNAT настроен корректно и локальный firewall пропускает трафик после трансляции.
Временная блокировка защитой от атак
При высокой нагрузке или волне брутфорса некоторые защиты могут временно «приземлять» новые TCP-сессии. Тогда на сервере могут быть SYN-RECV или вообще пусто (если фильтрация upstream).
Мини-ранбук: за 5 минут найти, где проблема
С клиента:
ssh -vvv -o ConnectTimeout=5 user@ip, убедиться в правильном IP (IPv4/IPv6).На сервере через консоль:
ss -lntp | grep ':22 '— слушает лиsshd.На сервере:
tcpdump -ni any 'tcp port 22'и повторить попытку подключения.Если SYN не видно — проверять cloud firewall и маршрут до сервера.
Если SYN видно — проверять nftables/iptables,
fail2ban,rp_filter,ip ruleи асимметрию.
Что полезно настроить заранее, чтобы не ловить таймауты
Профилактика экономит нервы, особенно на продакшн-серверах:
- Держите доступ через провайдерскую консоль/rescue на случай потери SSH.
- Перед изменением firewall держите вторую «страховочную» сессию активной, чтобы успеть откатить правила.
- В
fail2banиспользуйте разумные лимиты и учитывайте NAT (иначе можно забанить целый офис). - При сложной маршрутизации документируйте
ip rule/ip routeи осознанно выбирайте режимrp_filter.
Если вы часто меняете фильтрацию, лучше заранее предусмотреть аварийный доступ и сценарий отката: это дешевле, чем «спасать» сервер ночью.
Заключение
Ошибка ssh connection timed out на 22 порту почти всегда про сеть и фильтрацию: cloud firewall, nftables/iptables, fail2ban или маршрутизацию (route, ip rule). Самый быстрый путь к истине — связка ss (сервис слушает?) и tcpdump (пакеты вообще доходят?). Дальше уже точечно правите правила и маршруты, вместо того чтобы вслепую перезапускать sshd.
Если вы размещаете проекты у провайдера, где важно быстро поднимать доступ и изолировать сервисы по правилам, смотрите тарифы VDS или виртуального хостинга — пригодится и консольный доступ, и гибкость сетевых настроек.


