Установка OpenVPN на Ubuntu 20.04

Установка OpenVPN на Ubuntu 20.04
Photo by Privecstasy / Unsplash

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

Обновляем пакеты сервера

sudo apt-get update
sudo apt upgrade

Устанавливаем софт

sudo apt install openvpn easy-rsa iptables-persistent

При установке пакета iptables-persistent потребется пара подтверждений создания файлов для правил сетей IPv4 и IPv6. Можем отвечать везде yes.

Настраиваем центр сертификации

В OpenVPN открытый ключ называется сертификатом и имеет расширение .crt, а закрытый ключ так и называется ключом, его расширение - .key. Обслуживать всё это дело будут скрипты Easy-RSA.

Для того чтобы после обновления системы все сертификаты и настройки не были стёрты, скопируем набор скриптов из каталога /usr/share/easy-rsa куда-нибудь, например, в /etc/openvpn/:

sudo mkdir /etc/openvpn/easy-rsa
sudo cp -R /usr/share/easy-rsa /etc/openvpn/

Создадим центр сертификации в этой папке. Для этого сначала перейдем в неё:

cd /etc/openvpn/easy-rsa/

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

sudo cp vars.example vars

Отредактируем файл:

sudo nano vars

Ниже показаны лишь измененные фрагменты. Для начала редактируем поля создаваемого сертификата:

set_var EASYRSA_REQ_COUNTRY     "RU"
set_var EASYRSA_REQ_PROVINCE    "Krasnoyarsk krai"
set_var EASYRSA_REQ_CITY        "Krasnoyarsk"
set_var EASYRSA_REQ_ORG "Daniil V. Savenkov Blog"
set_var EASYRSA_REQ_EMAIL       "nobody@savenkoff.com"
set_var EASYRSA_REQ_OU          "Private VPN"
Описание полей сертификата
Поля сертификата можно посмотреть в его свойствах, например через IE: Свойства браузера - вкладка ”Содержание” - кнопка ”Сертификаты” - кнопка ”Просмотр” - вкладка ”Состав”. Субъект (Subject) - поле идентификации субъекта (владельца) сертификата Наименование субъекта, хранящееся в поле ”субъект”, имеет определенный формат и определяется набором именованных параметров, часть которых необязательна. Содержание

А так-же параметры шифрования:

set_var EASYRSA_ALGO            ec
set_var EASYRSA_DIGEST          "sha512"

Создаём каталог pki и необходимые файлы для генерации сертификатов:

sudo ./easyrsa init-pki

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

sudo ./easyrsa build-ca

Создаём ключи Диффи-Хафмана, которые используются при обмене ключами между клиентом и сервером:

sudo ./easyrsa gen-dh

Команда создаст файл /etc/openvpn/easy-rsa/pki/dh.pem. Если есть необходимость использовать TLS авторизацию, понадобится ключ Hash-based Message Authentication Code (HMAC). Он используется для предотвращения DoS атаки при использовании протокола UDP. Создаём:

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

Для отзыва уже подписанных сертификатов понадобится сертификат отзыва. Создаём:

sudo ./easyrsa gen-crl

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

sudo ./easyrsa build-server-full [server] nopass

, где [server] - это имя сервера (заменить на свой, квадратные скобки убрать), а опция nopass отключает использование пароля.

Копируем все полученные ключи надо в папку /etc/openvpn:

cp ./pki/ca.crt /etc/openvpn/ca.crt
cp ./pki/dh.pem /etc/openvpn/dh.pem
cp ./pki/crl.pem /etc/openvpn/crl.pem
cp ./pki/ta.key /etc/openvpn/ta.key
cp ./pki/issued/[server].crt /etc/openvpn/[server].crt
cp ./pki/private/[server].key /etc/openvpn/[server].key

не забываем про то, что [server] - это имя сервера (заменить на свой, квадратные скобки убрать).

Конфигурация сервера

По умолчанию, конфигурационных файлов OpenVPN нет. Их нужно создать самостоятельно в зависимости от того, что планируется настраивать, сервер или клиент. Нужный файл конфигурации OpenVPN можно найти по адресу /usr/share/doc/openvpn/examples/sample-config-files/. Создаём конфигурационный файл для сервера:

zcat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz | sudo tee /etc/openvpn/server.conf

Редактируем файл конфигурации сервера. Основные параметры port и proto - порт и протокол, по которым будет работать сервер:

port 1194
proto udp

Все созданные ключи нужно прописать в конфигурационном файле. Хоть и наши ключи хранятся по адресу /etc/openvpn, в самой папке с конфигурационным файлом, прописываем к ним полный путь (без указания пути может возникнуть ошибка Options error: --ca fails with 'ca.crt': No such file or directory (errno=2)):

ca ca /etc/openvpn/ca.crt
cert /etc/openvpn/[server].crt
key /etc/openvpn/[server].key  # This file should be kept secret
# Немного ниже меняем имя для сертификата Диффи-Хафмана
dh /etc/openvpn/dh.pem
tls-auth /etc/openvpn/ta.key 0 # This file is secret

Настраиваем диапазон адресов для виртуальной сети, наш сервер будет доступен по первому из них - 10.8.0.1:

server 10.8.0.0 255.255.255.0

Редактируем DNS сервера для клиентов VPN, раздаваемые по DHCP. Ниже приведена настройка для использования DNS Google и Cloudflare:

push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 1.1.1.1"

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

push "redirect-gateway def1 bypass-dhcp"

Раскомментируем запись логов в отдельные файлы (по-умолчанию лог пишется в syslog):

log         /var/log/openvpn/openvpn.log
log-append  /var/log/openvpn/openvpn.log

Основная конфигурация завершена, сохраняем.

Пробуем вручную запустить OpenVPN с указанием адреса конфигурационного файла, если ничего не произошло (визуально), то читаем логи.

sudo openvpn /etc/openvpn/server.conf

При успешном запуске мы консоль как-бы зависнет, без визуальных оповещений, остановить текущий процесс можно с помощью комбинации клавиш Ctrl + C. Проверяем логи и убеждаемся, что ошибок запуска нет, увидев заветное Initialization Sequence Completed. Теперь можно запустить сервер демоном:

sudo systemctl start openvpn@server

и сразу добавляем его в автозагрузку:

sudo systemctl enable openvpn@server

Настройка форвардинга пакетов

Для включения проброса пакетов можно отредактировать файл /etc/sysctl.conf, раскомментировав строку:

net.ipv4.ip_forward=1

, либо с помощью команды:

sysctl -w net.ipv4.ip_forward=1

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

Теперь надо разрешить прохождение пакетов в брандмауэре. Будем использовать iptables. Узнаем сетевой интерфейс, который используется для доступа к внешней сети с помощью команды:

ip -br a

lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             111.222.333.113/24 fe80::c8Xx:ff:feXx:13Xx/64
tun0             UNKNOWN        10.8.0.1 peer 10.8.0.2/32 fe80::83Xx:d9Xx:14Xx:e9Xx/64

В данном случае сетевым интерфейсом является eth0, интерфейсом OpenVPN - tun0. На основе этих данных можно сформировать правила для iptables и прописать их:

sudo iptables -I FORWARD -i tun0 -o eth0 -j ACCEPT
sudo iptables -I FORWARD -i eth0 -o tun0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

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

sudo iptables-save > /etc/iptables/rules.v4 

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

Создание сертификатов будет происходить на сервере. Переходим в директорию /etc/openvpn/easy-rsa/ и выполним команду:

cd /etc/openvpn/easy-rsa/
sudo ./easyrsa build-client-full [client1] nopass

, где [client1] - уникальное имя клиента OpenVPN (квадратные скобки убрать), а опция nopass отключает использование пароля. При выполнении команды понадобится ввести пароль, указанный ранее при формировании CA-сертификата.

Конфигурация клиента

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

sudo mkdir /etc/openvpn/clients
sudo mkdir /etc/openvpn/clients/[client1]

Переносим ранее созданные ключи клиента в его директорию с переименованием в client.cer и client.key соответственно:

sudo cp /etc/openvpn/easy-rsa/pki/issued/[client1].crt /etc/openvpn/clients/[client1]/client.crt
sudo cp /etc/openvpn/easy-rsa/pki/private/[client1].key /etc/openvpn/clients/[client1]/client.key

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

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/clients/client.conf
sudo nano /etc/openvpn/clients/client.conf

Основной параметр remote - сервер и порт, по которым будет присоединяться клиент (можно использовать ID или FQDN):

remote 111.222.333.113 1194

Так как мы будем для клиента собирать ovpn файл конфигурации, необходимо заккоментировать строки конфигурации, указывающие на файлы сертификатов, иначе, даже если их содержимое включить в файл, конфигурации будут требоваться файлы сертификатов, в ней указанные.

;ca ca.crt
;cert client.crt
;key client.key
;tls-auth ta.key 1

Создаём ovpn файл конфигурации для отправки клиенту. На Stack Exchange был найден скрипт для создания конфигурации в формате ovpn, отредактирован под текущее окружение. Скопируйте код ниже, сохраните в файл под именем MakeOvpnConfig.sh, загрузите файл в директорию /etc/openvpn/clients/ и выдайте права на выполнение скрипта.

#!/bin/bash

# Default Variable Declarations

DEFAULT="client.conf"
FILEEXT=".ovpn"
CRT="client.crt"
KEY="client.key"
CA="ca.crt"
TA="ta.key"
kRootPath="/etc/openvpn/"

#Ask for a Client name
echo "Please enter an existing Client Name folder:"
read NAME

#1st Verify that client's Public Key Exists
if [ ! -f ./$NAME/$CRT ]; then
   echo "[ERROR]: Client Public Key Certificate not found: ./$NAME/$CRT"
   exit
fi
echo "Client's cert found: ./$NAME/$CRT"

#Then, verify that there is a private key for that client
if [ ! -f ./$NAME/$KEY ]; then
   echo "[ERROR]: Client 3des Private Key not found: ./$NAME/$KEY"
   exit
fi
echo "Client's Private Key found: ./$NAME/$KEY"

#Confirm the CA public key exists
if [ ! -f $kRootPath$CA ]; then
   echo "[ERROR]: CA Public Key not found: $kRootPath$CA"
   exit
fi
echo "CA public Key found: $kRootPath$CA"

#Confirm the tls-auth ta key file exists
if [ ! -f $kRootPath$TA ]; then
   echo "[ERROR]: tls-auth Key not found: $kRootPath$TA"
   exit
fi
echo "tls-auth Private Key found: $kRootPath$TA"

#Ready to make a new .opvn file - Start by populating with the

cat $DEFAULT > $NAME$FILEEXT

#Now, append the CA Public Cert
echo "<ca>" >> $NAME$FILEEXT
cat $kRootPath$CA | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> $NAME$FILEEXT
echo "</ca>" >> $NAME$FILEEXT

#Next append the client Public Cert
echo "<cert>" >> $NAME$FILEEXT
cat ./$NAME/$CRT | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> $NAME$FILEEXT
echo "</cert>" >> $NAME$FILEEXT

#Then, append the client Private Key
echo "<key>" >> $NAME$FILEEXT
cat ./$NAME/$KEY >> $NAME$FILEEXT
echo "</key>" >> $NAME$FILEEXT

#Finally, append the TA Private Key
echo "key-direction 1" >> $NAME$FILEEXT
echo "<tls-auth>" >> $NAME$FILEEXT
cat $kRootPath$TA >> $NAME$FILEEXT
echo "</tls-auth>" >> $NAME$FILEEXT

echo "Done! $NAME$FILEEXT Successfully Created."

#Script written by Eric Jodoin
#Update by Eric Maasdorp 2017-12-16
#Update by Daniil V. Savenkov 2024-02-13

При запуске скрипт попросит указать имя директории клиента, для которого создаётся ovpn файл, листинг запуска получается примерно следующий:

./MakeOvpnConfig.sh
Please enter an existing Client Name folder:
client1
Client's cert found: ./client1/client.crt
Client's Private Key found: ./client1/client.key
CA public Key found: /etc/openvpn/ca.crt
tls-auth Private Key found: /etc/openvpn/ta.key
Done! client1.ovpn Successfully Created.

Скачать полученный файл с сервера можно любым удобным способом, через FTP, или используя mobaXterm.

Проверка подключения на Windows

На клиенте устанавливается клиент OpenVPN соответствующей разрядности. В нашем случае была установлена версия openvpn-connect-3.4.4.3412 и предварительно получен файл клиента в формате ovpn. Открываем интерфейс клиента, переходим на вкладку UploadFile, выбираем полученную конфигурацию и загружаем её в клиента.

Импорт полученного профиля в формате ovpn

Можем нажать Connect и проверить соединение с сервером. При успешном соединении приложение покажет статус Connected:

Успешное соединение клиента OpenVPN под Windows

Используемые материалы

Для создания заметки использованы материалы следующих статей: Настройка OpenVPN в Ubuntu 20.04, Как настроить OpenVPN Server на Ubuntu 20.04, Настройка OpenVPN сервера на Ubuntu 20.04, OpenVPN Client Export Package. Представленная конфигурация проверена и работоспособна на момент публикации заметки.