Про OpenVPN написано много гайдов, в том числе и про авторизацию через Active Directory. Большинство из них сводится к использованию LDAP, подхода с использованием Kerberos, оформленного в полноценную статью, я не нашел. Впрочем, чего-то нового тут изобретено не будет, я лишь скомпилировал уже сделанное до меня, PAM отлично работает с Kerberos, а OpenVPN имеет нативный плагин для PAM. Также я решил отказаться от пользовательских сертификатов и советы, где рекомендуют просто всем пользователям выдавать один сертификат, меня не устроили, поэтому было найдено другое решение, работающее на всех клиентах.

В своем случае я использовал Centos 7 в связке с sssd. Впрочем, ничто не мешает использовать winbind. Главное, иметь машину в домене и тикет Kerberos. Я не буду писать о том, как это делается, т.к. не скажу ничего нового, в сети много хороших мануалов.
Будет необходимо сменить настройки
Следующих настроек должно быть достаточно:
В случае с sssd не забываем, кроме всего прочего, что в
Насчет winbind мне сложно что-то сказать, я его не использовал.
Конечная цель получить правильный результат от getent. Проверяем, что машина может получать сведения о доменных пользователях и группах:
Теперь необходимо создать свой PAM модуль. Чтобы не использовать системный access.conf, сделаем отдельный файл, откуда будет читаться группа доступа. Я не так хорош в модулях PAM, поэтому не могу сказать, нужны ли все строки в примере, который будет ниже. В общем-то, нас интересует только строка
Самый простой вариант, взять, например, модуль login и добавить в него нужную строку. Что и было сделано.
Получаем:
Кладем его в
В
Осталось объяснить OpenVPN, что ему необходимо использовать PAM. Кладем в конфигурацию сервера следующие строки:
В разных дистрибутивах пути могут отличаться! Проверьте наличие файла по пути, либо используйте find.
Использование параметра username-as-common-name связано с тем, что в ином случае после выполнения auth-user-pass у клиента, серверу отправится имя, указанное в сертификате.
В конфиге клиента необходимо добавить строку
На этом настройка закончена, можно тестировать.
Теперь у нас есть авторизация через домен и сертификат пользователя бесполезен, отказаться от него кажется логичным решением. Но мобильные клиенты имеют с этим проблемы, просто не принимая такую конфигурацию, а десктопные хоть и работают, но злостно ругаются. Во-первых, изменим конфигурацию на сервере, чтобы он перестал требовать сертификат.
Далее в конфигурацию клиентов добавляем
Все, теперь клиенты не будут ругаться на сертификат. Забавно, что этот параметр спрятан в разделе вопросов-ответов для iOS. Я не тестировал на iOS, но Android, а так же MacOS (бета клиент) и Windows принимают эти настройки на ура. Только сторонний OpenVPN-клиент на Android пока этого не умеет (к моменту написания статьи уже могли поправить).

Немного об NSS
В своем случае я использовал Centos 7 в связке с sssd. Впрочем, ничто не мешает использовать winbind. Главное, иметь машину в домене и тикет Kerberos. Я не буду писать о том, как это делается, т.к. не скажу ничего нового, в сети много хороших мануалов.
Будет необходимо сменить настройки
/etc/nsswitch.conf
, если этого не было сделано ранее. В зависимости от того, какой модуль использовался, нужно вместо module_name вписать sss или winbind соответственно. Описание параметров можно прочесть с помощью man nsswitch.conf
.Следующих настроек должно быть достаточно:
passwd: files module_name
shadow: files module_name
group: files module_name
В случае с sssd не забываем, кроме всего прочего, что в
/etc/sssd/sssd.conf
в блоке [sssd] должен быть упомянут nss:services = nss, pam
Насчет winbind мне сложно что-то сказать, я его не использовал.
Конечная цель получить правильный результат от getent. Проверяем, что машина может получать сведения о доменных пользователях и группах:
> getent passwd kanlas
kanlas:*:14123583:1257570:Kanlas Kanlasovich:/home/kanlas@example.com:/bin/bash
> getent group VPN
vpn:*:13821391:kanlas,igor,marina
Примечание
Если вы использовали sssd и данные о пользователе получаются только с указанием полного имени (т.е. kanlas@example.com), добавьте в sssd.conf в блоке домена параметр
use_fully_qualified_names = False
Настраиваем PAM
Теперь необходимо создать свой PAM модуль. Чтобы не использовать системный access.conf, сделаем отдельный файл, откуда будет читаться группа доступа. Я не так хорош в модулях PAM, поэтому не могу сказать, нужны ли все строки в примере, который будет ниже. В общем-то, нас интересует только строка
account required pam_listfile.so onerr=fail item=group sense=allow file=/etc/openvpn/auth/access-groups
.Самый простой вариант, взять, например, модуль login и добавить в него нужную строку. Что и было сделано.
Получаем:
#%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth substack system-auth
auth include postlogin
account required pam_listfile.so onerr=fail item=group sense=allow file=/etc/openvpn/auth/access-groups
account include system-auth
password include system-auth
session required pam_selinux.so close
session required pam_loginuid.so
session optional pam_console.so
session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include system-auth
session include postlogin
-session optional pam_ck_connector.so
Кладем его в
/etc/pam.d
, назвав по своему усмотрению.В
/etc/openvpn/auth/access-groups
, указанный в модуле, у нас и будет записана группа доступа, можете указать свой путь при желании. Нужно будет указать имя группы (Common Name) с доменом. В моем случае я записал туда VPN@example.com.Осталось объяснить OpenVPN, что ему необходимо использовать PAM. Кладем в конфигурацию сервера следующие строки:
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so имя_модуля_pam
username-as-common-name
В разных дистрибутивах пути могут отличаться! Проверьте наличие файла по пути, либо используйте find.
Использование параметра username-as-common-name связано с тем, что в ином случае после выполнения auth-user-pass у клиента, серверу отправится имя, указанное в сертификате.
В конфиге клиента необходимо добавить строку
auth-user-pass
На этом настройка закончена, можно тестировать.
Убираем сертификат пользователя
Теперь у нас есть авторизация через домен и сертификат пользователя бесполезен, отказаться от него кажется логичным решением. Но мобильные клиенты имеют с этим проблемы, просто не принимая такую конфигурацию, а десктопные хоть и работают, но злостно ругаются. Во-первых, изменим конфигурацию на сервере, чтобы он перестал требовать сертификат.
verify-client-cert none
Далее в конфигурацию клиентов добавляем
setenv CLIENT_CERT 0
Все, теперь клиенты не будут ругаться на сертификат. Забавно, что этот параметр спрятан в разделе вопросов-ответов для iOS. Я не тестировал на iOS, но Android, а так же MacOS (бета клиент) и Windows принимают эти настройки на ура. Только сторонний OpenVPN-клиент на Android пока этого не умеет (к моменту написания статьи уже могли поправить).