Как сменить порт SSH в Rocky Linux и AlmaLinux
Для смены порта SSH в RHEL-системах необходимо настроить firewalld, добавить метку порта в SELinux и изменить 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 для сервера подробно описывает режимы, контексты и логические переменные (booleans).
Шаг 3: настройка порта в конфигурации sshd
В Rocky Linux 9 и 10, AlmaLinux 9 и 10, а также в актуальных версиях Fedora файл /etc/ssh/sshd_config начинается со строки include, поэтому правильным способом внесения изменений будет создание отдельного файла конфигурации. Это позволит избежать конфликтов при обновлении пакетов.
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 unit?
Некоторые образы запускают SSH через механизм socket activation в systemd вместо использования постоянно работающего сервиса. Если настроено именно так, systemd берет на себя прослушивание сокета и передает соединения в sshd, поэтому строка Port в файле sshd_config полностью игнорируется. Проверьте это перед тем, как выполнять перезапуск:
systemctl is-enabled sshd.socketОтвет enabled означает, что порт задан в socket unit, а не в sshd_config:
sudo systemctl edit sshd.socket[Socket]
ListenStream=
ListenStream=2222Необходимо указать пустую директиву ListenStream=. Значения накапливаются при использовании drop-in файлов, поэтому без пустой директивы для очистки списка сокет продолжит прослушивать порт 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 позволяет разделить два сетевых случая: отказ (refused) означает, что пакет достиг хоста, но на порту никто не слушал, а тайм-аут (timeout) означает, что ответа не поступило вовсе.
Закрытие порта 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, если вы все еще выбираете между ними. Перед использованием любого старого руководства проверьте, какой именно релиз у вас установлен, с помощью cat /etc/os-release. Руководства, написанные для Rocky Linux 8, по-прежнему популярны, и их шаги semanage и firewall-cmd остаются верными, но в Rocky 8 нет строки включения 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 содержит описание таймера и выбор между загрузкой обновлений и их применением.
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 и больше не будете вводить вручную.