UMGUM.COM 

Установка OpenVPN-сервера ( Инсталляция и настройка VPN-сервера "OpenVPN". )

25 марта 2010  (обновлено 5 июля 2020)

OS: "Linux Debian 5/6/7/8/9", "Linux Ubuntu 14/16/18 LTS".
Application: "OpenVPN v2.1/2.4", "EasyRSA", "Bash".

Задача: установить и настроить сервис доступа в сетевую инфраструктуру предприятия удалённых клиентов с шифрованием трафика с аутентификацией посредством индивидуальный x509-сертификатов.

На роль самого удобного и простого в применении на стороне клиента напрашивается протокол L2TP, клиенты которого реализованы для всех современных операционных систем, включая предназначенные для мобильных телефонов. Для использования L2TP не требуется установка дополнительного клиентского программного обеспечения - и это хорошо. Однако в процессе эксплуатации выявляются некоторые проблемы, вроде невозможности автоматически отправить клиенту маршруты на подсети за VPN-соединением, а также существенная трудность настройки IPSec в случае подключения с одного IP-адреса нескольких клиентов. В итоге, для организации доступа к разветвлённой корпоративной сети из хорошо известных и проверенных годами бесплатных решений остаётся только "OpenVPN Community Edition (CE)".

Последовательность дальнейших действий такова:

1. Подготовка системного окружения (отдельная инструкция);
2. Установка сервера "OpenVPN";
3. Создание корневого SSL-сертификата;
4. Создание SSL-сертификата для сервера "OpenVPN";
5. Настройка и запуск сервера "OpenVPN";
6. Разрешение пересылки сетевых пакетов в несущей системе;
7. Наладка ротации журналов событий;
8. Создание SSL-сертификатов для клиентов "OpenVPN".
9. Индивидуальная настройка сетевых параметров клиентов "OpenVPN".


Установка сервера "OpenVPN".

У проекта "OpenVPN Community" нет официального пакетного репозитория, так что основной способ установки - из исходных кодов, свободно доступных в git-репозитории. В "README" репозитория можно найти ссылки на инструкции по установке и настройке "OpenVPN", которыми мы в дальнейшем и воспользуемся. Кроме того, в Wiki проекта "Linux Debian" есть хорошее описание их подхода к настройке "OpenVPN".

При том, что официально "OpenVPN" в готовой сборке не поставляется, таковые сделаны для всех распространённых систем командами их поддержки. В частности, для "Linux Ubuntu 18.04 LTS" дистрибутивная версия "OpenVPN v2.4.4", а в разделе загрузки на сайте разработчиков последняя стабильная "v.2.4.9" - разбег не шокирующе велик, так что не будем усложнять себе жизнь и воспользуемся готовым APT-пакетом, идущим в комплекте с несущей операционной системой:

# apt-get update && apt-get upgrade
# apt-get install openvpn openssl iptables git

Сборки "OpenVPN" для "Linux Debian/Ubuntu" 2019-2020 годов не предусматривают запуск сервиса от имени произвольного непривилегированного пользователя. Можно попробовать это исправить, добавив соответствующую системную учётную запись, раздав разрешения, создав несколько sudo-правил и скриптовых обёрток для обхода недостаточного уровня полномочий при доступе к ресурсам, после чего вполне успешно запустив приложение в нужном контексте. Но за этим потребуется отключить автоматику управления приложения подсистемами "Sys-V/Systemd", написав свою - и вот мы уже потеряли возможность обновлять систему с приложениями встроенными инструментами APT. Я за максимальную совместимость и автоматизацию, и полагаю, что проще вынести VPN-сервис на полностью выделенный сервер, позволив ему там вытворять всё, что угодно.

Создаем директории для отображения статистики и хранения журнальных файлов:

# mkdir -p /var/lib/openvpn /var/log/openvpn
# touch /var/lib/openvpn/status.log
# touch /var/log/openvpn/server.log

"OpenVPN" страдает мелким капризом, не желая запускаться и завершая работу в случае отсутствия файла журнала событий. Потому заранее создаём его одной и команд выше.

Отмечу, что "OpenVPN" представляет собой практически всего один исполняемый файл, играющий роль как сервера, так и клиента, в зависимости от того, с каким параметрами конфигурации он запускается.

Создание корневого SSL-сертификата.

