Подключение RADIUS к OpenVPN: плагин или скрипт-хук?
Старый плагин RADIUS привязан к сборке сервера, под которую он скомпилирован. Его заменяет хук auth-user-pass-verify, но доверие переносится в ваш скрипт.
Плагин до сих пор советуют в обсуждениях, которые старше нынешних сборок, а на сервере, собранном вчера, он падает при загрузке. Это не ошибка конфигурации, которую можно исправить путём. Плагин и скрипт-хук решают одну и ту же задачу на разных уровнях, и переход с одного на другой меняет то, что нужно установить, что работает с правами сервера и что на самом деле говорит неудачный вход.
Миф: плагин — это поддерживаемый путь
Плагин — это разделяемый объект, загружаемый в процесс OpenVPN, поэтому он должен соответствовать интерфейсу, который этот процесс предоставляет. Сборки меняются, упаковка меняется, и библиотека, собранная под старый интерфейс, просто отказывается загружаться. Ничто в конфигурации сервера не может закрыть этот разрыв, поэтому совет «просто установите radiusplugin» заканчивается сервером, который не запускается.
Скрипт-хук стоит вне процесса. OpenVPN запускает программу, передаёт ей учётные данные и читает вердикт. Именно это разделение позволяет ему переживать обновления, и оно же делает его вашей ответственностью так, как плагин ею никогда не был.
Ни один из подходов не безопаснее по своей конструкции. Один исполняет чужой код внутри демона; другой исполняет ваш код рядом, с учётными данными в руках. Правильный вопрос — какой из этих двух рисков вы действительно можете эксплуатировать.
Что связывал плагин
Плагин нёс собственный файл конфигурации с хостом RADIUS, общим секретом, числом повторов и тайм-аутом, а конфигурация сервера ссылалась на него одной строкой. Обработка учётных данных оставалась внутри серверного процесса, то есть пароль никогда не пересекал границу процесса, которую администратор должен был защитить.
Ценой была связанность. Каждое обновление OpenVPN грозило несовместимым интерфейсом, а каждый дистрибутив, пересобирающий пакет, рисковал выпустить библиотеку, которая больше не подходит. Когда это происходит, сбой громкий и мгновенный, и это единственная милость этой конструкции.
Если такой плагин всё ещё загружается на вашей сборке, возможно, он и есть меньшая операционная поверхность. Подтвердите интерфейс, под который он собран, держите его привязанным к проверенной сборке и считайте любое обновление изменением, требующим полного теста входа, а не рутинным обновлением пакета.
Чему скрипт-хук действительно доверяет
Хук настраивается с auth-user-pass-verify и механизмом доставки: переменными окружения или временным файлом. В форме окружения OpenVPN требует script-security 3 — документированный уровень, разрешающий показывать пароль скриптам. Этот уровень — намеренное ослабление значения по умолчанию, и к нему следует относиться как к разрешению с приложенным обоснованием.
Всё, чего касается скрипт, наследует это доверие. Он должен принадлежать root, не быть записываемым для группы или других, указываться абсолютным путём и не иметь места, где недоверенное значение попадает в оболочку. Заключайте каждую переменную в кавычки, отвергайте неожиданные символы и никогда не стройте команду из переданного имени пользователя. Скрипт, работающий от root при каждой попытке входа, заслуживает одной проверки именно на эти четыре свойства.
ls -l /usr/local/sbin/radius-auth.sh
stat -c '%U %a' /usr/local/sbin/radius-auth.sh
Форма доставки файлом обходит проблему наследования окружения и передаёт учётные данные скрипту через временный файл с ограниченными правами. Если ваш клиент это поддерживает, обычно это лучший вариант по умолчанию, хотя при сбое появляется ещё один объект для очистки.
Коды выхода решают, будет ли отказ открытым
Код выхода скрипта — это вердикт: ноль принимает, не ноль отклоняет. Схема, создающая проблемы, — это shell-скрипт, который принимает только когда в ответе RADIUS есть определённый токен принятия, а для всего остального возвращает отказ, потому что так три разных события сливаются в один ответ. Неверный пароль, недоступный сервер и искажённый ответ становятся одним и тем же отказом.
Разделяйте эти случаи в скрипте, даже если хук умеет возвращать только «принять» или «отклонить». Записывайте результат бэкенда отдельно, подавайте сигнал при тайм-аутах и ошибках транспорта и делайте в мониторинге очевидным, когда аутентификация падает из-за недоступности сервиса, а не из-за опечаток пользователей.
Две привычки сохраняют остальное разумным. Если RADIUS — авторитет, он должен быть единственным местом проверки пароля, потому что теневая таблица создаёт два ответа на один вопрос, а второй — поверхность атаки, за которой никто не следит. И помните, что хук вызывается заново при каждой попытке, поэтому медленный скрипт вместе с нетерпеливым клиентом становится усилителем подбора паролей, если не добавить задержку или политику на стороне RADIUS.
Чем вы жертвуете, когда сертификат исчезает
Многие развёртывания такой формы полностью отключают проверку клиентского сертификата, оставляя имя пользователя и пароль как всё заявление клиента. Вместе с этой настройкой исчезает идентичность на основе сертификата. Канал остаётся зашифрованным, но единственное, что называет клиента, — это вердикт RADIUS. Всё ниже по потоку, что раньше опиралось на субъект сертификата, теперь должно опираться на имя пользователя.
Сохраняйте защиту канала управления, чтобы неаутентифицированный партнёр не мог исследовать или затапливать рукопожатие, и используйте username-as-common-name, когда конфигурация для каждого пользователя зависит от общего имени. Управляемые шлюзы часто решают это иначе, завершая аутентификацию по сертификату на шлюзе, который говорит EAP-TLS с RADIUS, и в этом случае ни одна из этих серверных директив не действует. Копируйте модель, которую документирует ваша платформа, а не модель соседнего продукта. Важные директивы различаются настолько, что их смешение даёт конфигурацию, которая разбирается и затем никого не аутентифицирует.