Политика паролей
Проверяй действием: смена пароля от имени самого пользователя (su -
alice -c passwd). Смена от root без enforce_for_root пройдёт с любым
паролем и ничего не докажет.
Стек модулей в /etc/pam.d: решает, пускать ли пользователя, какой пароль принять и когда заблокировать вход.
grep -v '^#' /etc/pam.d/common-auth | grep .
стек проверки входа
sudo pam-auth-update --enable pwquality
включить pwquality
echo 'Lab-Pass-2026' | pwscore
оценить пароль заранее
sudoedit /etc/security/pwquality.conf
правила паролей
sudo faillock --user alice
неудачные входы alice
sudo faillock --user alice --reset
снять блокировку
sudo journalctl -t su | grep -i fail
отказы su в журнале
PAM (Pluggable Authentication Modules) — библиотека, которой
программы поручают проверку пользователя. login, su, sudo, sshd и
passwd сами пароль не сверяют: они зовут PAM, а PAM читает файл с именем
программы в /etc/pam.d/ и проходит по его модулям. Чтобы поменять
политику — длину пароля, блокировку после неудач, — меняют стек модулей,
программы трогать не нужно. Файлы читаются при каждом входе, правка
действует сразу.
Файл программы обычно подключает общие файлы строкой @include:
Так же устроены sudo и sshd: правка common-auth меняет проверку
пароля у всех сразу.
Каждая строка начинается с типа — к какому этапу входа она относится:
| Тип | Когда идёт | Модули на машине |
|---|---|---|
auth |
проверка, кто ты: пароль | pam_unix, pam_faillock |
account |
можно ли этой учётной записи войти сейчас: срок, блокировка | pam_unix, pam_nologin |
password |
смена пароля | pam_pwquality, pam_unix |
session |
что сделать при входе и выходе | pam_limits, pam_umask, pam_systemd |
Вход по ключу в sshd пропускает стек auth: ключ сверяет сам sshd.
Стеки account и session идут и при входе по ключу.
Тип, флаг управления, модуль и его параметры. Модули идут сверху вниз, и флаг говорит, что делать с их ответом:
| Флаг | Модуль ответил «да» | Модуль ответил «нет» |
|---|---|---|
required |
дальше | отказ, но стек доходит до конца |
requisite |
дальше | отказ сразу |
sufficient |
успех сразу, если раньше отказа не было | дальше |
optional |
важен, только если модуль в стеке один | — |
[success=N default=ignore] |
пропустить N следующих строк | не учитывать, дальше |
Стек auth на машине:
Верный пароль: pam_unix перескакивает через одну строку — pam_deny — к
pam_permit, вход разрешён. Неверный: следующая строка pam_deny и
отказ. Порядок строк здесь — часть логики: строка, вставленная между
pam_unix и pam_deny, меняет, куда ведёт success=1.
В Ubuntu файлы common-* собирает pam-auth-update из профилей в
/usr/share/pam-configs/. На машине их пять: capability, mkhomedir,
pwquality, systemd, unix. Профиль — это строки и место, куда их
вставить:
На учебной машине профиль выключен. sudo pam-auth-update --enable
pwquality включает его и пересобирает common-password:
| Тип | Флаг | Модуль и параметры |
|---|---|---|
password |
requisite |
pam_pwquality.so retry=3 |
password |
[success=1 default=ignore] |
pam_unix.so obscure use_authtok try_first_pass yescrypt |
password |
requisite |
pam_deny.so |
password |
required |
pam_permit.so |
Первая строка — новая. use_authtok у pam_unix — взять пароль, который
уже проверил pam_pwquality, и не спрашивать снова.
Если common-* правили руками, pam-auth-update сначала спрашивает
Override local changes to /etc/pam.d/common-*?. Ответ yes пересоберёт
файлы из профилей и сотрёт ручные строки, no оставит файлы как есть — и
профиль не включится:
pam_pwquality проверяет новый пароль при смене. Правила
— в /etc/security/pwquality.conf или в файлах
/etc/security/pwquality.conf.d/*.conf (каталога на машине нет, его
создают mkdir). В pwquality.conf машины всё закомментировано, и
действуют значения по умолчанию:
| Параметр | Что значит | По умолчанию |
|---|---|---|
minlen |
минимальная длина | 8 |
minclass |
сколько классов из четырёх: строчные, заглавные, цифры, прочие | 0 |
dcredit, ucredit, lcredit, ocredit |
-N — нужно хотя бы N цифр, заглавных, строчных, прочих |
0 |
maxrepeat |
сколько одинаковых символов подряд можно | 0 — без проверки |
dictcheck |
сверка со словарём | 1 |
enforce_for_root |
отказывать и root | выключен |
Положительное значение *credit работает иначе: каждый такой символ, до N
штук, засчитывается в длину дважды. retry=3 — параметр модуля в строке
pam.d: сколько раз passwd переспросит.
Пароль заранее проверяет pwscore. Он читает тот же pwquality.conf, но
в PAM не смотрит — правило видно в pwscore ещё до pam-auth-update.
Ответ — оценка от 0 до 100 или причина отказа с кодом 1:
С minlen = 12, minclass = 3 и dcredit = -1 отказы такие:
| Пароль | Ответ |
|---|---|
labpassword2026 |
The password contains less than 3 character classes |
Kd8#vq2Lm9 |
The password is shorter than 12 characters |
Labpassword-xx |
The password contains less than 1 digits |
aaaaaaaaaaaaB1 |
… it does not contain enough DIFFERENT characters |
Kd8#vq2Lm9Zx |
36 — принят |
passwd от пользователя печатает те же причины после BAD PASSWORD: и
сдаётся после трёх попыток:
Root без enforce_for_root получает то же BAD PASSWORD, но пароль
меняется: sudo passwd deploy печатает предупреждение и password updated
successfully, chpasswd — только предупреждение и код 0. С
enforce_for_root отказ получает и root — chpasswd выходит с кодом 1 и
password not changed.
pam_faillock считает неудачные входы. Профиля для него в
pam-configs нет — его вписывают в common-auth руками, тремя строками
вокруг pam_unix:
и строкой account required pam_faillock.so в конец common-account.
| Строка | Что делает |
|---|---|
preauth |
до пароля: учётная запись заблокирована — отказ сразу |
authfail |
после неверного пароля: запись в счётчик и отказ |
authsucc |
после верного: счётчик обнуляется, вход разрешён |
account |
после входа без пароля, по ключу: тоже обнуляет счётчик |
Верный пароль перескакивает authfail (success=1) и попадает на
authsucc. Бывает вариант без authsucc: у pam_unix стоит success=2,
и верный пароль перескакивает сразу authfail и pam_deny. Счётчик тогда
обнуляет только строка account, поэтому без неё он растёт и после
удачных входов. Настройки — в /etc/security/faillock.conf; на машине там всё
закомментировано: deny = 3 неудачи, unlock_time = 600 секунд,
fail_interval = 900 — окно, в котором считаются неудачи. Root не
блокируется, пока не включён even_deny_root.
Три неверных su - deploy подряд и вход с верным паролем:
Пароль больше не спрашивают — preauth отказал до него. В журнале:
Счётчики — файлы /var/run/faillock/<пользователь>. Каталог /run живёт
в памяти, и перезагрузка их стирает. Снять блокировку раньше —
sudo faillock --user deploy --reset.
Вход по ключу через sshd заблокированную учётную запись пускает: стек
auth не идёт, а строка account обнуляет счётчик.
Проверяй действием: смена пароля от имени самого пользователя (su -
alice -c passwd). Смена от root без enforce_for_root пройдёт с любым
паролем и ничего не докажет.
Файл заменяется целиком — сверь его прежний стек с этим
(grep -v '^#' /etc/pam.d/common-auth | grep .): строки, которых тут
нет, перенеси. Пробелы вместо табуляций PAM читает так же. Проверка —
три неверных su - alice, затем sudo faillock --user alice
и вход с верным паролем: он должен получить отказ. После —
sudo faillock --user alice --reset.
sudo -i и не закрывай до конца проверки.sudo cp /etc/pam.d/common-auth /root/.su - alice, ssh alice@localhost.grep pwquality /etc/pam.d/common-password пуст — модуля в стеке нет:
sudo pam-auth-update --enable pwquality. Модуль есть, а пароль ставит
root — без enforce_for_root он получает только предупреждение
BAD PASSWORD, и пароль меняется.
Причина — в тексте после двоеточия: shorter than 12 characters —
minlen, less than 3 character classes — minclass, less than 1
digits — dcredit, dictionary check — dictcheck. Тот же ответ даст
pwscore — им удобно подобрать пароль.
pam_faillock насчитал deny неудач за fail_interval. Кто и откуда
ошибался — sudo faillock --user <имя> и journalctl -t su, journalctl
-u ssh. Блокировка снимется сама через unlock_time или сразу —
faillock --user <имя> --reset.
pam_faillock нет в common-auth или стоят не там: authfail
должен идти сразу за pam_unix, до pam_deny.even_deny_root выключен.auth с паролем не идёт вовсе.common-* правили руками, и pam-auth-update отказывается их
пересобирать — профиль не включается. --force пересоберёт файлы из
профилей и сотрёт ручные строки, например pam_faillock: впиши их снова
после --force.
Опечатка в строке с required или requisite закрывает вход по паролю
всем: su, login, sshd по паролю и sudo с паролем идут через
common-auth. Держи открытую root-сессию, пока новый вход не проверен.
С ним блокируется и root: несколько неверных паролей — и на сервер не
войти, пока не пройдёт unlock_time. Включай, только если есть другой
путь внутрь — консоль или вход по ключу.
/etc/shadow.UsePAM, вход по паролю и по ключу.su и sshd в журнале.Есть неточность? Сообщить об ошибке в статье