SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-09-13

Настройка безопасности сервера Rocky Linux 10

Пошаговое руководство по первичной защите Rocky Linux 10.2 и AlmaLinux. Настройка SSH по ключам, firewalld, dnf-automatic и сохранение режима SELinux enforcing для VPS.

Первый час работы с новым сервером Rocky Linux

Для обеспечения безопасности нового сервера Rocky Linux необходимо выполнить шесть действий до установки любого другого ПО: полное dnf upgrade, создание административного пользователя в группе wheel, настройка SSH только по ключам, настройка зоны firewalld с открытием только используемых сервисов, автоматические обновления через dnf-automatic и сохранение SELinux в режиме enforcing. Все приведенные ниже команды работают аналогично в AlmaLinux, так как обе ОС являются пересборками исходного кода Red Hat Enterprise Linux. Выполняйте их на сервере, к которому у вас есть альтернативный способ доступа, и держите вторую SSH-сессию открытой с того момента, как вы начнете изменять настройки SSH или межсетевого экрана.

Какую версию Rocky Linux выбрать

Этот материал написан для Rocky Linux 10.2, выпущенной 29 мая 2026 года; те же команды применимы к Rocky Linux 9 и AlmaLinux 10. В Rocky 10 по-прежнему поставляется DNF 4.20 в качестве dnf, поэтому привычные вам флаги работают ожидаемым образом. Запускайте новый сервер на ветке 10, а не 8: ветка 8 содержит самые старые версии Python и OpenSSL среди поддерживаемых, и каждый год её использования — это дополнительный год борьбы с ограничениями этих версий. Перед тем как доверять любому руководству, включая это, проверьте, какая именно система у вас загружена.

cat /etc/rocky-release
uname -r

Файл релиза выводит что-то вроде Rocky Linux release 10.2, а в 10.2 поставлялось ядро 6.12. В AlmaLinux этот файл называется /etc/almalinux-release, а /etc/os-release существует в обеих системах. Если вы ещё не сделали выбор, практические различия между Rocky Linux и AlmaLinux меньше, чем заявляется в маркетинговых материалах, и ни один пункт на этой странице не меняется в зависимости от дистрибутива. Оба дистрибутива существуют лишь потому, что Red Hat прекратила развитие CentOS как downstream-сборки в 2020 году, и история того, как это семейство прошло путь от Red Hat Linux через CentOS к Rocky и AlmaLinux, заслуживает прочтения, если вы всё ещё решаете, подходит ли вам использование rebuild-дистрибутива на ваших серверах.

Обновите всё перед выполнением любых других действий

sudo dnf upgrade --refresh -y
sudo dnf install -y dnf-plugins-core
sudo dnf needs-restarting -r

--refresh удаляет кэшированные метаданные репозиториев. Это важно для образов от провайдера, созданных за несколько недель до запуска системы, так как в противном случае dnf будет использовать устаревший индекс и сообщит, что система актуальна, хотя это не так. Затем needs-restarting -r отвечает на следующий вопрос: команда выводит Reboot is required to fully utilize these updates, если ядро или основные библиотеки были обновлены, и Reboot should not be necessary, если изменений нет. Перезагрузитесь сейчас, пока на сервере ничего не запущено и от него никто не зависит.

Создание административного пользователя в группе wheel

Вход под root по SSH означает, что кража одного ключа приводит к полной компрометации, к тому же это имя пользователя известно любому сканеру в интернете. Создайте обычную учетную запись, добавьте её в wheel и получайте права root через sudo.

sudo useradd -c 'admin account' deploy
sudo passwd deploy
sudo usermod -aG wheel deploy
id deploy

Две особенности Rocky могут удивить вас, если вы привыкли к Debian. useradd здесь автоматически создает домашний каталог, поэтому нет необходимости помнить про -m, а adduser является символической ссылкой на useradd, а не интерактивным скриптом, как в Debian. id deploy должен содержать wheel в списке групп. Эта группа и дает все права: стандартный /etc/sudoers в Red Hat содержит строку %wheel ALL=(ALL) ALL, поэтому членство в группе — это то, что дает учетной записи права root, а sudo grep -n '^%wheel' /etc/sudoers подтверждает, что строка действительно активна и не закомментирована. Кто и что выполнял через sudo впоследствии, также стоит записывать, и аудит команд пользователей на сервере охватывает эту сторону вопроса.

Теперь скопируйте свой открытый ключ со своей локальной машины, пока вход по паролю еще работает.

ssh-copy-id deploy@203.0.113.10
ssh deploy@203.0.113.10