Обеспечение конфиденциальности передаваемых данных реализуется сервисом "OpenVPN" посредством инкапсуляции в простейшее SSL-соединения, представляемое для пользователей в виде VPN-туннеля. Совершенно так же, как это случается при обращении к web-сайту по протоколу HTTPS, но в данном случае заверяющие подлинность сетевых узлов SSL-сертификаты выпущены не каким-то внешним центром сертификации, а создаются администратором VPN-сервиса.

Для управления SSL-сертификатам воспользуемся адаптированным для "OpenVPN" набором скриптов "EasyRSA" - это действительно проще, чем написание чего-то подобного самостоятельно:

# cd /usr/src
# git clone --single-branch --branch master https://github.com/OpenVPN/easy-rsa.git

На случай, если "OpenVPN" будет использоваться не только в роли принимающего подключения пользователей сервиса, но и как клиент для связи со сторонней сетевой инфраструктурой, явно вынесем настраиваемую сейчас конфигурацию в поддиректорию "./server/":

# mkdir -p /etc/openvpn/server/easy-rsa
# cp -r /usr/src/easy-rsa/easyrsa3/* /etc/openvpn/server/easy-rsa
# mv /etc/openvpn/server/easy-rsa/vars.example /etc/openvpn/server/easy-rsa/vars

Опишем заранее ряд констант, которые будут использоваться при создании x509-сертификатов, как сервера, так и клиентов:

# vi /etc/openvpn/server/easy-rsa/vars

....
set_var EASYRSA_REQ_COUNTRY "RU"
set_var EASYRSA_REQ_PROVINCE "Krasnoyarsk"
set_var EASYRSA_REQ_CITY "Krasnoyarsk"
set_var EASYRSA_REQ_ORG "Company Name"
set_var EASYRSA_REQ_OU "IT"
....
# Задаём срок действия корневого сертификата в десять лет
set_var EASYRSA_CA_EXPIRE 3650
....
# Задаём срок действия сертификатов сервера и клиентов в десять лет
set_var EASYRSA_CERT_EXPIRE 3650
....

Зачищаем место для работы (внимательно с этим - удаляются все ранее созданные сертификаты в файловой иерархии "./easy-rsa/") и генерируем первичный корневой "самоподписанный" сертификат:

# cd /etc/openvpn/server/easy-rsa
# ./easyrsa init-pki
# ./easyrsa build-ca nopass

Common Name (eg: your user, host, or server name) [Easy-RSA CA]: Self-signed CA certificat for OpenVPN Server

Проверим срок действия и вообще соответствие ожиданиям публичной части корневого сертификата:

# openssl x509 -noout -text -in /etc/openvpn/server/easy-rsa/pki/ca.crt | less

Далее для работы нам понадобится только публичная часть "самоподписанного" корневого сертификата "./pki/ca.crt", а секретный ключ "./pki/private/ca.key" будет использоваться исключительно скриптом "EasyRSA" для создания новых сертификатов и отзыва старых или скомпрометированных.

Заранее заготовим файл для перечня отозванных сертификатов:

# cd /etc/openvpn/server/easy-rsa
# ./easyrsa gen-crl

Закрываем доступ посторонним в директорию с сертификатами:

# chown -R root:root /etc/openvpn/server/easy-rsa
# chmod -R go-rwx /etc/openvpn/server/easy-rsa

Создание SSL-сертификата для сервера "OpenVPN".

Если делать всё правильно, с выносом секретной части "корневого" сертификата отдельно от VPN-сервера, то для создания подписанного сертификата понадобиться пройти путь создания приватного клуча и CSR-запроса ("easyrsa gen-req"), перемещения запроса в систему с корневым сертификатом ("easyrsa import-req"), создания там сертификата на основе запроса ("easyrsa sign-req"), и перемещение итогового файла на VPN-сервер.

Но, кто так делает, изначально пойдя по самому лёгкому пути с использованием "EasyRSA"? Для VPN-сервиса с количеством пользователей в пару десятков - никто, наверное. Потому, одной командой прогоняем всю цепочку операций создания условно серверного сертификата:

# cd /etc/openvpn/server/easy-rsa
# ./easyrsa build-server-full ovpn.example.net nopass

Просмотр содержимого полученного сертификата - всех трёх его компонентов:

# openssl rsa -noout -text -in ./pki/private/ovpn.example.net.key | less
# openssl req -noout -text -in ./pki/reqs/ovpn.example.net.req | less
# openssl x509 -noout -text -in ./pki/issued/ovpn.example.net.crt | less

Кроме SSL-сертификата серверу "OpenVPN" ещё понадобится служебный файл параметров "Диффи-Хэлмана", предназначающийся для обеспечения более надёжного шифрования соединения сервера и клиента:

