Очень часто внутри организации возникает необходимость объединить несколько удалённых устройств в единую виртуальную сеть. В этой статье мы подобно рассмотрим как это можно сделать на примере дистрибутива 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 — его порт для входящих соединений.
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’ (и в дальнейшем нельзя будет подписать сертификат сервера)
Спасибо, добавил параметр -R, отвечающий за рекурсивную обработку каталогов.
в разделе «Настройка сервера»:
— файл с параметрами Диффи-Хеллмана — указан неправильный путь: не хватает «второго»/подпапки «pki»
— база отозванных сертификатов — указан неправильный путь: не хватает «второго»/подпапки «pki»
(комментарии не допускают указание ссылок, поэтому привести правильный путь нет возможности)
Спасибо, добавил недостающий каталог.
В разделе «Настройка брандмауэра» перед firewall-cmd … пропущено sudo
На самом деле для команды firewall-cmd запуск через sudo не требуется — она сама выдаёт запрос на повышение прав, однако при установке на чистом сервере без X11, это невыполнимо, поэтому, согласен, sudo необходим. Добавил, спасибо.
Предлагаю в статью добавить абзац про обновление списка отозванных сертификатов (проблема: CRL has expired). Это первое с чем столкнется пользователь, установивший OVN по предлагаемой инструкции (в конфиге выше он самый «мало-живущий» — 180 дней).
Добавил. Спасибо.
Перед tls-crypt, видимо, нужно добавить key-direction 0
В конфиге сервера это не требуется ибо направление ключа у tls-crypt всегда равно нулю и указывается сразу после имени файла TA-ключа.
В конфиге клиента оно уже присутствует.