Облачное хранилище

Как настроить OpenVPN сервер на Ubuntu и включить аутентификацию через LDAP (Active Directory) + TOTP

Честно искал в интернет (не только в русскоязычном сегменте) статью под критерии ниже, полной так и не нашел, собирал по кусочком для потребовавшейся инсталляции, решил оставить тут для истории, надеюсь кому-то поможет.

Чем отличается моя сборка от тех, что описаны во множестве инструкций в сети:

  • Ubuntu 20-22
  • LDAP авторизация с MS AD
  • TOTP Google Auth
  • без скриптов и с отдельным окном для OTP у клиента

Статья собрана скорее, чтобы не забыть, что-то может быть упущено случайно или с уверенностью, что что-то очевидно и так. После публикации будет правится по вашим комментариям.

В данном примере настройка сервера выполняется с использованием дистрибутива Linux — Ubuntu Server. Клиент настраивается под Microsoft Windows. В качестве LDAP-сервера мною используется Microsoft Active Directory.

Статью можно использовать как основу для настройки OpenVPN на любой операционной системе семейства UNIX.

Готовим сервер

Заходим в систему под суперпользователем:

sudo su

Устанавливаем часовой пояс (у меня московское время) и синхронизируем его с сервером времени:

timedatectl set-timezone Europe/Moscow

Настраиваем задание в cron для автоматической синхронизации времени каждый день в 00:00:

mkdir -p /var/cron/tabs && echo '0 0 * * * /usr/sbin/ntpdate ru.pool.ntp.org' >> /var/cron/tabs/crontab && crontab /var/cron/tabs/crontab && crontab -l

Обновляем пакеты:

apt update && apt upgrade

Устанавливаем OpenVPN и создаем сертификаты

Устанавливаем пакеты openvpn и easy-rsa:

apt install openvpn easy-rsa openvpn-auth-ldap

Создаем каталог easy-rsa, переходим в него и копируем рабочие файлы:

