PAM-аутентификация в Linux: настройка политик безопасности

PAM-аутентификация в Linux: настройка политик безопасности

PAM-аутентификация в Linux: настройка политик безопасности

Что такое PAM и почему это важно знать каждому сисадмину

Когда мы проводим аудит Linux-инфраструктуры клиента, почти всегда натыкаемся на одну и ту же картину: PAM либо вообще не трогали со времён установки системы, либо настроили как-то вкривь-вкось по инструкции пятилетней давности. Между тем именно PAM — это тот самый слой, через который проходит каждый вход на сервер.

PAM расшифровывается как Pluggable Authentication Modules. Буквально — подключаемые модули аутентификации. Идея элегантная: приложение не реализует логику проверки пользователя самостоятельно, а делегирует это фреймворку. SSH, sudo, login, su — все они работают через PAM. Хотите добавить двухфакторную аутентификацию? Подключили модуль. Нужна блокировка после 5 неудачных попыток? Ещё один модуль. При этом само приложение не меняется ни строчкой.

Появился PAM ещё в середине 90-х в Solaris. В Linux пришёл через Linux-PAM — открытую реализацию, которая сейчас стоит на каждом дистрибутиве. Debian/Ubuntu используют пакет libpam-runtime, RHEL/CentOS — pam.

Почему это критически важно с точки зрения безопасности? Без нормальной настройки PAM у вас: нет блокировки при брутфорсе, слабые пароли принимаются системой, нет 2FA, нет ограничений на ресурсы. Один из наших клиентов — небольшая торговая компания в Москве — получил инцидент именно из-за отсутствия pam_faillock. Атакующий методично перебирал пароли к SSH почти сутки, пока это не заметили в логах.

Архитектура PAM: файлы конфигурации и типы модулей

Конфигурация PAM живёт в двух местах. Первое — файл /etc/pam.conf, где каждая строка начинается с имени сервиса. Второе — директория /etc/pam.d/, где каждый сервис получает свой файл. Современные системы используют второй вариант: /etc/pam.d/sshd, /etc/pam.d/sudo, /etc/pam.d/login и так далее.

Каждая строка конфигурации PAM выглядит так:

тип_модуля  флаг_управления  путь_к_модулю  [аргументы]

Четыре типа модулей, которые нужно знать наизусть:

  • auth — проверяет подлинность пользователя (пароль, токен, биометрия)
  • account — проверяет, разрешён ли доступ (не истёк ли пароль, нет ли ограничений по времени)
  • password — смена пароля, проверка его сложности
  • session — действия при открытии и закрытии сессии (монтирование home, лимиты ресурсов, логирование)

Флаги управления определяют, что происходит при успехе или провале модуля. Тут всё принципиально важно — неправильный флаг может обнулить всю вашу настройку безопасности:

  • required — при провале аутентификация в итоге не пройдёт, но PAM продолжит проверять остальные модули
  • requisite — при провале немедленно возвращается ошибка, дальше не идёт
  • sufficient — при успехе аутентификация считается пройденной, если до этого не было provалов с required
  • optional — результат модуля игнорируется, если остальные модули успешны

Посмотрите на типичный /etc/pam.d/common-auth на Ubuntu/Debian:

# /etc/pam.d/common-auth
auth    [success=1 default=ignore]  pam_unix.so nullok
auth    requisite                   pam_deny.so
auth    required                    pam_permit.so

Конструкция [success=1 default=ignore] — это расширенный синтаксис флагов. При успехе pam_unix.so — пропустить 1 модуль (то есть пропустить pam_deny.so). Иначе — проигнорировать (передать управление следующему). Сложновато с первого раза, но логика понятна.

На RHEL/CentOS структура немного другая — там общие правила инклудятся через system-auth и password-auth, которые генерирует authselect.

pam_faillock: блокировка аккаунта при брутфорсе

Это первое, что мы настраиваем на любом новом Linux-сервере. pam_faillock отслеживает неудачные попытки входа и блокирует аккаунт на заданное время. Раньше на этом месте был pam_tally2 — он устарел, в современных системах его нет, используйте только pam_faillock.

На Debian/Ubuntu конфигурация выглядит так. Редактируем /etc/pam.d/common-auth:

# /etc/pam.d/common-auth — добавляем pam_faillock

# Запускаем ПЕРЕД проверкой пароля
auth    required                    pam_faillock.so preauth silent

# Основная проверка пароля
auth    [success=1 default=ignore]  pam_unix.so nullok

# Фиксируем провал
auth    [default=die]               pam_faillock.so authfail

