Постановка задачи


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

Цель статьи — внедрить законченную систему предоставления удаленного доступа организации, что немного больше, чем «установка 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 работает без отключения политик безопасности.

Содержание


  1. Установка ОС и прикладного ПО
  2. Настройка криптографии
  3. Настройка OpenVPN
  4. Аутентификация в AD
  5. Запуск и диагностика
  6. Выпуск и отзыв сертификата
  7. Настройка сети
  8. Что дальше


Установка ОС и прикладного ПО


Используем дистрибутив 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.ovpn

client
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 дистрибутив размещен на сайте разработчика.

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

Стабильного коннекта!