mkdir /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa/*
Открываем на редактирование скрипт vars и выставляем подходящие значения для своего сертификата:
# nano ./vars
export KEY_COUNTRY="RU"
export KEY_PROVINCE="MSK"
export KEY_CITY="Moscow"
export KEY_ORG="Company"
export KEY_EMAIL="support@company.com"
export KEY_CN=SMC
export KEY_OU=SMC
export KEY_NAME=vpn.company.com
export KEY_ALTNAMES="company-openvpn-server"
#export PKCS11_MODULE_PATH=changeme
#export PKCS11_PIN=1234

Запускаем на исполнение отредактированный скрипт:

# . ./vars

На всякий случай, чистим каталоги от старых сертификатов:

# ./easyrsa clean-all

Генерируем первый сертификат:

# ./easyrsa build-ca
На все запросы просто нажимаем Enter, так как мы все настроили в переменных с помощью файла vars.

Создаем ключ для сервера:

# ./easyrsa build-server-full ovpnserver nopass
В конце подтверждаем подписание сертификата ([Y]).

Формируем ключ Диффи-Хеллмана:

# ./easyrsa gen-dh
Теперь создаем ключ для клиента:

# ./easyrsa build-client-full testclient nopass
В конце подтверждаем подписание сертификата ([Y]).

Ну и на последок, TLS-ключ:

# openvpn --genkey --secret keys/ta.key

Копируем каталог с созданными сертификатами и ключами в /etc/openvpn:

# cd /etc/openvpn
# cp easy-rsa/pki/{dh.pem,ca.crt} easy-rsa/pki{/issued/ovpnserver.crt,/private/ovpnserver.key} .

Устанавливаем плагин для проверки по LDAP

Клонируем во временную папку репозиторий:

git clone https://github.com/threerings/openvpn-auth-ldap

там в readme есть инструкция по установке:

cd openvpn-auth-ldap/
./ubuntu_16.04_lts_build.sh

В директории /etc/openvpn создаем каталог auth и в нем конфигурационный файл ldap.conf. В последний добавляем следующие строки:

mkdir /etc/openvpn/auth

mcedit /etc/openvpn/auth/ldap.conf

<LDAP>
  URL             ldap://dc.company.local
  BindDN          CN=company_app_oVPNserver,OU=Users,DC=company,DC=local
  password        ***
  Timeout         15
  TLSEnable       no
</LDAP>

<Authorization>
  BaseDN          "DC=company,DC=local"
  SearchFilter    "(&(sAMAccountName=%u)(memberOf=CN=oVPN_access,OU=Groups,DC=Company,DC=local))"
</Authorization>

ldap://dc.company.local — контроллер домена. CN=company_app_oVPNserver,OU=Users,DC=company,DC=local — учетная запись для связывания с контроллером домена. *** — пароль для учетной записи openvpn. DC=company,DC=local — корень в домене, с которого начнется поиск учетной записи для аутентификации. CN=oVPN_access,OU=Groups,DC=company,DC=local — группа безопасности, в которую должна входить учетная запись для успешной аутентификации.

Устанавливаем google authenticator

apt-get install libpam-google-authenticator

пакет даст нам возможность и генерировать токены (используйте команду “google-authenticator”)

Сразу сгенерируем TOTP GAuth:

echo Введите имя пользователя:
read user
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 --issuer=Company -l "$user@company.com" -s /etc/openvpn/google-authenticator/.$user.google_authenticator > /etc/openvpn/google-authenticator/$user.auth

.$user.google_authenticator – файл с секретом на первой строке (понадобится нам позже)
$user.auth – файл, который можно отправлять пользователю, там ссылка на QR-код, коды восстановления.

Устанавливаем плагин openvpn-otp

git clone https://github.com/evgeny-gridasov/openvpn-otp.git

в Readme все есть:

Убедитесь, что установлены следующие компоненты:

  • openvpn
  • openvpn-devel (Some distros have openvpn-plugin.h file in a separate package)
  • autoconf
  • automake
  • libtool
  • libssl-dev/openssl-devel/libressl-devel

To bootstrap autotools (generate configure and Makefiles):

./autogen.sh

Build and install with:

./configure --prefix=/usr
make install

Настраиваем сервер и клиента

Настройка сервера

Создаем конфигурационный файл и вставляем в него следующее содержимое:

# mcedit /etc/openvpn/server.conf

local 192.168.194.1
port 1194
proto tcp
dev tun
ca ca.crt
cert ovpnserver.crt
key ovpnserver.key
dh dh.pem
#tls-auth keys/ta.key 0
server 172.80.200.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
max-clients 320
#client-to-client
persist-key
persist-tun
verify-client-cert none
client-config-dir /etc/openvpn/client-configs/

username-as-common-name
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log

# LDAP plugin auth
plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth/ldap.conf
#OTP PLUGIN
plugin /usr/lib/openvpn/openvpn-otp.so debug=1 password_is_cr=1 otp_secrets=/etc/openvpn/otp-secrets

verb 3

mute 20
daemon
mode server
tls-server
#link-mtu 1522
tun-mtu 1395
comp-lzo
#push "comp-lzo"

##Redirect all traffic to VPN server ##
#push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 172.80.100.2"

##Push a specfic route to redirct to VPN server ##

up /etc/nat
  • 172.29.2.35 — IP-адрес, на котором сервер будет устанавливать VPN-соединение. 172.31.252.0 255.255.255.0 — адресация для виртуальной сети. 32 — количество клиентов для одновременного подключения.

Для удобства можно воспользоваться скриптом, он запрашивает имя пользователя и генерирует TOTP от Google, раскладывая секреты по нужным местам:

echo Введите имя пользователя:
read user
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 --issuer=Company -l "$user@company.com" -s /etc/openvpn/google-authenticator/.$user.google_authenticator > /etc/openvpn/google-authenticator/$user.auth


endfile=/etc/openvpn/google-authenticator/.${user}.google_authenticator
secret=$(sed -n '1p' $endfile)
echo "$user otp totp:sha1:base32:$secret::xxx *" >> /home/smcadmin/openvpn/otp-secrets
echo all is ok

Перезагружаем демон openvpn:

service openvpn restart

Настройка клиента

Заходим на официальный сайт openvpn и скачиваем клиента для Windows:

https://openvpn.net/index.php/open-source/downloads.html

Загрузка клиента openvpn

Запускаем скачанный файл и устанавливаем программу, нажимая «Далее».

В интернет много статей, где пароль УЗ AD и OTP вводятся в клиенте в одно поле одной строкой. Очень много похожих статей. А найти толковую про то, как сделать, чтобы поле для ввода TOTP отдельно от пароля у меня не вышло. Только обрывки и издалека.
Но, как и всегда, этого достичь очень просто! Для этого в клиенты OpenVPN ввели настройку static-challenge
Задается так: static-challenge “Text” 1 # use 0 if the OTP should not be echoed, где text – произвольное приглашение к вводу пароля, 1 – включатель опции

Воспользовавшись этой опцией создадим конфиг клиента:

#---------- Start of client.ovpn ----------
client
remote IP.IP.IP.IP port tcp
tls-client
dev tun
persist-key
persist-tun
remote-cert-tls server
key-direction 1
auth-nocache
reneg-sec 0
#redirect-gateway def1
  ##Un-comment these lines when using Linux
  ##in order to set the DNS server:
  ## If your Linux distro uses systemd-resolved:
  #script-security 2
  #up /etc/openvpn/update-systemd-resolved
  #down /etc/openvpn/update-systemd-resolved

  ## Otherwise:
  #script-security 2
  #up /etc/openvpn/update-resolv-conf
  #down /etc/openvpn/update-resolv-conf

# Set log file verbosity
verb 3
float
nobind
comp-lzo
#link-mtu 1522
tun-mtu 1395
block-outside-dns
<ca>
-----BEGIN CERTIFICATE-----
YourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCertYourCert
-----END CERTIFICATE-----
</ca>
auth-user-pass
auth-nocache
auth-retry interact
static-challenge "Введите код из Google Authenticator" 1 # use 0 if the OTP should not be echoed
#authorization.static_challenge prepend

(замените IP.IP.IP.IP, port и сертификат (внесен специально в конфиг для удобства передачи конфига на мобильные устройства)

Установите Authenticator от Google или другой OTP клиент и добавьте токен , сгенерированный раннее

Теперь можно подключаться

Спасибо за внимание.

P.S.: Коллеги, не надо кидать помидорами за возможную скудность и не разжеванность. Главная цель достигнута: оставить вслед о принципиально нужной на тот момент опции – запрос пароля OTP в отдельном окне + доменная авторизация при подключении к OpenVPN серверу, развернутому на Ubuntu 20/22
Конструктивная критика приветствуется в комментариях – по возможности буду подправлять.