Поднимаем OpenVPN сервер на Fedora

Очень часто внутри организации возникает необходимость объединить несколько удалённых устройств в единую виртуальную сеть. В этой статье мы подобно рассмотрим как это можно сделать на примере дистрибутива Fedora.

Подготовка

Для начала установим пакет из репозиториев дистрибутива:

sudo dnf install openvpn

Данный пакет включает в себя как клиент, так и сервер, а также необходимые примеры базовых файлов конфигурации и systemd-юниты для автоматического запуска при загрузке системы.

Установим пакет easy-rsa для простого и быстрого управления собственным PKI:

sudo dnf install easy-rsa

Создание локального УЦ (PKI)

Скопируем установленный easy-rsa в каталог локального PKI (в нашем примере это будет ~/pki):

mkdir -p ~/pki
cp -R /usr/share/easy-rsa/3/* ~/pki

Откроем создадим и заполним файл с шаблонами ~/pki/vars в любом текстовом редакторе:

touch ~/pki/vars
vim ~/pki/vars

Пример правильного файла vars:

# Easy-RSA 3 parameter settings

if [ -z "$EASYRSA_CALLER" ]; then
echo "You appear to be sourcing an Easy-RSA 'vars' file." >&2
echo "This is no longer necessary and is disallowed. See the section called" >&2
echo "'How to use this file' near the top comments for more details." >&2
return 1
fi

# Базовые константы путей и инфраструктуры. Не меняем.
set_var EASYRSA "$PWD"
set_var EASYRSA_OPENSSL "openssl"
set_var EASYRSA_PKI "$EASYRSA/pki"
set_var EASYRSA_DN "org"

# Задаём имя нашего CA, а также email администратора.
set_var EASYRSA_REQ_COUNTRY "NL"
set_var EASYRSA_REQ_PROVINCE "Noord-Holland"
set_var EASYRSA_REQ_CITY "Amsterdam"
set_var EASYRSA_REQ_ORG "MyORG LLC."
set_var EASYRSA_REQ_EMAIL "[email protected]"
set_var EASYRSA_REQ_OU "MyORG Name"

# Задаём стойкость шифра генерируемых ключей.
set_var EASYRSA_KEY_SIZE 2048

# Задаём алгоритм для ключей. Поддерживаются rsa (традиционный RSA) и ec
# (на основе эллиптических кривых).
set_var EASYRSA_ALGO rsa

# Задаём тип эллиптической кривой (если в предыдущей константе указано ec).
set_var EASYRSA_CURVE secp384r1

# Задаём срок действия корневого CA (по умолчанию 10 лет).
set_var EASYRSA_CA_EXPIRE 3650

# Задаём срок действия сертификатов серверов и клиентов.
set_var EASYRSA_CERT_EXPIRE 365

# Задаём срок действия CRL списков.
set_var EASYRSA_CRL_DAYS 180

# Отключаем поддержку legacy режима Netscape.
set_var EASYRSA_NS_SUPPORT "no"

# Если предыдущая опция включена, то комментарий для сертификата.
set_var EASYRSA_NS_COMMENT "MyORG Certificate"

# Имя временного файла, который будет использоваться при генерировании
# сертификатов и подписей.
set_var EASYRSA_TEMP_FILE "$EASYRSA_PKI/extensions.temp"

# Путь к каталогу с расширениями X509. Не изменяем.
set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types"

# Имя файла конфигурации OpenSSL. Также не изменяем.
set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-1.0.cnf"

# Имя клиентских сертификатов по умолчанию.
set_var EASYRSA_REQ_CN "MyORG Client"

# Формат подписи сертификатов. Рекомендуется использовать sha256.
set_var EASYRSA_DIGEST "sha256"

# Отключаем неинтеративный режим.
set_var EASYRSA_BATCH ""

Сначала нам необходимо произвести инициализацию локального PKI (это удалит все уже созданные в нём сертификаты, включая корневой):

cd ~/pki
./easyrsa init-pki

Теперь сгенерируем корневой сертификат, которым будут подписаны все сертификаты, выпущенные нашим удостоверяющим центром:

cd ~/pki
./easyrsa build-ca

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

Далее мастер будет запрашивать названия организации и другие стандартные поля, но т.к. мы уже создали файл vars, он просто импортирует их из него, поэтому просто жмём Enter на каждый вопрос.

По окончании работы будет создан и подписан локальный УЦ в виде файлов ~/pki/pki/ca.crt (сертификат) и ~/pki/pki/private/ca.key (закрытый ключ).

Создание сертификата для сервера

Теперь нам нужно создать сертификат для сервера. Сначала сформируем запрос на получение сертификата:

cd ~/pki
./easyrsa gen-req mysrv

Вместо mysrv здесь и далее в статье следует указывать внутреннее название нашего OVN сервера, например часть его доменного имени.

Будет запущен тот же мастер, что и для создания корневого сертификата. Обязательно зададим пароль секретного ключа, затем ответим на все вопросы кроме Common Name нажатием Enter. В этом поле укажем имя хоста нашего сервера.

Подпишем созданный сертификат:

cd ~/pki
./easyrsa sign-req server mysrv

Внимательно проверив все данные, напечатаем на клавиатуре yes и нажмём Enter, после чего введём пароль секретного ключа корневого сертификата для подписи.

На этом создание сертификата сервера было успешно завершено. Он может быть найден в ~/pki/pki/issued/mysrv.crt, а его ключ — ~/pki/pki/private/mysrv.key.

Создание сертификата для клиента

Для каждого клиента должен быть создан свой собственный сертификат! Выполним запрос на получение сертификата для первого клиента:

cd ~/pki
./easyrsa gen-req client1

Ответим на вопросы по своему усмотрению (они могут и не совпадать с указанными для сервера и УЦ), укажем пароль для защиты секретного ключа данного сертификата, затем нажмём Enter.

Подпишем созданный сертификат:

cd ~/pki
./easyrsa sign-req client client1

Как и в варианте для подписи ключа сервера, внимательно проверив все данные, напечатаем на клавиатуре yes и нажмём Enter, после чего введём пароль секретного ключа корневого сертификата для подписи.

Итоговый сертификат может быть найден в ~/pki/pki/issued/client1.crt, а его ключ — ~/pki/pki/private/client1.key.

Обновление сертификатов

По умолчанию сертификаты создаются на 1 год. По истечении этого срока их необходимо перевыпустить.

Сначала обновим базу easy-rsa, чтобы обнаружить и отметить сертификаты, требующие обновления:

cd ~/pki
./easyrsa update-db

Теперь подпишем нужный сертификат по старому CSR запросу:

cd ~/pki
./easyrsa sign-req client client1

Теперь можно передать любым способом на клиент или сервер обновлённый файл сертификата CRT из каталога ~/pki/pki/issued. Повторно копировать закрытый ключ при этом не требуется.

Создание параметров Диффи-Хеллмана

В обязательном порядке сгенерируем файл с параметрами для механизма обмена эфемерными ключами Диффи-Хеллмана (подробнее об этом здесь):

cd ~/pki
./easyrsa gen-dh

Через некоторое время результат будет сохранён в файле ~/pki/pki/dh.pem.

Создание базы отозванных сертификатов

Для корректной работы нашего удостоверяющего центра, необходимо создать базу данных отозванных сертификатов (CRL) в формате PEM:

cd ~/pki
./easyrsa gen-crl

По запросу введём пароль защиты секретного ключа нашего корневого сертификата.

Внимание! База отозванных сертификатов должна обновляться на сервере каждые 180 суток, в противном случае клиенты будут получать ошибку «CRL has expired».

Отзыв сертификатов

Любой выданный удостоверяющим центром сертификат (как клиентский, так и серверный) можно легко и просто отозвать. Для этого выполним:

cd ~/pki
./easyrsa revoke client1

Это действие отзовёт сертификат клиента с внутренним названием client1. Нас также попросят ввести с клавиатуры yes и нажать Enter.

По окончании необходимо обязательно выполнить обновление базы отозванных сертификатов таким же способом, как и её создание.

Создание общего статического ключа

Сгенерируем статический ключ TLS:

cd ~/pki
openvpn --genkey --secret ta.key

Настройка сервера

Все настройки сервера в Fedora хранятся в каталоге /etc/openvpn/server/, который доступен как для записи, так и для чтения только для суперпользователя.

Скопируем в данный каталог следующие файлы (возможно, потребуется переименовать существующие файлы для соответствия настройкам в файле конфигурации):

  • ~/pki/pki/issued/mysrv.crt (сертификат сервера);
  • ~/pki/pki/ca.crt (корневой сертификат УЦ);
  • ~/pki/pki/dh.pem (файл с параметрами Диффи-Хеллмана);
  • ~/pki/pki/crl.pem (база отозванных сертификатов);
  • ~/pki/ta.key (файл общего статического ключа).

Также нам потребуется скопировать в данный каталог и сертификат сервера в расшифрованном виде:

sudo openssl rsa -in ~/pki/pki/private/mysrv.key -out /etc/openvpn/server/mysrv.key

По запросу введём пароль для расшифровки закрытого ключа данного сертификата.

Создадим и откроем в текстовом редакторе с правами суперпользователя файл /etc/openvpn/server/server.conf:

sudo touch /etc/openvpn/server/server.conf
sudo chmod 0600 /etc/openvpn/server/server.conf
sudo vim /etc/openvpn/server/server.conf

Примерный листинг файла server.conf:

port 1194
proto udp
dev tun

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
dh /etc/openvpn/server/dh.pem
crl-verify /etc/openvpn/server/crl.pem

server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt

push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

keepalive 10 120

tls-server
tls-crypt /etc/openvpn/server/ta.key 0
tls-timeout 120
auth SHA512
cipher AES-256-GCM

max-clients 3

user nobody
group nobody

persist-key
persist-tun

log /var/log/openvpn.log
verb 3
mute 20

Теперь на все файлы в каталоге /etc/openvpn/server/ установим chmod 0600:

sudo find /etc/openvpn/server -maxdepth 1 -type f -exec chmod 0600 "{}" \;

Обязательно сбросим политики SELinux для данного каталога:

sudo restorecon -Rv /etc/openvpn/server

Настройка брандмауэра

Чтобы наш сервер заработал, необходимо разрешить сетевую активность сервера:

sudo firewall-cmd --permanent --add-service openvpn

Включим маскарадинг для зоны FirewallD:

sudo firewall-cmd --permanent --add-masquerade

Обновим конфигурацию FirewallD:

sudo firewall-cmd --reload

Разрешим перенаправление трафика как по протоколу TCP/IP версии 4, так и v6:

sudo sysctl -w net.ipv4.conf.all.forwarding=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1

Сохраним настройки перенаправления так, чтобы они работали и после перезагрузки системы:

sudo bash -c "echo -e \"net.ipv4.conf.all.forwarding=1\nnet.ipv6.conf.all.forwarding\" > /etc/sysctl.d/99-openvpn.conf"

Настройка автоматического запуска

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

sudo systemctl start openvpn-server@

Чтобы он начал запускаться вместе с системой, активируем нужный юнит:

sudo systemctl enable openvpn-server@

Для отключения автозапуска:

sudo systemctl disable openvpn-server@

Внимание, на сервере с CentOS после символа @ необходимо указать и внутреннее название сервера.

Приложение

Пример файла myclient.ovpn для клиентов, который может быть импортирован в Network Manager (но не следует забывать, что на клиентах с Fedora файлы сертификатов и их закрытые ключи должны располагаться в каталоге ~/.cert):

client
dev tun
proto udp
remote IP_ADDRESS 1194
resolv-retry infinite
nobind
persist-key
persist-tun
auth SHA512
cipher AES-256-GCM
key-direction 0
verb 3
mute 20

<ca>
  < ... сертификат УЦ (CA) ... >
</ca>

<cert>
  < ... сертификат клиента ... >
</cert>

<key>
  < ... приватный ключ клиента ... >
</key>

<tls-crypt>
  < ... статический ключ TLS ... >
</tls-crypt>

Шифры, указанные в конфиге клиента и сервера, должны обязательно совпадать, иначе будет выдаваться ошибка TLS Error: cannot locate HMAC in incoming packet.

Вместо IP_ADDRESS следует указать IP-адрес или доменное имя, на котором запущен сервер, а 1194 — его порт для входящих соединений.

10 commentaries to post

  1. CentOS 7: вместо cp /usr/share/easy-rsa/3/* ~/pki использовал cp -R /usr/share/easy-rsa/3/* ~/pki
    иначе cp: omitting directory ‘/usr/share/easy-rsa/3/x509-types’ (и в дальнейшем нельзя будет подписать сертификат сервера)

    1. Спасибо, добавил параметр -R, отвечающий за рекурсивную обработку каталогов.

  2. в разделе «Настройка сервера»:
    — файл с параметрами Диффи-Хеллмана — указан неправильный путь: не хватает «второго»/подпапки «pki»
    — база отозванных сертификатов — указан неправильный путь: не хватает «второго»/подпапки «pki»
    (комментарии не допускают указание ссылок, поэтому привести правильный путь нет возможности)

  3. В разделе «Настройка брандмауэра» перед firewall-cmd … пропущено sudo

    1. На самом деле для команды firewall-cmd запуск через sudo не требуется — она сама выдаёт запрос на повышение прав, однако при установке на чистом сервере без X11, это невыполнимо, поэтому, согласен, sudo необходим. Добавил, спасибо.

  4. Предлагаю в статью добавить абзац про обновление списка отозванных сертификатов (проблема: CRL has expired). Это первое с чем столкнется пользователь, установивший OVN по предлагаемой инструкции (в конфиге выше он самый «мало-живущий» — 180 дней).

  5. Перед tls-crypt, видимо, нужно добавить key-direction 0

    1. В конфиге сервера это не требуется ибо направление ключа у tls-crypt всегда равно нулю и указывается сразу после имени файла TA-ключа.

      В конфиге клиента оно уже присутствует.

Обсуждение закрыто.