# openssl dhparam -out /etc/openvpn/server/easy-rsa/pki/dhparam.key 2048

Также создаем служебный файл статического ключа "HMAC", обеспечивающего первичную простейшую аутентификацию как дополнительную защиту от DDoS атак:

# openvpn --genkey --secret /etc/openvpn/server/easy-rsa/pki/ta.key

Клиентскими сертификатами займёмся позже, а пока попробуем запустить сам сервер "OpenVPN".

Настройка и запуск сервера "OpenVPN".

Воспользуемся предоставленным разработчиками шаблоном конфигурационного файла "OpenVPN":

# cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
# gunzip /etc/openvpn/server.conf.gz

# vi /etc/openvpn/server.conf

# Задаём режим работы приложения
mode server
tls-server

# Включаем VPN-сервер в режим работы маршрутизатора (Layer 3)
# (явно задаём имя используемого виртуального сетевого интерфейса,
# это пригодится для чёткого описания правил защитного экрана):
dev tun0

# Включаем режим выделения клиентам адресов с маской "/30"
# (на серверах после "v2.1" можно выделять подсеть "/32", но тогда нереализуемы многосетевые схемы):
topology net30

# Принимаем подключения отовсюду:
local 0.0.0.0

# Указываем протокол и порт, на котором VPN-сервер будет принимать подключения
# (намеренно используем порт "для сайтов", чтобы дать клиентам возможность проходить
# из зашоренных корпоративных локальных сетей через защитные экраны и прокси):
proto tcp-server
port 443

# Указываем месторасположение SSL-сертификатов и ключей сервера:
ca /etc/openvpn/server/easy-rsa/pki/ca.crt
tls-auth /etc/openvpn/server/easy-rsa/pki/ta.key 0
dh /etc/openvpn/server/easy-rsa/pki/dhparam.key
cert /etc/openvpn/server/easy-rsa/pki/issued/ovpn.example.net.crt
key /etc/openvpn/server/easy-rsa/pki/private/ovpn.example.net.key

# Указываем месторасположение списка отозванных сертификатов:
crl-verify /etc/openvpn/server/easy-rsa/pki/crl.pem

# Включаем шифрование чуть более высокого относительно стандартного уровня:
cipher AES-256-CBC

# Включаем сжатие трафика между сервером и клиентом:
comp-lzo

# Указываем серверу поддерживать связь с клиентами путём посылания мини-пакета
# каждые 10 секунд и закрывать соединения, если ответ не пришёл спустя 120 секунд:
keepalive 10 120

# Задаём основной IP-адрес VPN-сервера и обслуживаемый сетевой диапазон
# (из него будут адресоваться подключившиеся клиенты, для которых явно
# не переопределены параметры через CCD; адреса будут выдаваться
# в порядке очерёдности автоматически из имеющихся свободных):
ifconfig 10.20.30.2 10.20.30.1
ifconfig-pool 10.20.30.4 10.20.30.254 255.255.255.0

# Передаём клиентам команды, дополняющие их сетевую конфигурацию
# (маршруты к обслуживаемым VPN-сервером подсетям общего пользования):
push "route 10.10.10.0 255.255.255.0"

# (опционально) Передаём клиенту команду перевести весь его трафик на VPN-соединение
;push "redirect-gateway def1 bypass-dhcp"

# Передаём клиентам команды, дополняющие их сетевую конфигурацию (DNS и опции):
push "dhcp-option DNS 10.10.10.10"

# Передаём клиентам указание проверять соединение каждые 10 секунд и
# перезапускать сессию, если от VPN-сервера нет ответа в течении 60 секунд:
push "ping 10"
push "ping-restart 60"

# Указываем директорию с клиентскими конфигурациями, переопределяющими параметры "по умолчанию":
client-config-dir /etc/openvpn/server/ccd

# Явно не разрешаем межклиентское взаимодействие:
;client-to-client

# Явно не разрешаем использование разными клиентами одинаковых "Common Name"
# (у нас для каждого клиента генерируется индивидуальный сертификат):
;duplicate-cn

# Указываем месторасположение и режим работы журналов событий:
status /var/lib/openvpn/status.log
log-append /var/log/openvpn/server.log
verb 3
;mute 10

Заранее создаём директорию для размещения клиентских конфигураций, переопределяющих глобальные:

# mkdir -p /etc/openvpn/server/ccd

