Вы только что подняли свежий Linux VPS — или на часах 2 ночи, а мониторинг кричит: SSH недоступен. Терминал выдаёт ssh: connect to host … port 22: Connection refused, и пульс учащается. Хуже того: нет VNC, нет облачной консоли под рукой — только мигающий курсор.
Такое мы видим несколько раз в месяц. Иногда джуниор правит sshd_config и забывает сделать reload. Иногда security group пропускает 80 и 443, но не 22. Иногда fail2ban тихо банит IP вашего домашнего провайдера после серии неудачных входов. Хорошая новость: Connection refused обычно диагностируется — без мистики. Этот гайд превращает пять самых частых путей разбора из продакшена в чеклист. Сначала читайте ошибку, потом идите слой за слоем. В большинстве случаев корень находится за двадцать минут.
Одно допущение: у вас есть запасной способ зайти — облачная VNC, serial-консоль или другая машина в том же VPC. Если вы полностью отрезаны, переходите к разделу Когда вы полностью заблокированы.
Перед разбором: три «не подключается» — не одно и то же
Многие смешивают Connection refused, Connection timed out и Permission denied — и час гоняются не за той проблемой. По официальной документации OpenSSH каждое сообщение указывает на свой уровень стека:
| Ключевое слово | Обычно означает | Проверить в первую очередь |
|---|---|---|
Connection refused |
TCP дошёл до хоста, но на порту никто не слушает — или локальный файрвол ответил REJECT | Работает ли sshd? Верный порт? ufw/iptables на сервере? |
Connection timed out |
Пакеты теряются по пути (маршрутизация, облачная security group, upstream-файрвол) | Security group, верный публичный IP, ICMP/проверка порта |
Permission denied |
SSH-handshake прошёл, но аутентификация провалилась (ключи, пароль, политика пользователей) | Права на ключи, AllowUsers, бан fail2ban вашего IP |
-v для деталейssh -v user@host (при необходимости до -vvv). Смотрите, зависает ли на «Connecting» или «Authenticating». Первое — сеть или порт; второе — ключи и настройки пользователя.
Правильное различие экономит время. Connection refused значит, пакет дошёл — проблема на стороне сервера или у его сетевой границы. Timed out — что-то по пути проглотило трафик; крутить sshd_config на недоступной машине бессмысленно, пока не почините маршрут. Permission denied почти всегда — учётные данные, политика аккаунта или бан IP после уже установленной TCP-сессии.
В команде вставляйте в канал инцидента точную строку ошибки. «SSH сломался» — двенадцать догадок; «Connection refused на порту 2222 с офисного IP» — сразу сужает поиск.
Метод 1: Проверить IP, DNS и доступность порта (сетевой слой)
Прежде чем винить sshd, докажите, что дорога открыта. На свежих VPS чаще всего: опечатка в IP, DNS ещё не разошёлся, или sshd слушает нестандартный порт, а вы стучитесь на 22.
Выполните на локальной машине по порядку:
# 1. Confirm resolved IP is correct dig +short your.domain.com ping -c 3 your.server.ip # 2. Probe whether SSH port is open (replace 22 with your actual port) nc -zv your.server.ip 22 # or telnet your.server.ip 22 # 3. Connect with explicit port (avoids ~/.ssh/config surprises) ssh -p 22 -i ~/.ssh/id_ed25519 user@your.server.ip
Если nc возвращает Connection refused, пакеты доходят до сервера — дело в локальном сервисе или локальном файрволе. Переходите к методу 2. При timed out или зависании приоритет — security group / Network ACL облака: разрешает ли inbound TCP на 22 (или ваш кастомный порт)? Источник 0.0.0.0/0 или по ошибке только приватная подсеть?
Проверьте и свою сеть. Корпоративные VPN, университетские сети и некоторые провайдеры фильтруют порт 22. Временно перенести sshd на 443 или 2222 для сравнения — классика: если альтернативный порт работает, причина в фильтрации на пути, а не на сервере.
При управлении несколькими хостами держите шпаргалку с публичными IP и SSH-портами. Ошибки копипаста из старых тикетов удивительно часты, особенно после миграции у провайдера или смены elastic IP.
При доступе по hostname помните про TTL и кэш. DNS могли обновить пять минут назад, а ноутбук или резолвер всё ещё смотрит на старый адрес. dig +short на вашей машине — истина, а не панель регистратора.
Метод 2: Проверить, запущен ли сервис sshd
Одна из самых частых причин Connection refused: sshd так и не стартовал или имя сервиса сменилось после обновления ОС. На Ubuntu/Debian unit обычно ssh; на RHEL/CentOS/Rocky — sshd. Не угадывайте — проверяйте командами.
После входа через VNC или облачную консоль:
# Debian/Ubuntu sudo systemctl status ssh sudo systemctl start ssh sudo systemctl enable ssh # RHEL/CentOS/Rocky sudo systemctl status sshd sudo systemctl start sshd # Is it listening? Which address and port? sudo ss -tlnp | grep ssh # Expect 0.0.0.0:22 or [::]:22 # Config syntax check (run after every edit) sudo sshd -t sudo systemctl reload ssh # or sshd
Если systemctl status показывает failed, сразу смотрите логи: sudo journalctl -u ssh -n 50 --no-pager. Типичные фатальные ошибки: опечатки в конфиге, отсутствующий HostKey, ListenAddress на неверном интерфейсе. После правок всегда sshd -t перед reload — слишком часто reload вслепую, sshd не поднимается, и вы сами себя запираете.
На свежеустановленных системах убедитесь, что openssh-server установлен: sudo apt install openssh-server (Debian-семейство) или sudo dnf install openssh-server (RHEL-семейство). Минимальные облачные образы иногда идут без SSH-сервера.
Полный диск тоже мешает sshd стартовать или принимать сессии. Быстрый df -h с консоли стоит десяти минут удалённых догадок. Если MaxStartups слишком ужали во время brute-force, под нагрузкой легитимные клиенты видят refused — ищите «drop connection» в journalctl.
Когда после частичного апгрейда сосуществуют несколько версий sshd, which sshd и путь ExecStart unit должны совпадать. Расхождение бинарников и путей конфига даёт загадочные «вчера же работало».
Метод 3: Проверить файрвол хоста и облачные security groups
sshd работает, ss показывает listener, а снаружи всё ещё refused — следующий подозреваемый: правила файрвола дропают или отклоняют трафик. На Linux обычно два слоя: облачная security group (снаружи NIC) и ufw/iptables/nftables в ОС (внутри). Оба должны пропускать SSH-порт.
Типичные проверки на системе:
sudo ufw status verbose
sudo ufw allow 22/tcp
sudo ufw allow 2222/tcp # if you changed the port
sudo ufw reload
# firewalld (CentOS, etc.)
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
# Inspect nftables/iptables directly
sudo iptables -L INPUT -n -v
Облачные security groups меняются в консоли провайдера, когда SSH лежит — волшебного CLI с ноутбука нет. Три детали: протокол TCP, диапазон портов включает SSH, source CIDR не сужен по ошибке до одного внутреннего хоста. На тестах временно 0.0.0.0/0 — нормально; после проверки сузьте до офисного egress IP.
Если на VPS крутятся Docker или Kubernetes, правила iptables могут переписываться автоматически. Выполните sudo iptables-save | grep 22 и ищите DROP/REJECT перед ACCEPT. Про минимальную экспозицию и компромисс SSH/HTTPS см. наш FAQ по минимальной экспозиции Linux: файрвол SSH/HTTPS.
IPv6 легко упустить: поправили IPv4 в security group, а ssh user@host предпочитает AAAA и упирается в заблокированный v6. При странном поведении тестируйте ssh -4 и ssh -6.
Зафиксируйте, какой слой вас заблокировал. Команды, которые чинят только ufw и забывают security group, часто повторяют тот же простой при следующем «усилении безопасности».
Метод 4: Проверить порт и настройки sshd_config
Многие админы уводят SSH с 22-го порта или ставят ListenAddress только на внутренний интерфейс. Клиенты на 22 увидят refused. Конфиг сервера — /etc/ssh/sshd_config. Ключевые директивы (полный справочник в мануале sshd_config):
Port 2222
# ListenAddress 0.0.0.0 # default: all interfaces; 127.0.0.1 blocks external access
PermitRootLogin prohibit-password
PasswordAuthentication no
AllowUsers deploy admin
Безопасная смена порта: убедиться, что новый порт слушает, обновить файрвол, потом закрыть старый. Не одним рывком — «перевести 22 на 2222 и сразу закрыть 22 в security group» часто отрезает доступ до проверки нового порта.
На RHEL с SELinux после смены порта выполните sudo semanage port -a -t ssh_port_t -p tcp 2222, иначе sshd может не забиндиться. AppArmor на Ubuntu тоже ограничивает пути — в логах будет явно.
На клиенте перепроверьте ~/.ssh/config на неверный Port или HostName. С алиасами Host prod копирование команды без -p — частая ошибка.
AllowUsers и DenyUsers могут сбивать с толку: TCP соединился, sshd ответил, потом провал auth — или в некоторых конфигурациях ранний обрыв. После ужесточения политики сравните локальное имя пользователя со списком на сервере.
Jump host и ProxyJump добавляют переменную. Refused на последнем прыжке может означать: бастион ок, а порт или security group цели — нет. Тестируйте каждый сегмент через nc и ssh -J.
Метод 5: Проверить блокировку IP (fail2ban / hosts.deny)
Если вместо refused видите Permission denied, но уверены, что ключ верный, подозревайте бан IP. fail2ban добавляет правила в iptables или hosts.deny после повторных неудачных паролей или странных handshake. Wiki fail2ban подробно описывает механику jail.
На сервере проверьте:
# fail2ban status sudo fail2ban-client status sshd sudo fail2ban-client set sshd unbanip YOUR.CLIENT.IP # Classic hosts-based bans grep -v '^#' /etc/hosts.deny grep -v '^#' /etc/hosts.allow # Cloud "ops lock" or DDoS mitigation # → check provider console for security alerts or temporary IP blocks
Забанить себя — обычное дело: скрипт сбоит, десятки failed login за секунды, fail2ban отправляет офисный egress IP в jail. После разбана добавьте admin IP в ignoreip или отключите парольную auth и оставьте ключи — меньше ложных срабатываний.
Если у вас Jenkins, GitLab Runner или похожие агенты с SSH-обратным подключением к VPS, сбои регистрации иногда выглядят как SSH-странности. В гибридной топологии путь controller–agent стоит нарисовать отдельно — см. Гибридная топология Jenkins: VPS-контроллер + облачный Mac JNLP enterprise pool.
Cloudflare и другие прокси не терминируют SSH на 22-м порту как HTTP. Если вы повесили не тот сервис или перепутали DNS бастиона и приложения — отступите и разберитесь, какой hostname вообще должен открывать SSH.
Полная блокировка: используйте аварийный путь
Если все пять методов оставили вас снаружи, попробуйте по порядку:
- Облачная VNC / serial-консоль — не зависит от SSH; войдите и поправьте конфиг
- Откат снапшота — если снимок был до изменений, это лучше бессонной ночи
- Single-user mode / rescue-образ — смонтируйте диск, chroot, отредактируйте
sshd_config - Тикет в поддержку — некоторые провайдеры временно открывают порт или снимают блок
Урок простой: никогда не делайте изменения «которые могут оборвать сессию» в единственном SSH-подключении. Держите второй терминал, используйте tmux — правки файрвола и sshd особенно рискованны.
После восстановления напишите трёхстрочный постмортем: что меняли, какой сигнал пропустили, какой запасной путь спас. Следующий дежурный скажет спасибо.
Чеклист профилактики: меньше паники в следующий раз
Потратьте десять минут после инцидента — дешевле, чем снова метаться:
- Вход по ключу, пароли отключены;
~/.ssh/authorized_keysс правами 600 - Нестандартный SSH-порт — ок, но меняйте security group и sshd_config вместе
- Настройте fail2ban
ignoreipдля доверенных сетей, чтобы не банить свою команду sshd -tперед reload; снапшот перед рискованными правками- Мониторинг не только «порт SSH 22 up/down» — agent или health check по приватной сети
Рассмотрите выделенный бастион со стабильным egress IP и жёсткими security groups на прод-нодах. IP вашего ноутбука из кофейни не должен быть единственным ключом к королевству.
Стабильный jump host: меньше паники, когда что-то ломается
Управляя несколькими Linux VPS, многие команды держат бастион с фиксированным egress IP для SSH-hopping — на проде security groups пускают только бастион, с ноутбука заходите цепочкой по ключам. Mac mini хорошо подходит: нативный Unix, Terminal и OpenSSH из коробки; чип M4 в простое около 4 Вт — достаточно тихо для круглосуточного релея, экономичнее и тише, чем ещё одна x86-коробка под столом.
Windows-машина в том же ценовом диапазоне в постоянной работе потребляет больше и шумит вентиляторами; macOS славится долгими аптаймами, FileVault и Gatekeeper делают хранение приватных ключей спокойнее. Если на том же узле нужны Xcode или Docker для релизов, облачный Mac mini объединяет бастион + сборку на одной ноде и сокращает переключения контекста.
Если вы проектируете надёжную удалённую ops-инфраструктуру, облачный Mac mini M4 от VPSSPark — практичный выбор как энергоэффективный jump host и dev-нода — смотреть тарифы и цены , чтобы разбор SSH в 2 часа ночи не оставался одиночным представлением.