Постановка задачи
Статья описывает организацию удаленного доступа сотрудников на продуктах с открытым исходным кодом и может быть использована как для построения полностью автономной системы, так и окажется полезной для расширения, когда в имеющейся коммерческой системе возникает нехватка лицензий или ее производительность оказывается недостаточной.
Цель статьи — внедрить законченную систему предоставления удаленного доступа организации, что немного больше, чем «установка OpenVPN за 10 минут».
В результате мы получим систему, в которой для аутентификации пользователей будут использоваться сертификаты и (опционально) корпоративный каталог Active Directory. Т.о. мы получим систему с двумя факторами проверки — что имею (сертификат) и что знаю (пароль).
Признаком, что пользователю разрешено подключение, является его членство в группе myVPNUsr. Центр сертификации будет использован автономный.
Цена внедрения решения — только небольшие аппаратные ресурсы и 1 час работы системного администратора.
Мы будем использовать виртуальную машину с OpenVPN и Easy-RSA 3-й версии на CetntOS 7, которой из расчета на 100 подключений выдано 4 vCPU, 4 GiB RAM.
В примере сеть нашей организации 172.16.0.0/16, в которой VPN сервер с адресом 172.16.19.123 расположен в сегменте 172.16.19.0/24, DNS серверы 172.16.16.16 и 172.16.17.17, а для VPN клиентов выделена подсеть 172.16.20.0/23.
Для подключения извне используется подключение по порту 1194/udp, а в DNS для нашего сервера создана A-запись gw.abc.ru.
Категорически не рекомендуется отключать SELinux! OpenVPN работает без отключения политик безопасности.
Содержание
- Установка ОС и прикладного ПО
- Настройка криптографии
- Настройка OpenVPN
- Аутентификация в AD
- Запуск и диагностика
- Выпуск и отзыв сертификата
- Настройка сети
- Что дальше
Установка ОС и прикладного ПО
Используем дистрибутив CentOS 7.8.2003. Нам нужна установка ОС в минимальной конфигурации. Удобно делать это с использованием kickstart, клонированием ранее установленного образа ОС и другими средствами.
После установки, назначения адреса сетевому интерфейсу (по условиям задачи 172.16.19.123), выполняем обновление ОС:
$ sudo yum update -y && reboot
Также необходимо убедиться, что на нашей машине выполняется синхронизация времени.
Для установки прикладного ПО нужны пакеты openvpn, openvpn-auth-ldap, easy-rsa и vim как основной редактор (понадобится репозиторий EPEL).
$ sudo yum install epel-release
$ sudo yum install openvpn openvpn-auth-ldap easy-rsa vim
Для виртуальной машины полезно установить гостевого агента:
$ sudo yum install open-vm-toolsдля хостов VMware ESXi, или для oVirt
$ sudo yum install ovirt-guest-agentНастройка криптографии
Переходим в каталог easy-rsa:
$ cd /usr/share/easy-rsa/3/Создаем файл переменных:
$ sudo vim varsследующего содержания:
export KEY_COUNTRY="RU"
export KEY_PROVINCE="MyRegion"
export KEY_CITY="MyCity"
export KEY_ORG="ABC LLC"
export KEY_EMAIL="admin@abc.ru"
export KEY_CN="allUsers"
export KEY_OU="allUsers"
export KEY_NAME="gw.abc.ru"
export KEY_ALTNAMES="abc-openvpn-server"
export EASYRSA_CERT_EXPIRE=3652
Здесь описаны параметры для условной организации ООО «ABC», можно исправить их на настоящие или оставить из примера. Самое важное в параметрах — последняя строка, определяющая срок действия сертификата в днях. В примере использовано значение 10 лет (365*10+2 високосных года). Это значение необходимо будет откорре��тировать перед выпуском сертификатов пользователей.
Далее настраиваем автономный центр сертификации.
Настройка включает экспорт переменных, инициализацию ЦС, выпуск корневых ключа и сертификата ЦС, ключ Диффи-Хеллмана, ключ TLS, а также ключа и сертификата сервера. Ключ центра сертификации необходимо тщательно оберегать и хранить в секрете! Все параметры при запросах можно оставить по умолчанию.
cd /usr/share/easy-rsa/3/
. ./vars
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-dh
./easyrsa gen-req myvpngw nopass
./easyrsa sign-req server myvpngw
./easyrsa gen-crl
openvpn --genkey --secret pki/ta.key
На этом основная часть настройки криптографического механизма закончена.
Настройка OpenVPN
Переходим в каталог OpenVPN, создаем служебные каталоги и добавляем ссылку на easy-rsa:
cd /etc/openvpn/
mkdir /var/log/openvpn/ /etc/openvpn/ccd /usr/share/easy-rsa/3/client
ln -s /usr/share/easy-rsa/3/pki/ /etc/openvpn/
Создаем основной файл конфигурации OpenVPN:
$ sudo vim server.confследующего содержания
port 1194
proto udp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/myvpngw.crt
key /etc/openvpn/pki/private/myvpngw.key
crl-verify /etc/openvpn/pki/crl.pem
dh /etc/openvpn/pki/dh.pem
server 172.16.20.0 255.255.254.0
ifconfig-pool-persist ipp.txt
push "route 172.16.0.0 255.255.255.0"
push "route 172.17.0.0 255.255.255.0"
client-config-dir ccd
push "dhcp-option DNS 172.16.16.16"
push "dhcp-option DNS 172.16.17.17"
keepalive 10 120
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1
username-as-common-name
plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-ldap.so /etc/openvpn/ldap.conf
Некоторые замечания по параметрам:
- если при выпуске сертификата было указно другое имя — укажите его;
- пул адресов указывайте под свои задачи*;
- маршрутов и DNS серверов может быть один или несколько;
- 2 последние строки нужны для реализации аутентификации в AD**.
*Выбранный в примере диапазон адресов позволит подключиться одновременно до 127 клиентам, т.к. выбрана сеть /23, а OpenVPN создает на каждого клиента подсеть по маске /30.
При особой необходимости порт и протокол могут быть изменены, однако следует иметь ввиду, что изменение порта номера порта повлечет настройку SELinux, а использование протокола tcp повысит накладные расходы, т.к. контроль доставки tcp-пакетов уже выполняется на уровне инкапсулированных в туннель пакетов.
**Если аутентификация в AD не нужна, закомментируйте их, следущий раздел — пропустите, а в шаблоне удалите строку auth-user-pass.
Аутентификация в AD
Для поддержки второго фактора будем использовать проверку учетной записи в AD.
Нам необходима учетная запись в домене с правами рядового пользователя и группа, членством в которой будет определяться возможность подключения.
Создаем конфигурационный файл:
/etc/openvpn/ldap.confследующего содержания
<LDAP>
URL "ldap://ldap.abc.ru"
BindDN "CN=bindUsr,CN=Users,DC=abc,DC=ru"
Password b1ndP@SS
Timeout 15
TLSEnable no
FollowReferrals yes
</LDAP>
<Authorization>
BaseDN "OU=allUsr,DC=abc,DC=ru"
SearchFilter "(sAMAccountName=%u)"
RequireGroup true
<Group>
BaseDN "OU=myGrp,DC=abc,DC=ru"
SearchFilter "(cn=myVPNUsr)"
MemberAttribute "member"
</Group>
</Authorization>
Основные параметры:
- URL «ldap://ldap.abc.ru» — адрес контроллера домена;
- BindDN «CN=bindUsr,CN=Users,DC=abc,DC=ru» — каноническое имя для привязки к LDAP (УЗ — bindUsr в контейнере abc.ru/Users);
- Password b1ndP@SS — пароль пользователя для привязки;
- BaseDN «OU=allUsr,DC=abc,DC=ru» — путь, с которого начинать поиск пользователя;
- BaseDN «OU=myGrp,DC=abc,DC=ru» — контейнер разрешающей группы (группа myVPNUsr в контейнере abc.ru\myGrp);
- SearchFilter "(cn=myVPNUsr)" — имя разрешающей группы.
Запуск и диагностика
Теперь мы можем попробовать включить и запустить наш сервер:
$ sudo systemctl enable openvpn@server.service
$ sudo systemctl start openvpn@server.service
Проверка запуска:
systemctl status openvpn@server.service
journalctl -xe
cat /var/log/messages
cat /var/log/openvpn/*log
Выпуск и отзыв сертификата
Т.к. помимо самих сертификатов нужны ключи и остальные настройки, очень удобно обернуть все это в один файл профиля. Этот файл затем передается пользователю и уже профиль импортируется на клиенте OpenVPN. Для этого создадим шаблон настроек и скрипт, формирующий профиль.
В профиль нужно добавить содержимое файлов корневого сертификата (ca.crt) и TLS ключ (ta.key).
Перед выпуском сертификатов пользователей не забудьте установить требуемый срок действия сертификатов в файле параметров. Не следует делать его слишком большим, рекомендую ограничиться максимум 180 днями.
vim /usr/share/easy-rsa/3/vars...
export EASYRSA_CERT_EXPIRE=180
vim /usr/share/easy-rsa/3/client/template.ovpnclient
dev tun
proto udp
remote gw.abc.ru 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
auth-user-pass
<ca>
-----BEGIN CERTIFICATE-----
PUT YOUR CA CERT (ca.crt) HERE
-----END CERTIFICATE-----
</ca>
key-direction 1
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
PUT YOUR TA KEY (ta.key) HERE
-----END OpenVPN Static key V1-----
</tls-auth>
Примечания:
- строки PUT YOUR... меняем на содержимое своих сертификатов;
- в директиве remote укажите имя/адрес своего шлюза;
- директива auth-user-pass используется для дополнительной внешней аутентификации.
В домашнем каталоге (или другом удобном месте) создаем скрипт запроса сертификата и создания профиля:
vim ~/make.profile.sh#!/bin/bash
if [ -z "$1" ] ; then
echo Missing mandatory client name. Usage: $0 vpn-username
exit 1
fi
#Set variables
basepath=/usr/share/easy-rsa/3
clntpath=$basepath/client
privpath=$basepath/pki/private
certpath=$basepath/pki/issued
profile=$clntpath/$1.ovpn
#Get current year and lowercase client name
year=`date +%F`
client=${1,,}
echo Processing $year year cert for user/device $client
cd $basepath
if [ -f client/$client* ]; then
echo "*** ERROR! ***"
echo "Certificate $client already issued!"
echo "*** ERROR! ***"
exit 1
fi
. ./vars
./easyrsa --batch --req-cn=$client gen-req $client nopass
./easyrsa --batch sign-req client $client
#Make profile
cp $clntpath/template.ovpn $profile
echo "<key>" >> $profile
cat $privpath/$1.key >> $profile
echo "</key>" >> $profile
echo -e "\n" >> $profile
openssl x509 -in $certpath/$1.crt -out $basepath/$1.crt
echo "<cert>" >> $profile
cat $basepath/$1.crt >> $profile
echo "</cert>" >> $profile
echo -e "\n" >> $profile
#remove tmp file
rm -f $basepath/$1.crt
echo Complete. See $profile file.
cd ~
Делаем файл исполняемым:
chmod a+x ~/make.profile.shИ можно выпустить наш первый сертификат.
~/make.profile.sh my-first-userОтзыв
В случае компрометации сертификата (утеря, кража) необходимо отозвать этот сертификат:
cd /usr/share/easy-rsa/3/
./easyrsa revoke my-first-user
./easyrsa gen-crl
Просмотр выданных и отозванных сертификатов
Для просмотра выданных и отозванных сертификатов достаточно просмотреть индексный файл:
cd /usr/share/easy-rsa/3/
cat pki/index.txt
Пояснения:
- первой строкой идет сертификат сервера;
- первый символ
- V (Valid) — действительный;
- R (Revoked) — отозванный.
Настройка сети
Последние шаги — настройка сети передачи — маршрутизации и межсетевых экранов.
Разрешение подключений в локальном брандмауэре:
$ sudo firewall-cmd --add-service=openvpn
$ sudo firewall-cmd --add-service=openvpn --permanent
Далее, включаем маршрутизацию IP трафика:
$ sudo sysctl net.ipv4.ip_forward=1
$ sudo echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/50-sysctl.conf
В корпоративной среде наверняка существует деление на подсети и нам необходимо сообщить маршрутизатору (-ам), каким образом отправлять пакеты, адресованные нашим VPN клиентам. В командной строке выполняем команду на манер (зависит от используемого оборудования):
# ip route 172.16.20.0 255.255.254.0 172.16.19.123и сохраняем конфигурацию.
Помимо этого на интерфейсе пограничного маршрутизатора, где обслуживается внешний адрес gw.abc.ru, необходимо разрешить прохождение пакетов udp/1194.
В случае, если в организации действуют строгие правила безопасности, на нашем VPN сервере необходимо также настроить межсетевой экран. На мой взгля��, наибольшую гибкость дает настройка iptables цепочек FORWARD, хотя настраивать их менее удобно. Немного подробнее о их настройке. Для этого удобнее всего использовать «прямые правила» — direct rules, хранимые в файле /etc/firewalld/direct.xml. Действующую конфигурацию правил можно узнать так:
$ sudo firewall-cmd --direct --get-all-ruleПеред изменением файла сделайте его резервную копию:
cp /etc/firewalld/direct.xml /etc/firewalld/direct.xml.`date +%F.%T`.bakПримерное содержимое файла таково:
<?xml version="1.0" encoding="utf-8"?>
<direct>
<!--Common Remote Services-->
<!--DNS-->
<rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o ens192 -p udp --dport 53 -j ACCEPT</rule>
<!--web-->
<rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p tcp -d 172.16.19.200 --dport 80 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
<rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p tcp -d 172.16.19.201 --dport 443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
<!--Some Other Systems-->
<rule priority="0" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -p udp -d 172.16.19.100 --dport 7000 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
<!--just logging-->
<rule priority="1" table="filter" ipv="ipv4" chain="FORWARD">-i tun0 -o eth0 -j LOG --log-prefix 'forward_fw '</rule>
</direct>
Пояснения
По существу это обычные правила iptables, иначе упакованные после появления firewalld.
Интерфейс назначения при настройках по умолчанию tun0, а внешний для туннеля может быть иным, напр., ens192, в зависимости от используемой платформы.
Последняя строка предназначена для журналирования отброшенных пакетов. Чтобы журналирование заработало, в конфигурации firewalld нужно изменить уровень отладки:
vim /etc/sysconfig/firewalld
FIREWALLD_ARGS=--debug=2
Применение настроек — обычная команда firewalld для перечитывания настроек:
$ sudo firewall-cmd --reloadОтброшенные пакеты можно просмотреть так:
grep forward_fw /var/log/messagesЧто дальше
На этом настройка закончена!
Осталось на стороне клиента установить клиентское ПО, импортировать профиль и подключиться. Для ОС типа Windows дистрибутив размещен на сайте разработчика.
В завершение подключаем наш новый сервер к системам мониторинга и архивации, и не забываем регулярно устанавливать обновления.
Стабильного коннекта!
