Постановка задачи
Статья описывает организацию удаленного доступа сотрудников на продуктах с открытым исходным кодом и может быть использована как для построения полностью автономной системы, так и окажется полезной для расширения, когда в имеющейся коммерческой системе возникает нехватка лицензий или ее производительность оказывается недостаточной.
Цель статьи — внедрить законченную систему предоставления удаленного доступа организации, что немного больше, чем «установка 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.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 дистрибутив размещен на сайте разработчика.
В завершение подключаем наш новый сервер к системам мониторинга и архивации, и не забываем регулярно устанавливать обновления.
Стабильного коннекта!
Sergey-S-Kovalev
Может я не заметил, но выдавая каждому индивидуальный сертификат при этом не задаётся к каким ресурсам имеет право доступа сотрудник. По Вашей статье получается, что подцепившись к сети, пользователь имеет доступ куда угодно по любым протоколам. Т.е. начало в общем правильное, но концовка так себе ибо тонны малвари на домашних компах спят и видят новые возможности. Это сразу станет видно в логах контроллера AD, когда имя рабочей станции в логах будет пустое при попытке авторизации. И ловля таких занятие не тривиальное.
Но зачем? Существует прекрасный давно работающий RADIUS. Прекрасно и легко мониторится, все впнщки не зависят от одной учетки, которая может быть случайно или намеренно заблочена.
В теории практика и теория не отличаются, но на практике совершенно другое дело.
Я вот могу сказать, что внедрение за неделю OpenVPN на 600+ человек совершенно разной подготовки с таким подходом как в статье будет жутким геммороем для ИТ специалиста.
Потому что по каждому сотруднику нужно будет:
1. Определиться будет у него впн или нет.
2. Со своей железяки он будет работать или нет.
3. Определиться с перечнем ресурсов к которому он будет цепляться.
4. Сгенерить сертификат и аксесс лист. Собрать индивидуальный дистрибутив. Записать правила в фаерволле (тут привет всем кто не использует радиус с привязкой к настройкам nap сервера)
5. Выдать ему индивидуальный дистрибутив который «Далее/Далее/Далее/Готово». Привет тем у кого мак/иос/андройд, поскольку там не «далее/далее/далее/готово», а несколько больше движений.
6. К дистрибутиву приложить инструкцию что «Никаких паролей с русскими символами! И если ТАР-адаптер занят перезагрузите систему и запустить OpenVPN ДО запуска тимвьювера или других впн сервисов. Если не помогло — удалить другие впн сервисы и средства удаленки и переустановить клиент OpenVPN»
7. Внезапно выяснить, что у юзвера ХР/Win7sp0 и понять что тебя ждет немного боли.
8. Внезапно выяснить, что в винде не все апдейты и на серваки с включенным NLA по рдп не пускает, поскольку в корп сети всеобновлено, а на личном ПК сотрудника нет. Там же винду ставил антипрививочник и отрубил нахрен все апдейты.
Общее на всех:
— Настроить выгрузку логов в SIEM, ELF или на худой конец в syslog север, потому что руководство 100% спросит кто и когда цеплялся за весь период. Возможно стоит начать до того как людям дадуд впн.
— Начать писать скрипт, который выгружает с компов лог событий id=4801,4800,4778,4779, поскольку выяснится, что подключится к впн это не значит начать работать. Ну или отдать эту проблему СБшникам, если у тех есть средства контроля по сети.
— Сделать вебстраничку, что бы топы могли оценить общий график подключений к впн. Типа впн выдали тыще человек, а подключилось только 150. Итак, кто оставшиеся 850 подлецов?!
— Внезапно выяснить, что в лесу доменов повершельный Get-ADGroupMember не отдает все то ты хочешь видеть. А именно список людей не входящих в домен корня леса. Покурить интернеты, где у всех точно такая же проблема и в итоге понять что проще написать самому.
— Видеть кучу подключений к vpn посреди ночи. И почему у этих нескольких человек из корп сети в сторону их личных ПК гигабайты трафика, когда остальные за рабочий день укладываются в 30 мегабайт?
— Обязательно делать снапшоты перед очередным
$ sudo yum update -y && reboot
— Понять что заворачивать весь трафик через свой шлюз было идиотской идеей.
Но за статью спасибо!
imichael Автор
Сергей, спасибо за комментарий!
Практически со всем соглашусь, но, во избежание разрастания статьи умышленно старался сократить ее, нещадно отсекая многие важные вещи, а аудиторию в заголовке обозначил как SMB. Боролся даже с желанием хотя бы простецкий график типа darkstat прикрутить! А вообще статья — проба пера, OpenVPN просто первый под руку попался. )
600+ — уже не самый типовой SMB. Как правило, специалисты в такой организации знают и понимают как строить подобные системы и для них статья мелковата, хотя может подойти как quick start.
По пунктам.
Если у коллег возникнет предложение, можно написать статью типа «продвинутые настройки OpenVPN» или «OpenVPN для 1000 пользователей».