Аутентификация PAM работает вручную, но не работает как служба OpenVPN
Вход через PAM, который работает из root-оболочки и не работает под systemd, указывает на helper, а не на пароль. Разделите привилегии, доступ к файлам и SELinux.
Аутентификация через PAM может проходить, когда вы запускаете клиент вручную, и завершаться ошибкой AUTH_FAILED, как только systemd запускает тот же профиль. Пароль между этими запусками не меняется; меняется набор ограничений вокруг процесса, который задаёт вопрос PAM. PAM отвечает через helper, чья способность менять собственные учётные данные — ровно то, что убирает усиленный unit. Найдите этот helper и границу, которая ему нужна, прежде чем трогать список возможностей.
unix_chkpwd — это двоичный файл, который отвечает на вопрос PAM
При локальной аутентификации по паролю pam_unix редко сам читает файл хешей. Он запускает unix_chkpwd, который дистрибутивы устанавливают с setuid root или setgid shadow, чтобы один пароль можно было проверить от имени процесса, которому незачем читать /etc/shadow. Уберите возможность получить эту идентичность — и helper не сможет завершить проверку, поэтому модуль вернёт обычную ошибку аутентификации.
Тогда в каждом журнале, который видит клиент, сбой выглядит как проблема с учётными данными. В этом и ловушка: клиент сообщает то, что ему сказал PAM, а PAM сообщает лишь то, что стек сказал «нет». Запуск helper вручную от root тоже ничего не доказывает, потому что задействует путь привилегий, который служба никогда не использует. Прочитайте unit, который systemd действительно загрузил, а затем системный журнал о сделанной попытке. Эти два взгляда отделяют проблему песочницы от проблемы неверного пароля.
Прочитайте unit, прежде чем читать журнал паролей
Поставляемый unit может нести drop-in, который вы не писали, а действующая конфигурация — это результат слияния. Напечатайте unit так, как его видит systemd, вместе с настройками песочницы, от которых зависит, может ли helper повысить собственные привилегии. На этом этапе достаточно осмотра только для чтения.
systemctl cat [email protected]
systemctl show [email protected] -p User -p Group -p CapabilityBoundingSet -p AmbientCapabilities -p NoNewPrivileges
journalctl -u [email protected] -bПервая команда показывает, откуда берутся unit и его drop-in, что важно, потому что переопределение, добавленное месяцы назад, живёт дольше памяти о том, зачем оно существует. Вторая печатает значения песочницы, от которых зависят два следующих раздела.
Сравните увиденное с работающим узлом той же дистрибуции и версии. Разница в User, CapabilityBoundingSet или NoNewPrivileges — конкретная зацепка; разница в пояснительных комментариях — нет. Запишите значения, прежде чем что-либо менять, потому что более позднее сравнение с движущейся целью ничего не доказывает. Если служба работает под непривилегированной учётной записью с пустым ограничивающим набором, helper почти ничего не может сделать.
Преобразование учётных данных, доступ к файлам и политика — это три границы
Начните с того, что происходит при exec. Двоичный файл setuid или файл с file capabilities вызывает преобразование учётных данных, поэтому итоговая идентичность не является продолжением вызывающего. Ограничивающий набор ограничивает то, что такой файл может получить, а NoNewPrivileges полностью блокирует получение setuid, setgid и file capabilities. Любое из этих трёх может остановить helper, оставив нетронутыми все остальные функции службы.
Далее отделите широкий обход дискреционных проверок от узкого доступа на чтение. CAP_DAC_OVERRIDE пропускает дискреционные проверки почти везде, тогда как CAP_DAC_READ_SEARCH охватывает чтение и обход каталогов со своими дополнительными полномочиями. Это разные инструменты с разным радиусом поражения, и ни один из них не является способом записать «пусть PAM читает файл shadow».
Наконец, спросите, разрешает ли обязательная политика это действие вообще. Возможность Linux не отменяет SELinux, и её наличие ничего не доказывает о правиле принудительного контроля типов. Рассматривайте отказ в доступе к файлу и отказ в возможности как разные свидетельства, потому что они называют разные исправления и часто разных ответственных. Читайте каждое поле записи, а не одно слово denied. Какая исполняемая программа выполнила действие, в каком домене она работала, какого типа цели коснулась, какой класс объекта был задействован и какое разрешение отказала политика — каждый из этих вопросов сужает ответ по-своему.
Вытащите отказ из журнала аудита
На узле в режиме enforcing журнал аудита — единственное место, где фиксируется отказ. Запросите последние события и читайте их относительно метки времени неудачного входа, а не относительно времени начала расследования.
ausearch -m AVC,USER_AVC -ts recentПустой результат не является доказательством невиновности. Он означает либо что аудит не собирает данные, либо что ваше окно пропустило попытку, и обе возможности нужно исключить, прежде чем исключать политику.
Руководство Red Hat по устранению неполадок SELinux ставит проверки меток и конфигурации перед генерацией разрешающих правил, и для этой проблемы это тоже правильный порядок. Неверно помеченный двоичный файл helper и пробел в политике дают похожие отказы, но требуют разных исправлений. Генерация разрешающего правила для ошибки метки скрывает дефект и оставляет следующему обновлению пакета возможность вернуть его. Подтвердите метку установленного helper, прежде чем писать какую-либо политику.
Докажите изменение одним принятым и одним отклонённым входом
Измените только ту границу, которую вы продемонстрировали, затем проверьте оба исхода. Учётная запись, которая должна аутентифицироваться, обязана успешно войти, а учётная запись с неверным паролем должна по-прежнему получать отказ. Изменение, после которого проходит каждая попытка, убрало аутентификацию, а не починило её.
Выполните реальную попытку подключения и сразу после неё прочитайте журнал. Строка, доказывающая исправление, — это запись pam_unix(openvpn:auth) для этой попытки: там должен быть успех аутентификации, и ни одна запись AVC не должна приходиться на ту же секунду.
journalctl -u [email protected] -n 30 --no-pager
ss -tnp | grep openvpnРаботающему туннелю нужно и переподключение, потому что изменения песочницы ломают второе соединение чаще первого. Проверьте установленный сокет после переподключения и убедитесь, что его по-прежнему обслуживает тот же unit.