auth    requisite                   pam_deny.so
auth    required                    pam_permit.so

# Снимаем счётчик при успехе
auth    optional                    pam_faillock.so authsucc

Настройки задаём в /etc/security/faillock.conf:

# /etc/security/faillock.conf
deny = 5           # блокировать после 5 неудачных попыток
fail_interval = 300    # в окне 5 минут (300 сек)
unlock_time = 600  # блокировка на 10 минут (600 сек)
silent             # не выдавать ошибку о блокировке (security through obscurity)
audit              # логировать в syslog
even_deny_root     # блокировать и root (осторожно с этим!)

На RHEL 8/9 и производных — проще, через authselect:

# RHEL/CentOS — включаем faillock через authselect
authselect enable-feature with-faillock
authselect apply-changes

# Затем настраиваем /etc/security/faillock.conf как выше

Управление блокировками — несколько команд, которые пригодятся в работе:

# Посмотреть статус блокировок всех пользователей
faillock

# Посмотреть конкретного пользователя
faillock --user john

# Разблокировать пользователя вручную
faillock --user john --reset

# Проверить, что модуль работает
grep "pam_faillock" /var/log/auth.log  # Debian
grep "pam_faillock" /var/log/secure    # RHEL

Важный момент по поводу even_deny_root. Если включить эту опцию и потом ошибиться с паролем root 5 раз подряд — сами себя заблокируете. Обычно эту опцию ставим только на серверах, где есть out-of-band доступ через iDRAC/iLO или физический KVM.

Файлы с данными о неудачных попытках хранятся в /var/run/faillock/ — по одному файлу на пользователя. При перезагрузке они сбрасываются, поскольку /var/run — tmpfs.

pam_pwquality: политика сложности паролей

Если не настроить требования к паролям — пользователи будут ставить «123456» или «qwerty». Без шуток. Мы это видели в реальных компаниях, в том числе в финансовом секторе. pam_pwquality решает эту проблему системно.

Устанавливаем (если нет):

# Debian/Ubuntu
apt install libpam-pwquality

# RHEL/CentOS — обычно уже есть
dnf install libpwquality

В /etc/pam.d/common-password (Debian) или /etc/pam.d/system-auth (RHEL) добавляем:

# /etc/pam.d/common-password
password    requisite    pam_pwquality.so retry=3
password    [success=1 default=ignore]    pam_unix.so obscure use_authtok try_first_pass sha512
password    requisite    pam_deny.so
password    required     pam_permit.so

Основные настройки — в /etc/security/pwquality.conf. Вот конфиг, который мы используем как базовый для большинства клиентов:

# /etc/security/pwquality.conf
minlen = 12         # минимум 12 символов
minclass = 3        # минимум 3 класса из 4 (цифры, прописные, строчные, спецсимволы)
dcredit = -1        # минимум 1 цифра
ucredit = -1        # минимум 1 заглавная буква
lcredit = -1        # минимум 1 строчная буква
ocredit = -1        # минимум 1 спецсимвол
maxrepeat = 3       # не более 3 одинаковых символов подряд
maxclassrepeat = 4  # не более 4 символов одного класса подряд
difok = 5           # минимум 5 отличающихся символов от старого пароля
gecoscheck = 1      # проверка на имя пользователя в пароле
dictcheck = 1       # проверка по словарю
usercheck = 1       # запрет содержания имени пользователя
retry = 3           # 3 попытки ввода нового пароля

Отдельный вопрос — история паролей. pam_pwhistory запрещает повторное использование последних N паролей. Добавляем в секцию password:

# Запрет последних 12 паролей
password    required    pam_pwhistory.so remember=12 use_authtok

История хранится в /etc/security/opasswd. Файл должен быть доступен только root (chmod 600). Проверьте, что он существует, иначе модуль молча пропускает проверку.

Протестировать политику паролей без реального изменения пароля:

# Проверить, пройдёт ли пароль валидацию (не меняет пароль!)
pwscore <<< "тестовый_пароль"
# Вернёт число от 0 до 100. Ниже 50 — слабый пароль

# Детальная проверка
pwmake 64  # сгенерировать случайный пароль с энтропией 64 бит

Двухфакторная аутентификация через pam_google_authenticator

Двухфакторная аутентификация на серверах — это уже не опция, это необходимость. Особенно если сервер доступен из интернета. pam_google_authenticator реализует TOTP (Time-based One-Time Password) — тот самый шестизначный код, который меняется каждые 30 секунд.

Устанавливаем:

# Debian/Ubuntu
apt install libpam-google-authenticator