В дистрибутивной поставке для "Linux Debian/Ubuntu" скрипты автоматического запуска "Sys-V/Systemd" принимают на вход сразу все конфигурационные файлы ".conf" в директории "/etc/openvpn", так что обычно достаточно просто запустить или перезапустить сервис.

В "Linux Ubuntu" для "Systemd" наверчена дополнительная конструкция сканирования набора конфигурационных файлов и запуска определённого с указанием имени сервиса, сопоставляемого с именем его конфигурационного файла. В самом простом случае, по умолчанию, имя сервиса будет "server":

# systemctl enable openvpn@server.service
# systemctl start openvpn@server
# systemctl status openvpn@server
# journalctl -xe

Если ошибок при запуске сервиса небыло, то проверяем, начал ли сервер "OpenVPN" прослушивать назначенный ему порт:

# netstat -apn | grep openvpn

tcp ... 0 0.0.0.0:443 0.0.0.0:* LISTEN .../openvpn

Если в системе нет других туннельных виртуальных интерфейсов, то "OpenVPN" по умолчанию задействует имя "tun0":

# ip addr show dev tun0

3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> ...
....

# netstat -rn

Destination Gateway    Genmask         ... Iface
0.0.0.0     10.10.10.1 0.0.0.0         ... ens3
....
10.20.30.0  10.10.30.2 255.255.255.0   ... tun0
10.20.30.2  0.0.0.0    255.255.255.255 ... tun0

Если свидетельств успешного запуска сервера посредством "Sys-V/Systemd" не наблюдается, то пробуем сделать это вручную и смотрим сообщения об ошибках в журнале событий:

# openvpn --config /etc/openvpn/server.conf --verb 4

Разрешение пересылки сетевых пакетов в несущей системе.

В конфигурации выше мы выбрали режим работы сервера "OpenVPN" в роли виртуального маршрутизатора, терминирующего клиентские подключения. Чтобы пакеты пересылались и далее, в соответствии с уже системной таблицей маршрутизации, потребуется явно включить режим "IP forwarding" для несущей системы:

# vi /etc/sysctl.d/30-ip-forward.conf

# Enable IP forwarding (for OpenVPN)
net.ipv4.ip_forward = 1

Применяем заготовленную для этапа запуска операционной системы конфигурацию вручную:

# sysctl -p -f /etc/sysctl.d/30-ip-forward.conf

Важно иметь в виду то, что в режиме конфигурации "topology net30" ("Layer 3") сервер "OpenVPN" эмулирует работу маршрутизатора, к портам которого подключены как сам сервер, так и его клиенты. При этом, каждому подключению выделяется, из описанного нами выше в конфигурационном файле диапазона, по четыре IP-адреса (подсеть /30, ограничиваемая маской 255.255.255.252), где (например):

"10.20.30.0" - адрес подсети 10.20.30.0/30;
"10.20.30.1" - адрес виртуального порта на стороне VPN-сервера;
"10.20.30.2" - адрес виртуального порта на стороне VPN-клиента;
"10.20.30.3" - адрес широковещательный (broadcast).

Надо отметить, что непосредственно к портам виртуального маршрутизатора обратиться не получится - в частности, на ICMP-запросы они не отвечают.

Начиная с "OpenVPN v2.1" появилась поддержка топологии "subnet" (), когда сервер и клиент находятся в одной подсети, и выделение IP осуществляется по одному, а не блоками из четырёх - это экономнее. Однако до сих пор не все клиенты этот режим поддерживают, да и логику маршрутизации придётся менять, что не всегда возможно с большим производственным наследием и разномастными подсетями, в которых нужно адресовать подключающихся пользователей.

Наладка ротации журналов событий.

В дистрибутивной поставке "OpenVPN" усечение и ротация журналов событий не предусмотрена. Исправим это:

# vi /etc/logrotate.d/openvpn

/var/log/openvpn/*.log {
  weekly
  rotate 12
  compress
  delaycompress
  missingok
  notifempty
  copytruncate
}

Проверяем корректность конфигурации, не воздействуя при этом на файлы журналов:

# logrotate -d /etc/logrotate.d/openvpn

Создание SSL-сертификатов для клиентов "OpenVPN".

Создание SSL-сертификатов для клиентов "OpenVPN" рассматривается в отдельной заметке.

Индивидуальная настройка сетевых параметров клиентов "OpenVPN".

Подготовка CCD-конфигурации для клиентов "OpenVPN" рассматривается в отдельной заметке.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )