Управление доступом на сервере сводится к четырём задачам: завести учётную запись, дать ей вход по ключу, ограничить, откуда и под каким именем можно подключаться, и выдать ровно те привилегии, которые нужны для работы. Bastion-хост, журналы и аудит обслуживают эти четыре задачи.
Порядок действий, который сохраняет доступ: подготовить SSH-ключ, проверить вход по нему в новом сеансе и только затем менять sshd_config и sudoers. Отключение парольной аутентификации до проверки ключа, самая частая причина потерять сервер и ехать в дата-центр за консолью KVM.
Ниже весь цикл целиком: useradd и authorized_keys с правами 700 и 600, директивы AllowUsers, AllowGroups и Match, отдельные файлы в /etc/sudoers.d/ с проверкой через visudo -c, отключение PasswordAuthentication и PermitRootLogin, ProxyJump на bastion и работа с логами. Команды приведены для Debian/Ubuntu и RHEL-подобных систем, различия отмечены по ходу текста.
Что входит в управление доступом на сервере и с чего начать
Полный контур доступа на Linux-сервере состоит из учётных записей, ключей, ограничений в sshd_config, правил sudoers, схемы подключения через bastion и журналов. Работает это только в комплексе: ключ без ограничения по IP пускает любого, у кого он оказался, а sudoers без аудита не показывает, кто и что запускал.
Принцип минимальных привилегий и порядок настройки
Порядок шагов выбран так, чтобы на каждом этапе оставался рабочий способ входа.
- Создать учётную запись: useradd -m -s /bin/bash deploy. В Debian/Ubuntu ту же задачу решает adduser deploy.
- Добавить публичный ключ в /home/deploy/.ssh/authorized_keys и выставить права 700 на каталог, 600 на файл.
- Открыть второй SSH-сеанс с ключом, не закрывая текущий, и убедиться, что вход прошёл по publickey.
- Настроить sudo: отдельный файл в /etc/sudoers.d/ с точечными командами.
- Ограничить вход по группам и адресам: AllowGroups, AllowUsers, Match Address.
- Отключить парольную аутентификацию и вход root: PasswordAuthentication no, PermitRootLogin no.
- Включить журналирование: LogLevel VERBOSE, log_output в sudo, при необходимости fail2ban и auditd.
Принцип минимальных привилегий раскладывается на три правила. Персональная учётная запись для каждого специалиста вместо общей, чтобы журнал указывал на конкретного человека. Вход root по SSH закрыт, административные задачи идут через sudo. Права sudo выдаются на конкретные команды, а не на всё подряд.
Изменения в sshd_config и sudoers проверяются до перезапуска службы. Для sshd это sshd -t, для sudo - visudo -c. Ошибка в синтаксисе при перезапуске оставит сервер без удалённого доступа, а исправлять её придётся через консоль.
Смежные темы, PAM, политики паролей и гранулярные права sudo, разобраны в материале Аутентификация и безопасный доступ в Linux: PAM, SSH-ключи и sudo.
Различия в путях и службах для Debian/Ubuntu и RHEL
Инструкция применима к обеим веткам, но имена служб, файлов и групп отличаются.
| Что | Debian/Ubuntu | RHEL/CentOS/Rocky/Alma |
|---|---|---|
| Конфигурация sshd | /etc/ssh/sshd_config | /etc/ssh/sshd_config |
| Имя службы | ssh | sshd |
| Журнал аутентификации | /var/log/auth.log | /var/log/secure |
| Группа администраторов | sudo | wheel |
| Пакет sudo | обычно установлен | может отсутствовать на minimal install |
Проверка перед началом работы:
cat /etc/os-release command -v sudo || echo "sudo не установлен" rpm -q sudo # RHEL dpkg -l sudo # Debian/Ubuntu
Если sudo нет, на RHEL его ставят через dnf install sudo, на Debian через apt install sudo. Без пакета первая же команда с sudo завершится ошибкой, а группа wheel или sudo останется декоративной.
Создание учётных записей и настройка SSH-ключей на сервере
Создание пользователя и подготовка домашней директории
useradd -m -s /bin/bash deploy passwd -l deploy id deploy ls -ld /home/deploy
Ключ -m создаёт домашний каталог, -s задаёт оболочку. Блокировка пароля через passwd -l оставляет учётную запись без пароля, но не удаляет её: вход возможен только по ключу. Вариант с установкой пароля (passwd deploy) нужен, если планируется вход через консоль или аварийный доступ.
Команда adduser deploy в Debian/Ubuntu делает то же самое и сразу запрашивает пароль, создавая каталог с корректными правами. Для sudo на RHEL пользователя добавляют в группу wheel:
usermod -aG wheel deploy usermod -aG sudo deploy # Debian/Ubuntu
Проверка: id deploy должен показать членство в нужной группе. Изменения в группах применяются к новым сеансам, уже открытые остаются со старыми правами.
Генерация пары ключей и добавление публичного ключа
ssh-keygen -t ed25519 -C "deploy@laptop" ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@203.0.113.10
ed25519 даёт компактный и быстрый ключ, поддерживаемый в актуальных сборках OpenSSH. Для совместимости со старыми системами, где этот тип недоступен, берут rsa с длиной 4096 бит: ssh-keygen -t rsa -b 4096.
Ручной вариант нужен, когда ssh-copy-id недоступен или на сервере нестандартный порт:
mkdir -p /home/deploy/.ssh chmod 700 /home/deploy/.ssh vi /home/deploy/.ssh/authorized_keys chmod 600 /home/deploy/.ssh/authorized_keys chown -R deploy:deploy /home/deploy/.ssh
Права здесь не формальность. При 777 на каталог или 644 на файл с ключом sshd откажет в аутентификации и запишет в лог предупреждение о небезопасных правах. Публичный ключ копируют свободно, приватный (файл id_ed25519 без расширения .pub) не покидает рабочую машину.
Приватный ключ защищают парольной фразой, а на время сессии подгружают в агент, чтобы не вводить её каждый раз:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 ssh-add -l
Проверка входа по ключу до отключения пароля
Новый сеанс открывают, не закрывая текущий, и смотрят, каким методом прошла аутентификация:
ssh -v deploy@203.0.113.10
В выводе ssh -v должна быть строка Authentications that can continue: publickey и запись Offering public key с путём к нужному ключу. Если перечислены password или keyboard-interactive, значит ключ не найден или права на .ssh некорректны. Разбираться с этим до правки sshd_config, а не после.
Ограничение доступа по IP и группам в sshd_config
Директивы AllowUsers, AllowGroups и Match в sshd_config
Сначала создают группу, членство в которой даёт право входа:
groupadd ssh-users usermod -aG ssh-users deploy getent group ssh-users
Затем в /etc/ssh/sshd_config добавляют ограничения:
AllowGroups ssh-users admins AllowUsers admin@192.0.2.10 DenyUsers guest backup DenyGroups interns
AllowUsers понимает шаблон вида пользователь@адрес, что привязывает конкретную учётную запись к конкретному IP. Пользователи, не попавшие ни в один Allow*, теряют доступ. Директивы обрабатываются в порядке DenyUsers, AllowUsers, DenyGroups, AllowGroups: решение принимает первое совпадение в этом списке.
Блок Match задаёт отдельные настройки для группы адресов или пользователей и размещается в конце файла. После него параметры действуют до следующего Match или до конца файла.
Match Address 203.0.113.0/24
PasswordAuthentication yes
AllowTcpForwarding no
Match Group contractors
AllowTcpForwarding no
X11Forwarding no
Типовой сценарий: для доверенной подсети офиса оставить парольный вход как аварийный, а для всех остальных адресов требовать ключ. Проверка синтаксиса до перезапуска: sshd -t. Эффективное значение параметра с учётом всех блоков Match показывает sshd -T.
Ограничение на уровне файрвола
Правила sshd ограничивают вход внутри демона, файрвол отсекает соединения раньше и снижает объём мусора в журналах от перебора.
iptables -A INPUT -p tcp --dport 22 -s 203.0.113.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP nft add rule inet filter input tcp dport 22 ip saddr 203.0.113.0/24 accept nft add rule inet filter input tcp dport 22 drop firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="22" protocol="tcp" accept' firewall-cmd --reload
Правило iptables с ACCEPT для доверенной подсети и DROP для остальных оставляет доступ только ей. Ошибка в CIDR, например лишний нулевой октет или не та маска, закрывает доступ полностью. Правила iptables и nftables до перезагрузки живут в памяти, для постоянного хранения нужны iptables-save, nft list ruleset в файл или пакет iptables-persistent в Debian/Ubuntu. Новое правило проверяют из отдельного сеанса, не закрывая текущий.
Настройка брандмауэра и защита SSH подробно разобраны в руководстве по базовой безопасности сервера.
Настройка sudoers: как выдать права без лишних рисков
Файл /etc/sudoers и все файлы в /etc/sudoers.d/ редактируют только через visudo. Он блокирует файл от параллельной записи и проверяет синтаксис, не давая сохранить заведомо сломанную конфигурацию.
Файлы в /etc/sudoers.d/ и проверка синтаксиса
visudo -f /etc/sudoers.d/deploy visudo -c
Директива @includedir /etc/sudoers.d в основном файле подключает каталог, поэтому отдельный файл на пользователя безопаснее правки /etc/sudoers: правило легко удалить, а область его действия ограничена.
# /etc/sudoers.d/deploy deploy ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
Права на файл: 440, владелец root:root. Sudo игнорирует файлы в sudoers.d с неверными правами и пишет об этом в журнал. Проверка выданных прав выполняется от лица администратора:
sudo -l -U deploy
Вывод покажет список разрешённых команд. Такой же список полезно приложить к заявке на выдачу прав, чтобы ревьюер видел точный набор.
Точечные права через Cmnd_Alias и ограничения NOPASSWD
Cmnd_Alias SERVICES = /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx Cmnd_Alias LOGS = /usr/bin/journalctl deploy ALL=(root) SERVICES, LOGS %devops ALL=(ALL:ALL) ALL
Cmnd_Alias собирает список разрешённых команд в одном месте. Запись deploy ALL=(root) SERVICES, LOGS даёт пользователю перезапуск nginx и чтение журнала, но не запуск оболочки. Строка %devops ALL=(ALL:ALL) ALL выдаёт группе полный набор прав, включая sudo -i и любой интерпретатор. Администратор с полным доступом должен быть в узкой группе, а не в общей.
NOPASSWD снимает запрос пароля. Он удобен для автоматизации, но при компрометации учётной записи атакующий получает привилегированные команды без второго фактора. Ограничить окно ввода пароля безопаснее, чем отключать его совсем:
Defaults timestamp_timeout=5 Defaults log_output Defaults use_pty
log_output пишет выполненные команды в журнал, use_pty запускает их в отдельном псевдотерминале. Чтобы отделить записи sudo от общего журнала, добавляют Defaults logfile=/var/log/sudo.log. Директива requiretty ограничивает запуск sudo интерактивным терминалом и мешает сценариям автоматизации, поэтому на серверах её обычно отключают через Defaults !requiretty. Для задач, где пароль ввести некому, NOPASSWD применяют точечно к одной команде, а не ко всему набору.
Отключение парольной аутентификации и усиление SSH
Правки sshd_config и проверка перед перезапуском
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak PubkeyAuthentication yes PasswordAuthentication no PermitEmptyPasswords no PermitRootLogin no KbdInteractiveAuthentication no MaxAuthTries 4 LoginGraceTime 30 X11Forwarding no AllowAgentForwarding no LogLevel VERBOSE
KbdInteractiveAuthentication закрывает интерактивный ввод пароля через PAM и часто остаётся включённым даже после PasswordAuthentication no, поэтому эту директиву проверяют отдельно. Старый синоним ChallengeResponseAuthentication в свежих версиях OpenSSH помечен как устаревший; если демон его не знает, достаточно оставить KbdInteractiveAuthentication.
Проверка и применение:
sshd -t sshd -T | grep -i -E "passwordauth|permitrootlogin|kbdinteractive" systemctl reload ssh # Debian/Ubuntu systemctl reload sshd # RHEL
Reload перечитывает конфигурацию без разрыва активных сессий, restart нужен при смене порта или параметров привязки. После отключения пароля восстановление возможно только через консоль KVM или IPMI, если ключи потеряны или повреждены. Смена Port на нестандартный снижает объём автоматического шума в логах, но не заменяет ограничение по адресам.
Защита от перебора и логирование SSH
fail2ban блокирует адреса после серии неудачных попыток. Конфигурация для sshd в отдельном файле:
# /etc/fail2ban/jail.d/sshd.local [sshd] enabled = true maxretry = 4 findtime = 10m bantime = 1h
На системах с systemd для fail2ban нужен параметр backend = systemd, иначе он не увидит записи в journal. Состояние проверяют командой fail2ban-client status sshd, она же показывает список заблокированных адресов. Уровень LogLevel VERBOSE заставляет sshd писать отпечатки ключей, что помогает понять, каким ключом подключались.
Просмотр журналов в реальном времени: journalctl -u ssh -f. Для файловых журналов это tail -f /var/log/auth.log в Debian/Ubuntu или tail -f /var/log/secure в RHEL.
Jump-host: доступ к внутренним серверам через bastion
Схема простая: один сервер с публичным адресом принимает подключения по строгим правилам, а внутренние серверы с приватными адресами SSH-портов в интернет не публикуют.
Настройка ProxyJump на клиенте
# ~/.ssh/config
Host bastion
HostName 198.51.100.7
User jump
IdentityFile ~/.ssh/id_ed25519
Host internal-app
HostName 10.0.0.5
User deploy
ProxyJump bastion
С такой записью подключение к внутреннему серверу выполняется как ssh internal-app, а приватный ключ внутреннего узла остаётся на рабочей машине и не копируется на bastion. Вариант без конфига: ssh -J jump@bastion deploy@10.0.0.5. Цепочку удобно проверять через ssh -v internal-app: в выводе видны два этапа аутентификации.
Ограничения на bastion-хосте
AllowGroups bastion-users AllowTcpForwarding yes PermitOpen 10.0.0.5:22 10.0.0.6:22 GatewayPorts no
PermitOpen сужает переадресацию до конкретных адресов и портов: скомпрометированный ключ на bastion не даст пробить туннель к произвольному узлу сети. Значение AllowTcpForwarding no отключает переадресацию полностью, но тогда ProxyJump перестанет работать, поэтому на bastion его оставляют включённым вместе с PermitOpen. GatewayPorts no запрещает публиковать туннели на внешних интерфейсах.
Для jump-доступа заводят отдельного пользователя без sudo и без файлов с приватными ключами внутренних серверов. Сессии на bastion полезно записывать через auditd или утилиту script в отдельный каталог. Сам bastion усиливают теми же мерами, что и остальные серверы: вход только по ключу, ограничение по IP, журналирование.
Журналы входов и аудит: как проверить, кто и когда подключался
Проверка успешных и неуспешных входов
last lastb who w journalctl -u ssh --since "1 day ago" grep "Failed password" /var/log/auth.log grep sshd /var/log/secure
last читает бинарный журнал wtmp и показывает успешные входы со временем и адресом. lastb читает btmp с неудачными попытками, требует прав root и часто пуст, если неудачных входов не было. who и w показывают активные сеансы в реальном времени.
Попытки входа с неверными именами видны в auth.log и secure как Invalid user. С включённым LogLevel VERBOSE там же сохраняются отпечатки ключей, что позволяет сопоставить подключение с конкретным ключом и понять, действием какого специалиста оно было.
Аудит действий sudo и сессий
Строка Defaults log_output в sudoers включает запись выполненных команд, файл журнала задаётся через Defaults logfile=/var/log/sudo.log. Для более глубокого аудита используют auditd с правилами на вызовы execve и sudo:
ausearch -m USER_CMD -ts recent ausearch -m EXECVE -ts today | head
Журналы быстро растут, поэтому настраивают ротацию через logrotate и следят за свободным местом. При LogLevel VERBOSE и включённом аудите объём записей заметно увеличивается, что важно учитывать на серверах с интенсивным трафиком.
Как выглядят следы атак, удобно разбирать на конкретном примере. В инциденте с роутерами MikroTik характерные записи имели вид: login failure for user -2 from "ip" via ssh; user "name" added by ssh:-2@"ip" (Security Week 2638). Имя пользователя с некорректными символами и создание учётной записи из SSH-сессии указывают на то, что аутентификацию обошли и закрепились в системе. Проверка журналов входит в чек-лист аудита безопасности Linux-сервера.
Типовые ошибки при выдаче прав и разбор инцидентов
Ошибки в SSH и sudoers, которые открывают доступ
- PermitRootLogin yes. Вход root по SSH даёт готовую цель для перебора и лишает журнал привязки к конкретному человеку. Проверка: sshd -T | grep permitrootlogin.
- PasswordAuthentication yes при доступе сервера из интернета. Пароли подбираются автоматически. Проверка: sshd -T | grep passwordauth.
- AllowUsers без ограничения по адресу. Директива без шаблона user@ip пускает пользователя с любого адреса. Ограничение: AllowUsers admin@192.0.2.10.
- Права 777 на ~/.ssh или 644 на authorized_keys. sshd отказывает во входе по ключу и пишет предупреждение. Исправление: chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys.
- NOPASSWD: ALL или ALL=(ALL:ALL) ALL в файле конкретного пользователя. Права уровня root без пароля. Исправление: список команд через Cmnd_Alias.
- Пользователь в группе sudo или wheel без необходимости. Проверка: getent group sudo, id username.
- Обновления не устанавливаются. Уязвимость в демоне или службе обнуляет аккуратную настройку доступа.
Чему учит инцидент с MikroTik
В 2026 году CERT Polska опубликовал данные о трёх уязвимостях в RouterOS. Взлом роутеров MikroTik возможен, если на устройстве разрешён доступ по протоколу SSH из интернета. Уязвимость CVE-2026-67276 позволяет обойти аутентификацию по SSH, если атакующему известно имя пользователя и модуль публичного ключа. Ошибка CVE-2026-86060 открывает возможность эскалации привилегий при использовании имени пользователя, содержащего некорректные символы. Комбинация двух уязвимостей делает возможной полную компрометацию устройства, обе имеют рейтинг 9,2 балла по шкале CVSS. Третья проблема, CVE-2026-67277 с рейтингом 8.8, находится в службе проверки скорости интернет-соединения и в худшем случае приводит к отказу в обслуживании (Security Week 2638).
Обновления, закрывающие эти уязвимости, выпущены в версиях RouterOS 7.25beta3, 7.24.2, 7.23.4 и 6.49.21. На момент публикации в сети наблюдалось более 122 тысяч потенциально уязвимых устройств. Две наиболее опасные уязвимости польский CERT обнаружил с помощью моделей GPT 5.5 Cyber и GPT 5.6 Sol компании OpenAI.
Переносить эти выводы на Linux-серверы напрямую нельзя: уязвимости описаны применительно к RouterOS, а не к универсальным серверным ОС. Общий принцип сохраняется: SSH, закрытый для интернета, вход без парольной аутентификации и свежие обновления убирают вектор, который в этом инциденте привёл к полной компрометации. Парольная аутентификация и вход с некорректным именем пользователя сработали как точка входа, хотя обе проблемы решаются настройкой ограничений доступа.
Чек-лист проверки и восстановление доступа
Чек-лист перед перезапуском служб
- sshd -t не показывает ошибок.
- sshd -T подтверждает нужные значения параметров.
- visudo -c возвращает parsed OK.
- Открыт второй SSH-сеанс с ключом, первый не закрыт.
- Сделаны копии /etc/ssh/sshd_config и /etc/sudoers.
- Есть доступ к консоли KVM или IPMI.
- Правила файрвола проверены из отдельного сеанса.
- sudo -l -U deploy показывает ожидаемый набор команд.
- Новые записи в journalctl -u ssh появляются.
Что делать, если доступ потерян
- Подключиться к серверу через консоль KVM или IPMI.
- Восстановить резервную копию: cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config.
- Если проблема в sudoers, удалить лишний файл из /etc/sudoers.d/ или отредактировать его через visudo -f.
- Проверить синтаксис: sshd -t и visudo -c.
- Перезапустить службу: systemctl restart ssh или systemctl restart sshd.
- Открыть новый SSH-сеанс и убедиться, что вход по ключу работает.
Если консоль недоступна, сервер загружают в rescue-режиме или в однопользовательском режиме через GRUB, монтируют корневую файловую систему и правят конфиги на диске. Причина потери доступа в большинстве случаев одна: парольная аутентификация отключена до того, как вход по ключу проверен.
Контур безопасности собирается из пяти элементов: ключи вместо паролей, ограничения по группам и адресам, точечные права sudo, схема с bastion вместо публикации портов и журналы, по которым видно, кто и когда подключался. Пройтись по каждому пункту на своём сервере помогает чек-лист аудита безопасности Linux-серверов, а найденные отклонения стоит сразу превратить в задачи с конкретными сроками.