Skip to content

OpenVPN и Easy-RSA

Развертывание CA сервера (EasyRSA)

CA (Certification Authority) = ЦС (Центр Сертификации) = Удостоверяющий центр
В криптографии это сторона, чья честность неоспорима, а public key широко известен. Это компонент, отвечающий за управление криптографическими ключами юзеров.
Ее задача - подтверждать подлинность ключей шифрования с помощью сертификатов электронной подписи. Открытые ключи и др. инфа о юзерах хранится центрами сертификации в виде цифровых сертификатов.
[[Lets Encrypt]] - тот же CA.

Bash
sudo apt install easy-rsa -y
mkdir ${HOME}/easy-rsa
ln -s /usr/share/easy-rsa/* ${HOME}/easy-rsa/
sudo chown $USER ${HOME}/easy-rsa
chmod 700 ${HOME}/easy-rsa
cd ${HOME}/easy-rsa
./easyrsa init-pki
cp vars.example pki/vars

./easyrsa init-pki создал директорию инфраструктуры открытых ключей (PKI - Public Key Infrastructure).
Все готово для создания CA - значит, пора создавать пару "секретный ключ и сертификат".

Сначала edit the vars (нужно для содержимого сертификата):

Text Only
# OpenVPN и Easy-RSA

set_var EASYRSA_REQ_COUNTRY "RUS"
set_var EASYRSA_REQ_PROVINCE "Moscow"
set_var EASYRSA_REQ_CITY "Moscow"
set_var EASYRSA_REQ_ORG "SomeCompany"
set_var EASYRSA_REQ_EMAIL "admin@SomeCompany.net"
set_var EASYRSA_REQ_OU "LLC"
# Информация выше никак не влияет на функциональность CA,
# она будет отражена в содержимом сертификата

set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

Build the CA:

Bash
./easyrsa build-ca
# Нужно будет ввести passphrase, остальная инфа возьмется из pki/vars

Появится pki/ca.crt - открытый ключ CA. Он будет использоваться клиентами и серверами для проверки при авторизации.
Его нужно будет доставить и на сервер OpenVPN, в нашем случае.

На этом с развертыванием CA сервера. Дальше на нем можно будет подписывать запросы сертификатов.

Подпись запроса серверных сертификатов (тип запроса: server)

Bash
./easyrsa sign-req server server
# Подпись request-а на серверный сертификат сервера "server"

Пример:
Bash
# Передача на CA сервер запроса, подпись там и возврат на VPN сервер
scp -P 2478 pki/reqs/server.req test@192.168.1.11:/home/test/easy-rsa/pki/reqs/
ssh test@192.168.1.11 -p 2478 "cd ${HOME}/easy-rsa && ./easyrsa sign-req server server"
scp -P 2478 test@192.168.1.11:${HOME}/easy-rsa/pki/issued/server.crt .

В чем смысл подписи?

Полученный файл server.crt​​​ содержит открытый ключ шифрования сервера OpenVPN, а также новую подпись от сервера ЦС.
Смысл подписи состоит в том, чтобы сообщить всем, кто доверяет серверу ЦС, что они также могут доверять серверу OpenVPN при подключении к нему.

Подпись запроса клиентских сертификатов (тип запроса: client)

Bash
./easyrsa sign-req client SomeClient
# Подпись request-а на клиентский сертификат клиента "SomeClient"

Развертывание VPN сервера (OpenVPN)

У OpenVPN есть 3 вида аутентификации:
1. Предустановленный ключ
2. Аутентификация по сертификатам
Для шифрования соединения и клиент, и сервер юзают сертификаты
3. Аутентификация с помощью пары "логин и пароль"
Может использоваться без создания сертификата для клиента, но серверный сертификат всё равно нужен

Буду использовать аутентификацию по сертификатам - способ, который наиболее гибок в настройках.

Bash
sudo apt install easy-rsa openvpn -y

Здесь EasyRSA нужен чисто для создания запросов.

Bash
mkdir ${HOME}/easy-rsa
ln -s /usr/share/easy-rsa/* ${HOME}/easy-rsa/
sudo chown "$USER":"$USER" ${HOME}/easy-rsa
chmod 700 ${HOME}/easy-rsa
cd ${HOME}/easy-rsa
./easyrsa init-pki

Генерация запроса на серверный сертификат

Bash
./easyrsa gen-req server nopass
# Passphrase

Этой командой создадутся файл запроса на серверный сертификат (server.req) и секретный ключ (server.key).

!! Нужно передать этот запрос (server.req) на сервер CA, подписать там и забрать сертификат (server.crt) :
[[#Подпись запроса серверных сертификатов (тип запроса server)]]

P.S. Это еще и безопасно тем, что запрос и подписанный сертификат не являются секретными данными - можно спокойно осуществлять передачу.

TLS Crypt

Для доп. защиты нужно создать доп. секретный ключ для аутентификации и шифрования данных, передаваемых между клиентом и сервером OpenVPN (что и зовется TLS Crypt):

Bash
openvpn --genkey secret ta.key
sudo chown $USER:$USER ta.key

Теперь нужно положить указанные файлы в папку с конфигами OpenVPN (/etc/openvpn/server/):
+ серверный сертификат (server.crt)
+ секретный ключ сервера (server.key)
+ сертификат CA (ca.crt)
+ секретный ключ для TLS Crypt (ta.key)

Bash
sudo cp path/to/server.crt path/to/server.key path/to/ca.crt path/to/ta.key /etc/openvpn/server

Генерация клиентских сертификатов

Bash
mkdir -p ${HOME}/clients/{keys,files}
chmod -R 700 ${HOME}/clients
cd ${HOME}/easy-rsa
./easyrsa gen-req SomeClient nopass
cp pki/private/SomeClient.key ${HOME}/clients/keys

\<Подпись запроса>
[[#Подпись запроса клиентских сертификатов (тип запроса client)]]

После подписи запроса:

Bash
cp path/to/ta.key path/to/SomeClient.crt path/to/SomeClient.key path/to/ca.crt ${HOME}/clients/keys
sudo chown "$USER":"$USER" ${HOME}/clients/keys

Конфигурация OpenVPN и системы (для работы VPN)

Соус server.conf: /usr/share/doc/openvpn/examples/sample-config-files/server.conf

Содержимое моего конфига /etc/openvpn/server/server.conf:

Bash
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh none
server 10.8.0.0 255.255.255.0
keepalive 10 120
tls-crypt ta.key
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup
persist-key
persist-tun
verb 3
explicit-exit-notify 1
ifconfig-pool-persist /var/log/openvpn/ipp.txt
status /var/log/openvpn/openvpn-status.log
log /var/log/openvpn/openvpn.log

Включение IPv4 forwarding (чтобы vpn работал):

Bash
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Firewall (ufw):

Bash
sudo ufw allow 1194/udp
sudo ufw reload

iptables.sh:

Bash
#!/usr/bin/env bash

eth="$1"
proto="$2"
port="$3"

# OpenVPN
iptables \
    -A INPUT -i "$eth" -m state --state NEW \
    -p "$proto" --dport "$port" -j ACCEPT

# Allow TUN interface connections to OpenVPN server
iptables -A INPUT -i tun+ -j ACCEPT

# Allow TUN interface connections to be forwarded through other interfaces
iptables -A FORWARD -i tun+ -j ACCEPT
iptables \
    -A FORWARD -i tun+ -o "$eth" \
    -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables \
    -A FORWARD -i "$eth" -o tun+ \
    -m state --state RELATED,ESTABLISHED -j ACCEPT

# NAT the VPN client traffic to the internet
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o "$eth" -j MASQUERADE

Usage:

Bash
sudo ./iptables4openvpn.sh <net_interface_name> udp 1194

Запуск OpenVPN

Bash
sudo systemctl -f enable openvpn-server@server.service
sudo systemctl restart openvpn-server@server.service
sudo systemctl status openvpn-server@server.service

Клиентские конфиг-файлы (.ovpn)

Соус client.conf: /usr/share/doc/openvpn/examples/sample-config-files/client.conf

Вот мой шаблон клиентского конфига client.conf:

Bash
client
dev tun
proto udp
remote remote_server_ip 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
key-direction 1
verb 3
;tls-crypt ta.key 1

Надо будет поменять remote_server_ip на IP адрес VPN сервера:

Bash
VPN_SERVER_IP="$(dig +short myip.opendns.com @resolver1.opendns.com)"
sed -i "s/remote_server_ip/${VPN_SERVER_IP}/" client.conf

На digitalocean предоставили такой скрипт для создания клиентских конфигов (.ovpn файлов):

Bash
#!/usr/bin/env bash

# First argument: Client identifier
KEY_DIR=${HOME}/clients/keys
OUTPUT_DIR=${HOME}/clients/files
BASE_CONFIG=${HOME}/clients/client.conf

cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-crypt>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-crypt>') \
    > ${OUTPUT_DIR}/${1}.ovpn

Usage:

Bash
./make_ovpn.sh SomeClient

Создастся конфиг ~/client-configs/files/SomeClient.ovpn, который содержит:
+ Сертификат CA сервера (ca.crt)
+ Клиентский сертификат (SomeClient.crt)
+ Клиентский секретный ключ (SomeClient.crt)
+ Секретный ключ для TLS Crypt (ta.key)

Всё, осталось его доставить на нужное устройство (которое хочет подключится к VPN) и импортировать этот .ovpn файл в клиентское приложение OpenVPN.


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

Соус: https://www.digitalocean.com/community/tutorials/how-to-set-up-and-configure-an-openvpn-server-on-ubuntu-20-04-ru#15


Troubleshoot

Если проблемы с tls-crypt: [[OpenVPN tls-crypt unwrap error]]


Соусы:
Скиллбокс - модуль 24
[[Нераздельная легкая установка OpenVPN + EasyRSA]]
Гайд от digitalocean
Гайд из github-а EasyRSA

VPN #openvpn #easyrsa #pki