Как сменить порт SSH в Rocky Linux и AlmaLinux
Для смены порта SSH в RHEL-системах нужно настроить firewalld, добавить метку в SELinux через semanage и обновить sshd_config. Следуйте инструкции, чтобы не потерять доступ.
Почему для смены порта SSH здесь требуется три шага
Чтобы изменить порт SSH в Rocky Linux, AlmaLinux, CentOS Stream или Fedora, недостаточно одной правки. Три независимые системы определяют, будет ли работать соединение на новом порту. firewalld решает, дойдет ли пакет до машины. SELinux решает, разрешено ли sshd вообще использовать этот номер порта. sshd_config определяет, какой порт запрашивает демон. Пропустите шаг с SELinux — и демон откажется запускаться. Пропустите шаг с firewalld — и он запустится, будет слушать порт, но никто не сможет к нему подключиться.
В Ubuntu эта задача решается одной правкой и перезапуском, так как в Ubuntu используется AppArmor, а не SELinux, и нет профиля, ограничивающего порты для привязки sshd. Если там запущен ufw, достаточно добавить одно правило. В этом вся разница. В семействе RHEL по умолчанию установлены firewalld и SELinux в режиме enforcing, и обе системы контролируют номера портов.
Выполняйте работу в следующем порядке, чтобы текущая сессия оставалась активной на каждом этапе:
- Откройте новый порт в firewalld, оставив порт 22 открытым на текущий момент.
- Добавьте метку SELinux для нового порта с помощью
semanage. - Укажите порт в конфигурации sshd.
- Перезапустите
sshd, затем войдите через новый порт из второго терминала, прежде чем закрывать первый.
Перед началом работы найдите веб-консоль вашего провайдера (VNC или последовательный порт) и убедитесь, что можете войти через неё. Эта консоль — ваш единственный способ вернуться в систему, если что-то пойдет не так. Смена порта — одна из самых частых причин, по которой пользователи теряют доступ к только что арендованному серверу.
Сначала установите semanage
semanage — это инструмент для изменения настроек политики SELinux, и в минимальной установке Rocky Linux или AlmaLinux он отсутствует. Он находится в пакете policycoreutils-python-utils.
sudo dnf install -y policycoreutils-python-utilsЗапуск команды до установки этого пакета приводит к ошибке sudo: semanage: command not found, и именно на этом этапе многие пользователи решают, что SELinux не установлен, и пропускают этот шаг. SELinux установлен. Отсутствует только инструмент управления. Если синтаксис dnf для вас в новинку, эквиваленты команд dnf и apt помогут соотнести его с тем, что вы уже знаете.
Выберите порт и убедитесь, что он свободен
Подойдет любой свободный TCP-порт в диапазоне от 1024 до 65535. Перед тем как закрепить выбор, выполните две проверки:
sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222Первая команда показывает, слушает ли какой-либо процесс этот порт. Вторая проверяет, не назначен ли этот порт политикой SELinux для другого типа сервиса. Если порт свободен, обе команды не выведут ничего. Если порт уже занят политикой, команда semanage port -a на шаге 2 завершится с ошибкой ValueError: Port tcp/2222 already defined. В этом случае необходимо выбрать другой номер порта.
В данном руководстве в качестве примера используется порт 2222. Это первый порт, который сканеры проверяют после 22, поэтому на реальном сервере лучше выбрать менее очевидный вариант.
Шаг 1: откройте порт в firewalld
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports--permanent записывает правило в файл зоны на диске и не затрагивает работающий межсетевой экран. --reload загружает конфигурацию с диска в активный межсетевой экран. Если пропустить перезагрузку, правило будет создано, но не начнет действовать до следующего перезапуска firewalld. Это одна из самых частых причин, по которой вся процедура кажется нерабочей без видимых оснований.
Пока не трогайте запись сервиса ssh. Эта запись обеспечивает доступ к 22 порту и служит резервным вариантом на время тестирования.
Также проверьте панель управления вашего хостинг-провайдера. Многие провайдеры используют сетевой экран перед VPS, работающий вне операционной системы, поэтому порт, открытый в firewalld, может блокироваться на вышестоящем уровне. В руководстве по основам firewalld для VPS подробно описаны зоны и различие между runtime и permanent конфигурациями, если эта модель для вас нова.
Шаг 2: назначение метки порта для SELinux
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t-a добавляет новое назначение порта. -t ssh_port_t — это тип, который используется для SSH-портов. Вторая команда выводит список всех портов, которые теперь охватывает ssh_port_t, чтобы вы могли убедиться в добавлении номера перед внесением изменений в работу демона.
Почему SELinux вообще блокирует порт
SELinux (Security-Enhanced Linux) присваивает метку каждому объекту в системе, и номера TCP-портов являются такими же объектами, как и любые другие. SSH-демон работает в ограниченном домене под названием sshd_t. Политика позволяет sshd_t привязываться к TCP-портам с меткой ssh_port_t, и по умолчанию единственный порт с такой меткой — 22. Если вы попросите демон привязаться к порту 2222, ядро проверит метку, обнаружит, что политикой этому номеру назначен какой-то общий тип, и откажет в разрешении name_bind для сокета.
Именно поэтому данный сбой не выглядит как проблема с межсетевым экраном. Ядро отклоняет запрос еще до того, как создается слушающий сокет, поэтому sshd сообщает об ошибке и завершает работу. Проблема с межсетевым экраном — это зеркальная ситуация: демон запущен и работает исправно, а пакеты отбрасываются при попытке входа.
Команда getenforce показывает, в каком режиме находится система. В режиме Permissive отказ записывается в лог, но не применяется принудительно, поэтому смена порта кажется успешной, но перестает работать в тот день, когда кто-то выполнит setenforce 1 или система перезагрузится в режиме enforcing. В любом случае порту необходимо присвоить метку. В руководстве по основам SELinux для сервера подробно описаны режимы, контексты и булевы значения. Порты — не единственные объекты, с которыми возникают подобные сложности; та же политика запрещает контейнеру чтение примонтированного каталога хоста, пока этот путь не будет перемаркирован. Именно поэтому в инструкции по установке Docker на Rocky Linux или AlmaLinux присутствует шаг по настройке SELinux, о котором никогда не упоминают в руководствах для Ubuntu.
Шаг 3: настройка порта в конфигурации sshd
В Rocky Linux 9 и 10, AlmaLinux 9 и 10, а также в актуальных версиях Fedora файл /etc/ssh/sshd_config начинается со строки include, поэтому оптимальным местом для внесения изменений будет отдельный файл конфигурации (drop-in). В этом случае обновления пакетов не затронут ваши настройки.
grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -tЕсли grep не находит строку Include, что характерно для Rocky Linux 8 и других старых образов, добавьте Port 2222 непосредственно в /etc/ssh/sshd_config. sshd -t анализирует всю конфигурацию, включая дополнительные файлы, и сообщает о синтаксических ошибках. Исправьте все найденные ошибки перед перезапуском, так как при невозможности прочитать конфигурацию демон не запустится.
Port может встречаться несколько раз, и sshd будет ожидать соединений на всех указанных портах. Оставить Port 22 вместе с Port 2222 на первый день — это недорогой способ обезопасить себя, при условии, что вы не забудете удалить старый порт позже.
Запущен ли ваш sshd через socket-юнит?
Некоторые образы запускают SSH через механизм socket activation в systemd, а не как постоянно работающий сервис. В такой конфигурации systemd сам прослушивает сокет и передает соединения в sshd, поэтому строка Port в файле sshd_config полностью игнорируется. Проверьте это перед тем, как выполнять перезапуск:
systemctl is-enabled sshd.socketОтвет enabled означает, что порт задан в socket-юните, а не в sshd_config:
sudo systemctl edit sshd.socket[Socket]
ListenStream=
ListenStream=2222Необходимо указать пустую директиву ListenStream=. Значения параметров накапливаются из файлов-конфигураций (drop-ins), поэтому без предварительной очистки списка сокет продолжит прослушивать как порт 22, так и 2222. Примените изменения с помощью sudo systemctl daemon-reload, а затем выполните sudo systemctl restart sshd.socket. Если данный юнит отключен или отсутствует на вашем сервере, этот раздел к вам не относится.
Шаг 4: перезапуск и проверка из второго терминала
sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshdОставьте этот терминал открытым. Не завершайте сеанс. Откройте второй терминал на своей машине и подключитесь через новый порт:
ssh -p 2222 youruser@203.0.113.10Закрывайте первую сессию только после того, как второй вход в систему прошел успешно. Если подключиться не удалось, у вас остается активная оболочка, из которой можно отменить все изменения. Эта привычка — разница между пятиминутной настройкой и днем, потраченным на работу через консоль провайдера.
Блокировка файрволом или отказ SELinux? Как их различить
С вашего ноутбука эти две ошибки выглядят почти одинаково. На сервере они не имеют ничего общего.
- Если
systemctl status sshdпоказывает, что юнит не запущен, значит, демон не получил свой сокет. Это ошибка конфигурации или отказ SELinux. - Если юнит активен, а
ss -tlnpпоказывает, что sshd привязан к новому порту, значит, с демоном всё в порядке, а проблема находится на сетевом пути: firewalld, внешний файрвол провайдера или неверно указанный адрес и порт.
В случае с SELinux не гадайте, а прочитайте запись аудита:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerОтказ name_bind для класса tcp_socket указывает процесс в comm="sshd", номер порта в src= и метку, которая фактически назначена порту в tcontext=. Последнее поле — это и есть ответ. Любое значение, отличное от ssh_port_t, означает, что шаг 2 не был применён к используемому вами порту; обычно это опечатка в номере или неверный протокол. Установите setroubleshoot-server, если хотите, чтобы sealert переводил запись в понятное предложение.
Сообщение, которое сам sshd записывает, когда ядро запрещает привязку, выглядит так:
error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.Permission denied на порту выше 1024, где для привязки не требуются привилегии root, является признаком SELinux. Address already in use в той же строке указывает на другую ошибку: порт занят другим процессом. Со стороны клиента разница между connection refused и connection timed out позволяет разделить два сетевых случая, так как отказ означает, что пакет достиг хоста, но на порту никто не слушал, а таймаут означает, что ответа не поступило вовсе.
Закрытие порта 22 и обновление клиентов
После того как несколько сеансов входа через новый порт прошли успешно, закройте порт 22:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allНе меняйте SELinux-метку для порта 22. Она задается базовой политикой и не предоставляет никаких прав, как только межсетевой экран перестанет пропускать пакеты.
Затем обновите настройки клиентов, так как все инструменты, использующие порт по умолчанию, теперь требуют явного указания порта. Добавьте настройки в ~/.ssh/config на локальной машине один раз, чтобы не вводить -p постоянно:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync и Ansible считывают этот файл. Задания резервного копирования, проверки мониторинга и cron-скрипты, в которых жестко прописан порт 22, этот файл не используют, поэтому найдите их, пока изменения еще свежи в памяти.
Что дает и чего не дает смена порта
Это снижает объем мусора в логах. Автоматизированные сканеры постоянно атакуют порт 22, и перенос службы на другой порт убирает большинство этих записей из журнала, что позволяет легче заметить реальные события. Это не является мерой безопасности. Любой сканер, проверяющий весь диапазон портов, обнаружит ваш демон и прочитает его баннер с версией в любом случае. Рассматривайте смену порта как наведение порядка, а настоящую защиту обеспечьте с помощью аутентификации только по ключам с отключенным входом по паролю, что пошагово описано в руководстве по укреплению SSH на VPS.
Все вышеперечисленное работает одинаково на обоих основных дистрибутивах, основанных на RHEL, так как они собираются из одних и тех же исходных кодов. См. сравнение Rocky Linux и AlmaLinux, если вы все еще выбираете между ними. Существование двух почти идентичных сборок стало возможным после того, как CentOS перестал быть таковым в 2020 году — эта история подробно изложена в статье о переходе от Red Hat к CentOS, Rocky и AlmaLinux. Перед использованием старых руководств проверьте, какой именно релиз у вас установлен, с помощью cat /etc/os-release. Руководства, написанные для Rocky Linux 8, все еще занимают высокие позиции в поиске, а их шаги semanage и firewall-cmd остаются верными, однако в Rocky 8 отсутствует строка include sshd_config.d и нет сокет-юнита, поэтому часть руководств, касающаяся sshd, не соответствует актуальной системе.
Необходимо указать fail2ban новый порт
Пакет fail2ban отсутствует в базовых репозиториях. Он устанавливается из EPEL (Extra Packages for Enterprise Linux):
sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalldПодпакет fail2ban-firewalld позволяет fail2ban применять блокировки через firewalld, что необходимо, если firewalld управляет набором правил на сервере.
Стандартная тюрьма (jail) sshd использует port = ssh, имя которого разрешается через /etc/services в порт 22. После изменения настроек тюрьма будет следить за портом, который никто не атакует, поэтому блокировок не будет, пока попытки входа на порт 2222 накапливаются. Укажите порт числом в /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = systemd считывает неудачные попытки входа из journal, а не из /var/log/secure. Это более безопасный выбор для минимальной установки, где rsyslog может отсутствовать. Запустите службу командой sudo systemctl enable --now fail2ban и проверьте состояние тюрьмы с помощью sudo fail2ban-client status sshd. Синтаксис тюрьмы совпадает с тем, что используется в настройке fail2ban для SSH в Ubuntu 24.04. Различия заключаются только в источнике пакета и действии при блокировке.
Установка обновлений важнее смены порта
Сервер с измененным портом SSH и четырьмя месяцами не установленных обновлений безопасности находится в худшем состоянии, чем сервер на порту 22, который обновляется каждую ночь. Включите автоматическую установку обновлений в той же сессии, пока вы работаете под root: автоматические обновления dnf в Rocky Linux и AlmaLinux описывает настройку таймера и выбор между загрузкой обновлений и их применением. Установленное обновление не перезапускает демоны, которые продолжают работать со старым кодом, поэтому проверка того, что требует перезапуска или перезагрузки стоит потраченной минуты каждый раз, когда openssh-server или связанная с ним библиотека попадают в пакет обновлений.
FAQ
Почему sshd не запускается после смены порта в Rocky Linux?
Почти всегда причина в отсутствии метки порта в SELinux. sshd работает в изолированном домене sshd_t, и политика разрешает ему привязываться только к портам с меткой ssh_port_t, которая по умолчанию назначена только порту 22. Ядро запрещает привязку, поэтому демон завершает работу вместо прослушивания порта, а journalctl -u sshd содержит строку вида error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Выполните sudo semanage port -a -t ssh_port_t -p tcp 2222 с вашим номером порта, а затем перезапустите службу. Если команда semanage не найдена, сначала установите policycoreutils-python-utils.
Нужно ли использовать semanage, если SELinux работает в режиме permissive?
Да. В режиме permissive отказ записывается в лог, но привязка всё равно разрешается, поэтому кажется, что изменения сработали. Однако метка по-прежнему отсутствует. В тот момент, когда кто-либо выполнит setenforce 1 или сервер перезагрузится с параметром SELINUX=enforcing в файле /etc/selinux/config, sshd перестанет запускаться на этом порту. Добавление метки требует выполнения одной команды и предотвращает сбой, который иначе проявился бы через несколько недель без очевидной причины.
Порт помечен и sshd запущен, почему соединение прерывается по таймауту?
Если демон запущен, значит, SELinux не блокирует его, а значит, пакеты отбрасываются на пути к серверу. Проверьте sudo firewall-cmd --list-ports для вашего порта и убедитесь, что вы выполнили firewall-cmd --reload после добавления правила --permanent, так как постоянное правило само по себе не применяется к работающему файрволу. Затем проверьте панель управления хостингом на наличие внешнего сетевого файрвола перед VPS. Это второе место, где часто блокируется трафик, и внутри операционной системы это никак не отображается.
Какой порт использовать вместо 22?
Любой свободный TCP-порт в диапазоне от 1024 до 65535. Избегайте 2222 и 22222 на реальных серверах, так как сканеры проверяют их сразу после 22. Убедитесь, что номер свободен с помощью sudo ss -tlnp, проверьте, что политика SELinux ещё не зарезервировала его с помощью sudo semanage port -l, и не выбирайте порты, назначенные службам, которые вы можете установить позже. Высокий, труднозапоминаемый номер вполне подходит, так как вы один раз запишете его в ~/.ssh/config и больше не будете вводить вручную.