Вторая команда должна открыть оболочку без запроса пароля. Выполните sudo -v в этом сеансе. Система запросит пароль учетной записи, который вы только что установили, и вернет управление без вывода сообщений, если членство в wheel вступило в силу. Оставьте этот сеанс открытым.

Почему на Rocky не работает вход по ключу, хотя файл выглядит корректно

ssh-copy-id устанавливает правильную метку SELinux, так как записывает файл от имени владельца. При ручном создании authorized_keys метка часто оказывается неверной, что является типичной ловушкой семейства Red Hat, отсутствующей в Ubuntu. Если создать /home/deploy/.ssh от имени root или скопировать файл из /tmp или /root, файл получит неверную метку SELinux. В результате sshd отказывает в доступе на чтение, аутентификация по ключу не проходит, а ls -l не показывает никаких ошибок.

ls -Z /home/deploy/.ssh/authorized_keys
sudo restorecon -Rv /home/deploy/.ssh
sudo ausearch -m AVC -ts recent

ls -Z должен показывать тип ssh_home_t. Если файл имеет тип user_home_t или admin_home_t после копирования из /root, это и есть ошибка; restorecon исправляет метку в соответствии с политикой. ausearch выводит соответствующий отказ в доступе в виде строки avc: denied { read } с упоминанием comm="sshd" — именно так можно отличить проблему SELinux от проблем с правами доступа. Обычные права доступа также должны соблюдаться: права на каталог должны быть 700, а на файл — 600, иначе sshd запишет Authentication refused: bad ownership or modes for file в журнал.

Отключение входа по паролю в соответствии с конфигурацией sshd в Rocky

/etc/ssh/sshd_config в Rocky 9 и 10 начинает работу с чтения каталога дополнительных конфигурационных файлов.