# RHEL/CentOS (из EPEL)
dnf install epel-release
dnf install google-authenticator

Каждый пользователь генерирует свой ключ. Запускаем от имени пользователя (не root!):

# От имени пользователя, которому нужна 2FA
google-authenticator

Скрипт задаст несколько вопросов. Разумные ответы для большинства случаев:

  • «Do you want authentication tokens to be time-based?» — y (TOTP, не HOTP)
  • «Do you want me to update your ~/.google_authenticator file?» — y
  • «Do you want to disallow multiple uses of the same authentication token?» — y (защита от replay-атак)
  • «By default, a new token is generated every 30 seconds...» — n (±30 секунд достаточно для синхронизации часов)
  • «Do you want to enable rate-limiting?» — y (3 попытки за 30 секунд)

QR-код сканируете в Google Authenticator, Authy, или любом другом TOTP-приложении. Сохраните резервные коды — они понадобятся, если потеряете телефон.

Теперь настраиваем PAM. Для SSH добавляем в /etc/pam.d/sshd:

# /etc/pam.d/sshd
# Добавляем в начало файла
auth    required    pam_google_authenticator.so nullok secret=/home/${USER}/.google_authenticator

Параметр nullok означает: если у пользователя нет файла ~/.google_authenticator — пропустить проверку. Полезно при постепенном внедрении. Когда все настроят 2FA — убираем nullok.

Критически важные настройки в /etc/ssh/sshd_config:

# /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
UsePAM yes

# Требовать И ключ, И одноразовый код
AuthenticationMethods publickey,keyboard-interactive

# Или только пароль + TOTP (без ключа)
# AuthenticationMethods keyboard-interactive

После изменения sshd_config — обязательно проверить конфиг и перезапустить:

sshd -t  # проверка синтаксиса, ошибок быть не должно
systemctl restart sshd

# ОБЯЗАТЕЛЬНО: не закрывайте текущую сессию!
# Откройте новое окно и проверьте, что вход работает
# Иначе рискуете потерять доступ к серверу
Лайфхак из практики: перед включением 2FA убедитесь, что у вас есть резервный способ входа на сервер — iDRAC/iLO консоль или физический доступ. Мы один раз наблюдали, как коллеги заблокировали сами себя после включения 2FA на сервере без IPMI.

pam_limits: ограничения ресурсов через /etc/security/limits.conf

Вот ситуация, которая встречается регулярно: один пользователь или процесс «жрёт» все файловые дескрипторы или процессы на сервере — и система встаёт. pam_limits позволяет задать ресурсные ограничения на уровне аутентификации, ещё до запуска пользовательской сессии.

Модуль pam_limits уже подключён во всех дистрибутивах по умолчанию — в /etc/pam.d/common-session есть строка:

session    required    pam_limits.so

Настройки читаются из /etc/security/limits.conf и файлов в /etc/security/limits.d/. Формат строки:

# формат: domain  type  item  value
# domain: имя пользователя, @группа, * (все), % (для maxlogins только)
# type: soft (мягкий лимит, пользователь может повысить до hard), hard (потолок)
# item: тип ресурса
# value: значение

Реальный пример конфига — то, что мы ставим на серверах с веб-приложениями:

# /etc/security/limits.d/90-custom.conf

# Веб-пользователь — много файловых дескрипторов
www-data    soft    nofile      8192
www-data    hard    nofile      65536

# Разработчики — ограничение на процессы и ядра дампа
@developers soft    nproc       1024
@developers hard    nproc       2048
@developers soft    core        0       # запрет core dumps
@developers hard    core        0

# Глобальные ограничения на открытые файлы
*           soft    nofile      4096
*           hard    nofile      32768

# Запрет многосессионности для обычных пользователей
@users      hard    maxlogins   3

# PostgreSQL — ей нужно много
postgres    soft    nofile      65536
postgres    hard    nofile      65536
postgres    soft    nproc       4096
postgres    hard    nproc       4096

Полный список значений для item:

  • nofile — максимум открытых файловых дескрипторов
  • nproc — максимум процессов
  • memlock — размер заблокированной памяти (в KB)
  • stack — размер стека (в KB)
  • core — максимальный размер core dump (в KB)
  • maxlogins — максимум одновременных сессий
  • priority — приоритет nice (от -20 до 19)
  • rtprio — максимальный приоритет реального времени

Проверить текущие лимиты для пользователя или процесса:

# Текущие лимиты текущего пользователя
ulimit -a

# Лимиты конкретного процесса
cat /proc/1234/limits

