Экстренный VPN сервер Openconnect с двухфакторной авторизацией на Centos 8

Предисловие

Вечерком воскресенья в середине марта мне поступил телефонный звонок, суть которого заключалась а том, что 200+ человек не приедут в понедельник в офис, а переводятся на «удалёнку». Фраза: одни на «удаленку», а админы на «продлёнку», завертелась у меня в голове.

Нельзя сказать, что удаленного доступа к внутренним ресурсам у нас не было совсем, но мы использовали IPSEC VPN на связке Shrew soft VPN client + Pfsense для экстренного доступа некоторых IT специалистов к вмененным им в поддержку информационным системам. У Shrew soft VPN client проявлялась особенность, заключавшаяся в том, что после некоторого количества успешных соединений перестают работать ipv4 маршруты. Лечилась данная ситуация перезапуском Windows служб или перезагрузкой конечного устройства. Перспектива объяснять коллегам этот нюанс неопределенное количество раз в день вызывала нервный тик и тремор конечностей одновременно.

Муки выбора

Я определил следующие требования к решению для организации VPN до офисных систем:

  1. Простота настройки. В надежде, что некоторые справятся самостоятельно;
  2. Наличие клиента для популярных операционных систем;
  3. Поддержка парольной авторизации Active Directory; Срочный Выпуск ключей(сертификатов) не входил в мои планы
  4. Двухфакторная аутентификация. Желательно бесплатно;
  5. Минимальные вложения, а лучше бесплатно, поскольку бюджет 2020 на IT-оборудование не предполагал затрат на шлюз удаленного доступа;
  6. И предсказуемая стабильность и производительность;

Новомодный WireGuard работает на ключах, openvpn-gui, имхо, имеет не самый дружелюбный интерфейс клиента, пару лет назад я пробовал SoftEther VPN, но остался не доволен производительностью, про Shrew soft писал выше. Openconnect VPN Server + OpenConnect SSL VPN Client — настройка клиента 1 строкой поддержка всех популярных платформ, возможность работать только по tcp, поддержка духфакторной аутентификации, интеграция с LDAP, то что надо! Еще и совместимость с Cisco Anyconnect client 🙂

Настройка

Настройку сервера я производил на базе ОС Centos 8. При установке Centos 8 в минимальной конфигурации я постоянно сталкиваюсь с некорректной работы русской локали, которая решается установкой glibc-langpack-en, и заменой системного шрифта>

dnf install glibc-langpack-en
setfont UniCyr_8x16
Меняем в /etc/vconsole.conf FONT="UniCyr_8x16"

Настройка межсетевого экрана:


#Устанавливаем зону trusted по-умолчанию для всех сетевых интерфейсов
#В связи с переходом на nftables есть проблема с работой Firewalld в части правил в цепочке Forward. Пока рекомендуют использовать зону trusted 
firewall-cmd --set-default-zone=trusted
#Добавляем новую службу в firewalld - ocserv (используются порты 443/tcp 443/udp)
firewall-cmd --permanent --new-service=ocserv
firewall-cmd --permanent --service=ocserv --set-description="OpenConnect SSL VPN Server"
firewall-cmd --permanent --service=ocserv --add-port=443/tcp
firewall-cmd --permanent --service=ocserv --add-port=443/udp
#Внешнему интерфейсу(в моем случае ens192) назначаем зону drop
firewall-cmd --zone=drop --change-interface=ens192 --permanent
firewall-cmd --reload
#В зону drop добавляем разрешающее правило для созданной службы ocserv
firewall-cmd --zone=drop --permanent --add-service=ocserv
firewall-cmd --reload

OpenConnect SSL VPN Server может использовать для авторизации механизм pam. Для «сквозной» авторизации клиентов Active Directory добавим наш новый сервер в домен:


#Установим необходимые пакеты 
dnf install realmd sssd oddjob oddjob-mkhomedir adcli samba-common samba-common-tools krb5-workstation

Проверим доступность инфрастуктуры Active Directory

realm  discover mydomain.ru

mydomain.ru
type: kerberos
realm-name: MYDOMAIN.RU
domain-name: mydomain.ru
configured: no
server-software: active-directory
client-software: sssd
required-package: oddjob
required-package: oddjob-mkhomedir
required-package: sssd
required-package: adcli
required-package: samba-common-tools

 #Подключение к домену  Active Directory
realm join mydomain.ru -U Username

Автоматически будет сформирован конфигурационный файл службы SSSD (System Security Services Daemon) /etc/sssd/sssd.conf. Необходимо добавить пока еще не установленную службу VPN сервера ocserv в настройки. Параметр use_fully_qualified_names отвечает за формат имени пользователя.

Листинг /etc/sssd/sssd.conf

[sssd]
domains = mydomain.ru
config_file_version = 2
services = nss, pam
default_domain_suffix = mydomain.ru

