Автентифікатор показує новий шестизначний код, VPN його відхиляє, а той самий код бездоганно перевіряється, коли ви тестуєте його з власної оболонки. Ця різниця — уся історія. Модуль PAM, який не може відкрити секрет реєстрації, повертає помилку, що виглядає точно так само, як неправильний код, і середовище служби, яке приховує домашні каталоги, — часта причина. Перш ніж послаблювати будь-які права, визначте, у якій із трьох ситуацій ви перебуваєте.

Яка з трьох помилок це?

Перша — секрет, який модуль взагалі не може прочитати. Друга — секрет, який він може прочитати, але не може оновити. Третя — код, який справді неправильний, зазвичай через дрейф годинника або повторно використане значення.

Розділіть їх, прочитавши журнал служби та системний журнал автентифікації для однієї невдалої спроби, потім підтвердьте, яку службу PAM завантажує плагін і який рядок модуля використовує ця служба. Загальне повідомлення про помилку автентифікації їх не розрізняє, як і успішний ручний тест, бо ваша оболонка — не середовище служби.

Подання файлової системи в юніті — звичайний винуватець, коли збоїть лише служба.

systemctl show -p ProtectHome -p ProtectSystem -p ReadWritePaths [email protected]
ls -l /var/lib/vpn-otp/*/.google_authenticator 2>/dev/null | head -n 20

Варіант A: винести секрет із домашнього каталогу

Коли служба приховує /home, а ви хочете зберегти цей захист, зберігайте секрет там, де вона може його бачити. Модуль приймає шлях secret= і обліковий запис user=, який виконує файлові операції, що дозволяє центральному сховищу обслуговувати багато ідентичностей.

Це охайний варіант, і він потребує найбільшої обережності, бо спільне сховище робить один каталог межею безпеки кожного облікового запису.

auth required pam_google_authenticator.so secret=/var/lib/vpn-otp/${USER}/.google_authenticator user=vpn-otp

Перевірте три речі, перш ніж довіряти йому: обліковий запис існує, робочий процес модуля може перемкнутися на нього, і файли належать йому з обмежувальними режимами. Не використовуйте ~ або шлях із домашньою змінною разом із user= і не вимикайте перевірки власності модуля, щоб шлях запрацював. Збережіть етап пароля та решту стека недоторканими.

Варіант B: залишити файл і відкрити шлях

Якщо секрет має залишитися в домашньому каталозі користувача, юніту потрібне подання, яке включає цей єдиний каталог, не розкриваючи всіх домашніх каталогів на хості. Drop-in може додати вузько обмежене bind-монтування під ізольованим домашнім каталогом.

Це зберігає власність за користувачем як модель, ціною зміни юніта, яку треба переглядати щоразу, коли змінюється пісочниця.

Дві межі легко пропустити. Шлях лише для читання, доданий під каталогом, який приховує пісочниця, не розкриває його, бо батьківського каталогу просто немає. І монтування має бути записуваним, якщо модуль повинен оновлювати стан, що вводить наступний варіант. Пишіть drop-in окремим файлом, а не редагуйте спакований юніт у /usr/lib, щоб оновлення пакета не скасувало його мовчки.

Варіант C: зберегти пісочницю і виправити записи стану

Читання секрету — лише половина автентифікації. Модуль може перезаписувати відомості про зсув часу, захист від повтору або лічильник, і файл, що пройшов перевірку читання, усе ще може не записатися.

Цей збій виглядає як поганий код при наступній спробі, а не при цій, тому його плутають із дрейфом годинника.

Дайте йому власний записуваний каталог і спрямуйте туди шлях секрету, замість робити записуваним увесь домашній каталог. Підтвердьте власника каталогу, вільне місце файлової системи та чи обмежує юніт записи в іншому місці. Потім перевірте два послідовні входи, бо другий доводить шлях запису, а перший — лише читання.

Перевіряйте як служба, а не як ви самі

Кожна важлива перевірка має виконуватися всередині пісочниці юніта з ідентичністю юніта.

Команда, успішна від root, повідомляє, що файл існує, і більше нічого. Вхід через справжню службу повідомляє, чи може модуль прочитати секрет, використати його й записати назад потрібне.

Насамкінець збережіть вимогу недоторканою. Додавання варіанта з нульовим паролем, прийняття збоїв лише для читання або вилучення пісочниці — усе це прибрало б симптом зміною політики. Користувач, зобов'язаний пред'явити код, і далі має отримувати відмову, коли секрет недоступний.

Схожі статті