Include /etc/ssh/sshd_config.d/*.conf

sshd сохраняет первое найденное значение для любого параметра, а поскольку этот include находится в самом верху файла, дополнительный файл имеет приоритет над основной конфигурацией. Среди дополнительных файлов первым применяется тот, чье имя идет раньше в алфавитном порядке. Образы от облачных провайдеров часто оставляют в этом каталоге файл 50-cloud-init.conf, устанавливающий PasswordAuthentication yes. Файл с номером больше 50 проиграет ему без вывода предупреждений. Сначала изучите содержимое каталога, затем создайте файл, который будет сортироваться раньше остальных.

ls -l /etc/ssh/sshd_config.d/
sudo tee /etc/ssh/sshd_config.d/01-hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
EOF
sudo chmod 600 /etc/ssh/sshd_config.d/01-hardening.conf
sudo sshd -t

KbdInteractiveAuthentication — это строка, которую пропускают большинство руководств. PasswordAuthentication no закрывает путь для обычного пароля, но PAM keyboard-interactive является вторым способом вызвать тот же запрос пароля, поэтому, если оставить его включенным, внесенные изменения не сработают. sshd -t проверяет конфигурацию и ничего не выводит, если она корректна. После этого запросите у демона, какие настройки он фактически применил, вместо того чтобы просто перечитывать свой файл.

sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication) '

Все четыре строки должны соответствовать тому, что вы написали. Если возвращается passwordauthentication yes, значит, побеждает другой дополнительный файл, а ls выше покажет вам, какой именно. Только после этого выполняйте перезагрузку, и только при открытой первой сессии.

sudo systemctl reload sshd

Откройте второй терминал и войдите в систему, прежде чем закрывать первый. Восстановление доступа к заблокированному VPS означает использование консоли провайдера, что медленнее любого другого способа. В sshd_config нужно изменить больше параметров, чем эти четыре строки, и в укреплении безопасности SSH на VPS рассматриваются остальные настройки.

Открывайте только те сервисы, которые вы используете, с помощью firewalld

В Rocky Linux firewalld установлен и включен по умолчанию, что является главным отличием от версии этого чек-листа для Ubuntu, где присутствует ufw, но он неактивен. Образы от провайдеров различаются, поэтому проверьте состояние перед внесением изменений.

sudo firewall-cmd --state
sudo firewall-cmd --get-default-zone
sudo firewall-cmd --list-all

--state выводит running или not running. Зона по умолчанию — public в стандартном образе, а --list-all показывает разрешенные в ней сервисы. ssh — один из них, именно поэтому вы смогли войти в систему. Добавьте только то, что вы действительно предоставляете, и ничего больше.

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services

Флаг --permanent записывает изменения в файл зоны и не меняет текущую конфигурацию работающего файрвола. Правило, добавленное без этого флага, применяется к работающему файрволу, но исчезает после следующего --reload или перезагрузки. Если вы забыли --reload, правило, которое вы добавили, не появится в --list-services. Если вы хотите протестировать настройки перед сохранением, добавьте правило без --permanent, убедитесь, что сервис отвечает, а затем выполните sudo firewall-cmd --runtime-to-permanent. Зоны и расширенные правила (rich rules) позволяют настроить гораздо больше, подробнее об этом в основах firewalld для VPS.

Одна деталь, которую файрвол на сервере не может показать: большинство провайдеров используют второй пакетный фильтр в своей сети, перед вашим сервером. Если firewall-cmd --list-all сообщает, что порт открыт, но внешние соединения всё равно отклоняются, скорее всего, он заблокирован на стороне провайдера. Проверьте панель управления, прежде чем приступать к отладке на сервере.

EPEL и CRB: только при необходимости для пакетов

Собственные репозитории Rocky намеренно сделаны небольшими, а два дополнительных источника заполняют пробелы. CRB (CodeReady Builder) содержит заголовочные файлы для разработки и библиотеки, отсутствующие в базовых репозиториях. EPEL (Extra Packages for Enterprise Linux) — это сборки сообщества Fedora для данного семейства дистрибутивов; именно там находятся fail2ban и еще несколько тысяч пакетов.

sudo dnf config-manager --set-enabled crb
sudo dnf install -y epel-release
sudo dnf repolist

crb — это идентификатор репозитория в Rocky и AlmaLinux. В Rocky 8 этот же репозиторий назывался powertools, а в Red Hat Enterprise Linux он имеет имя codeready-builder-for-rhel-10-x86_64-rpms, поэтому скопированные инструкции часто завершаются ошибкой Error: No matching repo to modify: crb. Пакет epel-release находится в репозитории extras дистрибутива Rocky, который включен по умолчанию, поэтому импортировать ключи вручную не требуется. Включайте эти репозитории только тогда, когда они необходимы для установки нужного вам ПО, так как каждый дополнительный репозиторий — это еще один источник, из которого будут подтягиваться автоматические обновления. В Включение EPEL и CRB в Rocky и AlmaLinux рассматриваются вопросы приоритетов и закрепления версий (pinning).

Автоматические обновления безопасности с помощью dnf-automatic

Ни один из вышеперечисленных методов не обеспечит безопасность системы через три недели, если сервер перестанет получать патчи. В Rocky отсутствует unattended-upgrades. Эквивалентом является dnf-automatic, который состоит из одного конфигурационного файла и таймера systemd; в Rocky 10.2 поставляется версия 4.20.

sudo dnf install -y dnf-automatic

Отредактируйте /etc/dnf/automatic.conf. Эти параметры определяют дальнейшие действия.

[commands]
upgrade_type = default
random_sleep = 3600
download_updates = yes
apply_updates = yes
reboot = never

[emitters]
emit_via = stdio

Параметр apply_updates по умолчанию имеет значение no в поставляемом файле. Это главная ловушка данного раздела: вы устанавливаете пакет, активируете таймер, уходите, а машина каждое утро скачивает обновления, но не устанавливает ни одного из них. Установите значение yes, а затем проверьте, что запуск действительно выполнил работу.

sudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timer
journalctl -u dnf-automatic.service --since -7d

Команда list-timers должна показать NEXT время в течение следующего дня, а журнал (journal) — это место, где объясняются причины сбоя или пустого запуска. Легко ошибиться в двух дополнительных деталях. Пакет также содержит dnf-automatic-install.timer, dnf-automatic-download.timer и dnf-automatic-notifyonly.timer; эти юниты намеренно переопределяют ваш конфигурационный файл своим фиксированным поведением. Поэтому активируйте только dnf-automatic.timer, иначе файл, который вы только что отредактировали, будет проигнорирован.

Вторая деталь — upgrade_type. Установка значения security кажется осторожным выбором, но в дистрибутиве, основанном на пересборке, это более рискованный вариант. Он фильтрует обновления на основе метаданных рекомендаций (updateinfo.xml), публикуемых вместе с пакетами, а метаданные Rocky в некоторых ветках иногда оказываются устаревшими. Протестируйте это на своей системе, прежде чем полагаться на данный метод.

sudo dnf updateinfo list --available --security

Пустой список на системе, где есть ожидающие обновления, означает, что метаданные не помечают ничего как исправление безопасности, поэтому upgrade_type = security не установит ничего. default обновляет всё, что в стабильной корпоративной ветке представляет собой небольшой и хорошо протестированный набор изменений. В Запуск dnf-automatic в Rocky и AlmaLinux рассматриваются эмиттеры, настройки перезагрузки и способы удержания пакета от обновления.

Нужна ли защита от перебора паролей на сервере с доступом только по ключам?

При использовании PasswordAuthentication no и KbdInteractiveAuthentication no попытка SSH-брутфорса не может увенчаться успехом, так как пароля для подбора не существует. Остается лишь «шум» в логах и незначительная нагрузка на CPU при отклонении соединений. Это единственный аргумент в пользу fail2ban на небольшом сервере: она делает journalctl -u sshd снова читаемыми. Если на сервере запущен любой сервис с аутентификацией по паролю, аргументы в пользу защиты становятся гораздо весомее.

Пакет fail2ban доступен в репозитории EPEL, поэтому сначала включите его. В Rocky 10 используется версия 1.1.0.

sudo dnf install -y fail2ban-server fail2ban-firewalld fail2ban-selinux fail2ban-systemd

fail2ban-firewalld — это подпакет, который здесь важен. Без него fail2ban применяет блокировки через команды iptables, что на сервере с firewalld означает работу двух инструментов с одним набором правил nftables без учета действий друг друга. fail2ban-selinux содержит модуль политики, позволяющий демону выполнять свою работу при включенном SELinux в режиме enforcing. По умолчанию ни один «jail» не включен, а файл jail.conf перезаписывается при обновлении пакета, поэтому размещайте свои настройки в отдельном файле рядом с ним.

sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF'
[sshd]
enabled = true
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

backend = systemd считывает данные из journal вместо /var/log/secure, что является правильным выбором для минимального образа, так как журнал присутствует всегда, а лог-файл существует только при установленном rsyslog. Команда fail2ban-client status sshd должна вывести информацию о «jail» с его секциями фильтров и действий, а также список заблокированных адресов, который изначально пуст. На публичном IP-адресе он не останется пустым надолго. Убедитесь, что блокировка действительно доходит до межсетевого экрана с помощью sudo firewall-cmd --list-rich-rules. Устанавливайте bantime в часах, а не в днях, и добавьте свой постоянный IP-адрес в ignoreip в том же файле, так как первым, кого блокирует неверно настроенный «jail», обычно оказываетесь вы сами.

Оставьте SELinux в режиме enforcing и выполните одну команду semanage для смены порта

Самый частый совет по Rocky в интернете — установить SELINUX=disabled и перезагрузиться. Не делайте этого. SELinux — одна из главных причин выбора этого семейства дистрибутивов вместо Ubuntu. Поставляемые политики написаны специально для ПО из официальных репозиториев, и стандартная установка nginx или podman работает под ними без каких-либо изменений. Docker — частое исключение, так как он устанавливается из сторонних источников, и доступ к его bind mounts блокируется, пока вы не назначите им правильные метки. Именно этому посвящена большая часть руководства по установке Docker на Rocky или AlmaLinux. Сначала проверьте текущий статус.

getenforce
sudo sestatus

getenforce должен вывести Enforcing. Некоторые образы от провайдеров поставляются с Permissive, который только логирует отказы, но ничего не блокирует, поэтому лучше прочитать значение, а не предполагать его. Если что-то перестает работать, запись об отказе уже создана для вас.

sudo ausearch -m AVC -ts recent

Единственный случай, когда при первичной настройке вы столкнетесь с политикой — это перенос SSH с порта 22. Политика sshd разрешает привязку только к портам с меткой ssh_port_t, и 22 — единственный порт с такой меткой. Если вы просто измените Port 2222, демон откажется запускаться, а в journalctl -u sshd появится следующая ошибка:

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

Решение состоит из одной команды и установки пакета, который её предоставляет.

sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

semanage не установлен в Rocky 10 по умолчанию, поэтому первая ошибка, с которой сталкиваются пользователи — это semanage: command not found, а не сообщение, указывающее на SELinux. Полная последовательность действий, включая сохранение доступа по 22 порту до тех пор, пока вы не убедитесь в работоспособности нового, описана в смене SSH-порта с учетом SELinux и firewalld. Для изучения контекстов, булевых значений и действий при конфликтах установленного ПО с политиками SELinux, ознакомьтесь с основами SELinux для сервера.

Что можно пропустить на одном небольшом VPS

Не всё из этого списка необходимо на одной маленькой машине.

  • Оставьте SELinux в режиме enforcing. Это ничего не стоит, а одна команда semanage выше решает единственный сценарий, с которым вы, скорее всего, столкнетесь в первый час работы.
  • Оставьте dnf-automatic вместе с apply_updates = yes. Сервер без обновлений безопасности — это та проблема, с которой люди сталкиваются на самом деле.
  • Пропустите fail2ban, если SSH — единственный сервис, ожидающий соединений, и доступ разрешен только по ключам. Это избавит логи от лишнего шума ценой запуска еще одного демона и риска заблокировать себе доступ. systemctl status fail2ban выводит данные об использовании памяти юнитом, поэтому вы можете сами оценить стоимость этого решения для вашей системы.
  • Пропустите EPEL и CRB, пока они не потребуются для установки нужного пакета. Подключение репозитория — это долгосрочное решение о том, откуда будут приходить обновления.
  • Пропустите смену порта SSH. Это уменьшает количество записей от сканеров в логах. Это не остановит никого, кто целенаправленно изучает ваш сервер.

Единственное, что никогда нельзя пропускать — это скучная рутина: держите вторую SSH-сессию открытой при любых изменениях настроек SSH или межсетевого экрана, и научитесь пользоваться последовательной консолью (serial console) вашего провайдера до того, как она вам понадобится. Если вы переходите с Debian или Ubuntu, эквиваленты команд dnf и apt быстро помогут восстановить мышечную память, а unattended-upgrades в Ubuntu выполняет ту же задачу в той системе. Дистрибутивно-независимая версия этого списка — первые десять минут на новом VPS, а учетные записи с минимальными привилегиями на VPS раскрывают вопрос управления пользователями шире, чем просто добавление одного участника в wheel.

FAQ

Стоит ли отключать SELinux на сервере с Rocky Linux?

Нет. Сообщение об отказе в доступе указывает на файл или порт, которые не предусмотрены политикой. Прочитайте его с помощью sudo ausearch -m AVC -ts recent, затем исправьте метку командой restorecon или установите нужный для сервиса булев параметр. Если необходимо ослабить ограничения, установите SELINUX=permissive в /etc/selinux/config на время отладки: это позволит записывать отказы в лог, не блокируя действия. Избегайте SELINUX=disabled, так как в отключенном состоянии система перестает поддерживать метки файлов, и при последующем включении режима принудительного контроля (enforcing) потребуется полная перемаркировка диска при следующей загрузке.

Нужен ли еще fail2ban, если для SSH используется только вход по ключам?

Для самого SSH — нет. Если параметры PasswordAuthentication no и KbdInteractiveAuthentication no установлены и проверены в sudo sshd -T, у атакующего нет пароля для подбора, и попытки перебора не увенчаются успехом. В этом случае fail2ban лишь делает журнал событий чище и немного снижает нагрузку на процессор при отклонении соединений. Его использование становится оправданным, как только на сервере появляется сервис, принимающий пароли, например, почтовый сервер или форма входа веб-приложения.

Почему вход по ключу не работает после создания каталога .ssh от имени root?

Потому что файл имеет неверную метку SELinux, и sshd отказывает в доступе к нему. Проверьте это с помощью ls -Z /home/deploy/.ssh/authorized_keys. Тип должен быть ssh_home_t, а файл, созданный от root или скопированный из /root, обычно имеет тип admin_home_t. Выполните sudo restorecon -Rv /home/deploy/.ssh, чтобы восстановить метку согласно политике. Подтвердите диагноз с помощью sudo ausearch -m AVC -ts recent: команда выведет строку avc: denied { read } с указанием comm="sshd". Также проверьте обычные права доступа: 700 для каталога и 600 для файла.

Чем заменить unattended-upgrades в Rocky Linux?

dnf-automatic, который устанавливается через sudo dnf install -y dnf-automatic и управляется с помощью /etc/dnf/automatic.conf и dnf-automatic.timer. Установите apply_updates = yes в секции [commands], так как значение по умолчанию — no, и в противном случае таймер будет бесконечно скачивать обновления, не устанавливая их. Включите только dnf-automatic.timer и никакие другие юниты, поскольку дополнительные таймеры из пакета переопределяют ваш конфигурационный файл своим фиксированным поведением.

Стоит ли разворачивать новый сервер на Rocky Linux 8?

Отдавайте предпочтение ветке 10 или 9, если используемое вами ПО еще не имеет сборок для 10. В Rocky 8 используются самые старые версии Python и OpenSSL среди поддерживаемых веток, поэтому для нового ПО все чаще отсутствуют пакеты под эту версию. В итоге вам придется либо собирать программы из исходного кода, либо добавлять сторонние репозитории на машину, которую вы планировали оставить простой. Проверьте версию текущей системы с помощью cat /etc/rocky-release, так как образы от провайдеров с пометкой "Rocky Linux" иногда оказываются старее, чем указано в панели управления.