[domain/mydomain.ru]
ad_domain = mydomain.ru
ad_gpo_map_remote_interactive = +ocserv
krb5_realm = MYDOMAIN.RU
realmd_tags = manages-system joined-with-adcli
cache_credentials = True
id_provider = ad
krb5_store_password_if_offline = True
default_shell = /bin/bash
ldap_id_mapping = True
use_fully_qualified_names = True
fallback_homedir = /home/%u@%d
access_provider = ad

Включим и запустим службу SSSD

systemctl enable sssd
systemctl start sssd

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

realm permit --all

На данном этапе должна заработать аутентификация по ssh на сервер для пользователей домена.

Выбирая модуль для реализации двухфакторной двухэтапной аутентификации я посмотрел на стоимость поддерживаемого из коробки Duo security и выбрал TOTP (Time-based One-time Password) в лице Google Authenticator. В этой реализации критическим важным является момент синхронизации времени сервера службами точного времени. Проверить корректность работы демона chronyd можно командой: chronyc sources

Вывод chronyc sources

210 Number of sources = 2
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^- ntp1.vniiftri.ru 1 6 17 1 -171us[ -171us] ± 2166us
^* ntp2.vniiftri.ru 1 6 17 1 -237us[ -57us] ± 2494us

Установка Google Authenticator:

dnf install epel-release
dnf install google-authenticator qrencode-libs

Далее необходимо из под учетной записи пользователя на сервере(sudo su DomainUser) выполнить команду google-authenticator и ответив в положительно на все вопросы получить индентификатор/qr-код для приложения Google Authenticator на смартфоне пользователя (IOS, Google play)

Установка Openconnect VPN Server:

dnf install ocserv
#Включим автозапуск сервера при загрузке
systemctl enable ocserv

Конфигурационный файл /etc/ocserv/ocserv.conf

auth = «pam»
#IPv4 внешний адрес на котором работает служба
listen-host = 1.1.111.1
tcp-port = 443
udp-port = 443
run-as-user = ocserv
run-as-group = ocserv
socket-file = ocserv.sock
chroot-dir = /var/lib/ocserv
isolate-workers = true
max-clients = 0

#Ограничение на кол-во сессий с одинаковым логином
max-same-clients = 1
keepalive = 32400
dpd = 90
mobile-dpd = 1800
switch-to-tcp-timeout = 25
try-mtu-discovery = true

#LetsenCrypt сертификаты для шифрования
server-cert = /etc/letsencrypt/live/vpn.mydomain.ru/fullchain.pem
server-key = /etc/letsencrypt/live/vpn.mydomain.ru/privkey.pem

########################
cert-user-oid = 0.9.2342.19200300.100.1.1
compression = true
tls-priorities = "@SYSTEM"
auth-timeout = 240
idle-timeout = 1200
mobile-idle-timeout = 2400
min-reauth-time = 300
max-ban-score = 50
ban-reset-time = 300
cookie-timeout = 300
deny-roaming = false
rekey-time = 172800
rekey-method = ssl
use-occtl = true
pid-file = /var/run/ocserv.pid
device = vpns
predictable-ips = true
default-domain = vpn.mydomain.ru
#Адрес сети для VPN клиентов
ipv4-network = 192.168.178.0/24

#Настройка маршрутизации DNS-запросов
tunnel-all-dns = true
dns = 192.168.1.1
########################
ping-leases = false

#Маршрутизация VPN клиента к внутренним сетям
route = 192.168.1.0/255.255.255.0
route = 192.168.2.0/255.255.255.0
########################
cisco-client-compat = true
dtls-legacy = true
user-profile = profile.xml

Получаем сертификаты LetsEncrypt для шифрования VPN трафика. Поднимать веб сервер для этого вовсе не обязательно. Создавать задание на регулярный перевыпуск сертификатов я не стал, полагая, что 3-х месяцев хватит для разрешения ситуации с COVID-19 в том или ином ключе.


firewall-cmd --zone=drop --add-service=http
curl -O  https://dl.eff.org/certbot-auto
mv certbot-auto /usr/local/bin/certbot-auto
chown root /usr/local/bin/certbot-auto
chmod 0755 /usr/local/bin/certbot-auto
certbot-auto certonly --standalone --preferred-challenges http -d vpn.mydomain.ru
firewall-cmd --zone=drop --remove-service=http

Включаем двухфакторную аудентификацию и запускаем службу VPN сервера

sed '/^#%PAM-1.0$/a auth       required     pam_google_authenticator.so' /etc/pam.d/ocserv
systemctl start ocserv
systemctl start ocserv

Включаем возможность пересылки трафика между интерфейсами

echo "net.ipv4.ip_forward=1">/etc/sysctl.d/0-ocserv.conf
sysctl -w net.ipv4.ip_forward=1

Клиентам предлагаем установить openconnect-gui. В настройках профиля указываем наш сервер vpn.mydomain.ru

При подключении на запрос Password от клиента необходимо заполнять OTP из Google Authenticator. На запрос Password1 пароль пользователя Active Directory.

Три недели полет нормальный…

Специально для сайта ITWORLD.UZ. Новость взята с сайта Хабр