# После изменения limits.conf — нужно заново залогиниться
# Изменения применяются только для новых сессий!
Важно: systemd-сервисы по умолчанию игнорируют limits.conf. Для них лимиты задаются через LimitNOFILE=, LimitNPROC= и другие директивы в unit-файле. PAM-лимиты работают только для интерактивных сессий и процессов, запущенных через PAM.

Практические сценарии: реальные конфигурации из проектов

Теория — это хорошо, но давайте посмотрим на конкретные конфиги, которые мы реально применяем.

Сценарий 1: Хардовый сервер с SSH-доступом для команды разработчиков

Задача — доступ по SSH-ключу + TOTP для 8 разработчиков. Блокировка при брутфорсе. Слабые пароли не принимать (для sudo).

# /etc/pam.d/sshd
auth       required     pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth       required     pam_google_authenticator.so
auth       include      common-auth
auth       [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
auth       optional     pam_faillock.so authsucc

account    required     pam_nologin.so
account    include      common-account

session    required     pam_limits.so
session    include      common-session

Сценарий 2: Sudo с требованием повторного пароля и таймаутом

По умолчанию sudo помнит аутентификацию 15 минут. Для чувствительных серверов лучше снизить или вообще убрать кеш:

# /etc/sudoers или /etc/sudoers.d/security
Defaults    timestamp_timeout=5    # кеш 5 минут
Defaults    passwd_tries=3         # 3 попытки ввода пароля
Defaults    badpass_message="Неверный пароль. Попытка залогирована."
Defaults    log_input, log_output   # логировать всё, что делается через sudo
Defaults    iolog_dir=/var/log/sudo-io

# Требовать пароль даже для пользователей в группе sudo
%sudo   ALL=(ALL:ALL) ALL

Сценарий 3: Временный доступ с автоматической блокировкой

Иногда нужно дать временный доступ подрядчику. Используем pam_time для ограничения по времени:

# /etc/security/time.conf
# Формат: services;ttys;users;times
# Разрешить contractor доступ только в будни с 9 до 18
sshd;*;contractor;Wk0900-1800

# /etc/pam.d/sshd — добавляем в секцию account
account    required    pam_time.so

Ещё один полезный модуль — pam_access. Позволяет разрешать или запрещать доступ на основе пользователя, группы и источника (IP, хостнейм, tty):

# /etc/security/access.conf
# Формат: (+|-) : пользователи : источники

# Разрешить root только с localhost
+ : root : LOCAL
- : root : ALL

# Разрешить группу admins с любого адреса
+ : @admins : ALL

# Разрешить всех пользователей с внутренней сети
+ : ALL : 192.168.10.0/24

# Запретить всё остальное
- : ALL : ALL

В /etc/pam.d/sshd добавить в секцию account:

account    required    pam_access.so

Отладка PAM: что делать, когда что-то пошло не так

PAM — то место, где ошибка конфигурации может привести к полной блокировке сервера. Поэтому до любых изменений: резервная копия файлов, открытая запасная SSH-сессия.

Где искать логи? Зависит от дистрибутива:

# Debian/Ubuntu
tail -f /var/log/auth.log

# RHEL/CentOS
tail -f /var/log/secure

# Systemd — все системные логи
journalctl -u sshd -f
journalctl -t sudo -f

# Поиск конкретных провалов за сегодня
grep "authentication failure" /var/log/auth.log | grep "$(date +%b\ %e)"

Полезный инструмент для отладки — pamtester. Позволяет проверить конфигурацию PAM для любого сервиса без реального входа:

# Установка
apt install pamtester  # Debian
# Или собрать из исходников

# Тест аутентификации пользователя через сервис sshd
pamtester sshd john authenticate

# Тест смены пароля
pamtester sshd john chauthtok

Если что-то сломалось и вы заблокированы — несколько путей восстановления:

  • Если есть другая открытая SSH-сессия — используйте её для исправления конфига
  • Консоль через iDRAC/iLO/KVM — всегда имейте этот доступ на продакшне
  • Single-user mode (recovery mode) — загрузка с параметром single или init=/bin/bash
  • Live CD/USB — примонтировать корневую FS и исправить конфиг

Чтобы быстро найти синтаксические ошибки в конфигах PAM:

# Проверить, что все модули PAM существуют
for f in /etc/pam.d/*; do
    echo "=== $f ===";
    awk '{if ($3 != "" && $3 !~ /^#/ && $1 !~ /^#/) print $3}' "$f" | while read mod; do
        [ -f "$mod" ] || echo "MISSING: $mod"
    done
done

# Список всех доступных PAM-модулей
ls /lib/x86_64-linux-gnu/security/  # Debian 64-bit
ls /lib64/security/                  # RHEL

Чеклист настройки PAM для production-сервера

Мы дошли до финала. Собираем всё в практический чеклист, который используем при приёмке нового Linux-сервера в эксплуатацию:

  • Настроен pam_faillock: deny=5, unlock_time=600, fail_interval=300
  • Настроен pam_pwquality: minlen=12, minclass=3, dictcheck=1
  • История паролей через pam_pwhistory: remember=12
  • Максимальный срок действия пароля: chage -M 90 username
  • Минимальный срок (защита от обхода истории): chage -m 1 username
  • pam_limits подключён в common-session, настроены limits.conf
  • Для серверов с SSH из интернета — 2FA через pam_google_authenticator
  • Для критичных серверов — pam_access с белым списком IP
  • Логи auth.log/secure мониторятся (Zabbix, Prometheus+Loki, или хотя бы logwatch)
  • Резервный доступ через IPMI/iDRAC/физику задокументирован

Проверить итоговый статус паролей пользователей:

# Сводка по всем аккаунтам
awk -F: '$2 ~ /^\$/ {print $1}' /etc/shadow | while read u; do
    echo -n "$u: "
    chage -l "$u" | grep -E "Password expires|Account expires|Last password"
done

# Найти аккаунты без срока истечения пароля
awk -F: '$2 ~ /^\$/ {print $1}' /etc/shadow | while read u; do
    exp=$(chage -l "$u" | grep "Password expires" | awk '{print $NF}')
    [ "$exp" = "never" ] && echo "NO EXPIRY: $u"
done

PAM — мощный инструмент. Потратьте день на его нормальную настройку, и сэкономите недели на расследовании инцидентов. На практике именно некорректно настроенная аутентификация — точка входа в большинстве компрометаций Linux-серверов, которые мы разбирали за последние два года.

Часто задаваемые вопросы

Что такое PAM в Linux и зачем он нужен?
PAM (Pluggable Authentication Modules) — это фреймворк аутентификации в Linux, который позволяет гибко настраивать методы проверки подлинности без изменения самих приложений. SSH, sudo, login — все они используют PAM. Модульная архитектура позволяет добавлять 2FA, блокировку по неудачным попыткам, политики паролей и ограничения ресурсов через простые конфигурационные файлы.
Как настроить блокировку аккаунта после нескольких неудачных попыток входа?
Используйте модуль pam_faillock. В /etc/pam.d/common-auth добавьте строки с auth required pam_faillock.so preauth silent и auth required pam_faillock.so authfail. В /etc/security/faillock.conf задайте deny=5 (блокировка после 5 попыток), unlock_time=600 (разблокировка через 10 минут), fail_interval=300 (окно в 5 минут). Разблокировать вручную: faillock --user username --reset.
Как добавить двухфакторную аутентификацию через Google Authenticator?
Установите libpam-google-authenticator, запустите google-authenticator от имени каждого пользователя для генерации ключа. В /etc/pam.d/sshd добавьте строку auth required pam_google_authenticator.so. В /etc/ssh/sshd_config задайте ChallengeResponseAuthentication yes и AuthenticationMethods publickey,keyboard-interactive. После перезапуска sshd вход потребует и SSH-ключ, и одноразовый код.
Чем pam_pwquality отличается от pam_cracklib?
pam_pwquality — современная замена pam_cracklib, поставляется в пакете libpam-pwquality. Проверяет длину, классы символов, похожесть на старый пароль, наличие в словарях. Конфигурируется через /etc/security/pwquality.conf. pam_cracklib устарел, на современных системах его лучше не использовать.
Как через PAM ограничить ресурсы для пользователей?
Модуль pam_limits читает настройки из /etc/security/limits.conf и /etc/security/limits.d/. Формат: username type item value. Например: @developers soft nofile 8192, @developers hard nofile 16384 — лимиты на открытые файлы. Применяется автоматически при входе пользователя через любой PAM-сервис.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈️ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Подпишитесь на рассылку ITfresh

Каждую неделю мы выпускаем практические гайды для руководителей IT и системных администраторов. Это не просто теория! Здесь вы найдёте всё: безопасность, 1С, миграции, резервные копии и проверенные лайфхаки из наших реальных проектов.

Письмо придёт в течение минутыНе нашли его во «Входящих» — загляните в папку «Спам» или «Промоакции» и нажмите «Не спам». Так все следующие выпуски будут приходить прямо в основную почту.
Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.