bender

Сервер OpenVPN с авторизацией по сертификату на CentOS 7

Если Вы ещё не забыли, суть всего проекта состоит в том, чтобы показать, как разворачивать серверную инфраструктуру небольшой компании, в основном на базе Linux. И если помните в предыдущих сериях мы развернули сервер АД, и по этому многие из Вас зададут резонный вопрос, зачем я делаю авторизацию на базе сертификатов, когда гораздо проще авторизовывать пользователей через уже озвученный АД. На то есть целых три причины:

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

Давайте приступим. Сначала, как водится, немного теории, чтобы мы с Вами понимали, как это работает, а также, что нужно сделать, чтобы оно работало именно так, а не иначе. Тема на самом деле, очень обширная, и в общем-то не самая простая. Но сегодня мы поднимаем очень простую и самую распространённую схему, так что сильно не заморачивайтесь.
Итак, для чего нужен vpn сервер, и собственно сам VPN-тоннель. Тут всё очень просто. Допустим, нам необходимо получить доступ к ресурсам локальной сети нашей компании извне. Как это можно организовать? В принципе, можно конечно открыть сответствующие порты, и организовать их проброс на целевую машину. Но это просто глупо, и обычно этого делают, т.к. в этом случае Вы ставите под угрозу сервер, а вслед за ним и всю сеть компании. Гораздо уместней будет использовать шифрованный VPN-тоннель.

Рассмотрим в общих чертах, как работает openVPN.

После установки и конфигурирования, сервер слушает порт 1194 либо по TCP либо по UDP. Клиент обращается к серверу на этот порт, после чего происходит аутентификация. В процессе которой, в нашем случае, сервер проверяет данные сертификата. Если всё верно, сервер посылает клиенту ответ со своими данными. Клиент, так же проверяет сертификат сервера. После чего происходит авторизация, в процессе которой сервер считывает данные для конкретного пользователя (маршруты и т.п.). Если всё нормально между клиентом и сервером образовывается VPN-тоннель. Тоннель этот образовывается методом инкапсулирования. Условно инкапсуляцией, можно назвать процесс упаковывания пакета в пакет. Т.е. внутри пакета, который ходит от клиента до сервера, лежит ещё один зашифрованный пакет, который при получении дешифруется клиентом и сервером. Во внутреннем пакете содержится данные о сети и т.п. т.е. фактически по своей структуре он не отличается от того в который вложен.

Естественно, это не самая точная аналогия, по этому всем интересующимся можно смело читать описания протоколов и манулы. Но для того, чтобы понять, что и для чего мы будем делать, этого хватит.

Итак, для того, чтобы всё заработало нам нужно:

  • Обновить ОСь
  • Подключить репозиторий EPEL
  • Настроить, либо отключить SELinux
  • Установить все необходимые пакеты
  • Минимально поправить конфиги сервера OpenVPN, там в основном сетевые настройки.
  • После чего мы заполним файл со стандартными переменными для генерации ключей
  • Затем настроим Firewall
  • Включим автозапуск служб, и сразу их стартанём
  • Ну и в конце мы попробуем войти в нашу виртуальную сеть, с рабочей виндовой машинки.

Вроде бы ничего не забыл, давайте перейдём к делу.

У меня уже имеется машинка под сервер, с дефолтной конфигурацией:

  • CentOS7
  • 512ОЗУ
  • 8ГБ Жёсткий диск
  • Она находится у нас за шлюзом во внутренней сети, и имеет локальный адрес 192.168.10.11

Итак, приступим:

Обновляем систему

yum update -y

Ставим все необходимые пакеты. Обратите внимание, что помимо пакета openVPN, нам понадобится ещё пакет easy-rsa, для генерации сертификатов.

yum install epel-release -y
yum install vim wget mc screen acpid ntp bash-completion openvpn easy-rsa -y

Отключаем SE Linux:

vim /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Ребутимся:

reboot

Теперь копируем скрипты для генерации сертификатов в папку с openvpn:

cp /usr/share/doc/openvpn-*/sample/sample-config-files/server.conf /etc/openvpn

Заходим в файл конфигурации сервера (предварительно я почистил конфиг grep'ом) и внесём в него изменения. В принципе меня интересует сейчас несколько позиций, а именно:

#Порт и протокол который будет слушать сервер.
port 1194
proto udp
#Имя уст-ва.
dev tun
#Местополжоение сертификатов, клчей.
ca ca.crt
cert server.crt
dh dh2048.pem
#"Адресация" сервера.
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
#Машрутры.
push "route 192.168.10.0 255.255.255.0"
push "route 10.8.0.0 255.255.255.0"
#Указываем DNS сервер в нашей сети, чтобы подключившиеся клиенты могли "резолвить" компьютеры в нашей сети.
push "dhcp-option DNS 192.168.10.2"
#Проверка "жив" ли клиент. Кждые десять секунд опрос клиента, если в течение 120 секунд ответа нет - рестарт интерфеса
keepalive 10 120
#Использовать/неиспользовать сжатие трафика через tun. Умолчание - адаптивный режим
comp-lzo
#Не считывать ключи при перезапуске тоннеля
persist-key
#Не "трогает" интерфейс tun при перезапуске OpenVPN
persist-tun
#Логи
status /var/log/openvpn-status.log
log  /var/log/openvpn.log
log-append /var/log/openvpn.log
#Уровень логирования
verb 3

И ещё один важный момент. По-умолчанию сервер open-vpn запрещает одновременное подключение с помощью одного сертификата. Т.е. для каждого клиента Вы должны генерировать свой ключ и сертификат. Если у Вас всё же есть такая необходимость то раскомментируйте эту строчку в /etc/openvpn/server.conf:

duplicate-cn

Создадим папку для наших ключей:

mkdir -p /etc/openvpn/easy-rsa/keys
cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa

Теперь поправим значения стандартных переменных, которые будут подставляться при генерации сертификата:

vim /etc/openvpn/easy-rsa/vars

Обратите внимание, этот файл тоже очень хорошо задокументирован, по этому сейчас мы пройдёмся только по нужным нам, на данный момент значениям, которые будут подставляться всякий раз, когда мы генерируем ключ:
export EASY_RSA="`pwd`"
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
export KEY_DIR="$EASY_RSA/keys"
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"
export KEY_SIZE=2048
export CA_EXPIRE=3650
export KEY_EXPIRE=3650
export KEY_COUNTRY="KZ"		#Страна
export KEY_PROVINCE="ALA"		#Область
export KEY_CITY="Almaty"		#Город
export KEY_ORG="BENDER.KZ"		#Название организации
export KEY_EMAIL="admin@traning.kz"		#Почта
export KEY_OU="ITD"	#Подразделение (отдел) комании
export KEY_NAME="traning.kz"	#Имя ключа

 Генерируем всё для сервера:

source ./vars
./clean-all
./build-ca
./build-key-server server
./build-dh

 Скопируем ключи:

cd /etc/openvpn/easy-rsa/keys
cp dh2048.pem ca.crt server.crt server.key /etc/openvpn

 Сгенерируем всё для клиента:

cd /etc/openvpn/easy-rsa
./build-key ovpntest

Сконфигурируем firewalld, для этого создадим файл:

vim /etc/firewalld/direct.xml

Со следущим содержанием:

<direct>
  <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-i eth0 -p gre -j ACCEPT</rule>
</direct>

Добавляем в зону паблик UDP порт 1194, не забываем ставить permanent:

firewall-cmd --zone=public --add-port=1194/udp --permanent

Накладываем на зону паблик маскарад:

firewall-cmd --zone=public --add-masquerade --permanent

Перезагрузим firewalld:

firewall-cmd --reload

Добавляем в автозагрузку службу openvpn:

systemctl enable openvpn@server.service
systemctl start openvpn@server.service

В принципе на этом всё. Ниже приведен пример файла конфигурации клиента:

client
remote 192.168.1.197
comp-lzo
ca ca.crt
cert ovpntest.crt
key ovpntest.key
dev tun
proto udp
port 1194
nobind
auth-nocache
script-security 2
persist-key
persist-tun
user openvpn
group openvpn