OpenVPN на Ubuntu 24.04: Полное руководство без граблей

Введение

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

Что мы получим в итоге

Серверная часть:

  • Ubuntu 24.04 с OpenVPN 2.6.14
  • Easy-RSA 3.1.7 для управления PKI
  • Порт: 11940/UDP (настраиваемый)
  • Виртуальная подсеть: 10.9.0.0/24
  • Шифрование: AES-128-GCM с SHA256
  • DNS: AdGuard DNS (94.140.14.14, 94.140.15.15)
  • Полный NAT и маршрутизация через VPN

Клиентская часть:

  • Корректные .ovpn профили для всех платформ
  • Поддержка роутеров, iPhone, Android, macOS, Windows
  • Проверенная работа с Passepartout и OpenVPN Connect

Анатомия проблем и их решения

Проблема №1: ./easyrsa: No such file or directory

Суть проблемы: Пакет easy-rsa установлен через apt, но исполняемый скрипт и шаблоны не копируются автоматически в рабочий каталог /etc/openvpn/easy-rsa.

Решение:

install -d -m 700 /etc/openvpn/easy-rsa
if [ ! -f /etc/openvpn/easy-rsa/easyrsa ]; then
  cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
fi

Проблема №2: No Easy-RSA ‘vars’ configuration file exists

Суть проблемы: Это не ошибка, а предупреждение. Easy-RSA 3 работает без файла vars, особенно с EASYRSA_BATCH=1.

Ошибка, которой нужно избегать:

# НЕПРАВИЛЬНО - вызовет Option conflict
EASYRSA_REQ_CN="server" ./easyrsa build-server-full server nopass

Правильное использование:

# CA создаём с CN
EASYRSA_BATCH=1 ./easyrsa build-ca nopass

# Серверный и клиентские сертификаты - без внешнего CN
EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass
EASYRSA_BATCH=1 ./easyrsa build-client-full client1 nopass

Проблема №3: OpenVPN активен, но tun0 не создаётся

Возможные причины:

  1. Конфигурационный файл не найден или содержит ошибки
  2. Указанные файлы сертификатов не существуют
  3. Неправильные права доступа на ключи

Диагностика:

# Проверка синтаксиса конфига
openvpn --config /etc/openvpn/server/server.conf --test-parse

# Проверка статуса службы
systemctl status openvpn-server@server --no-pager -n 20

# Поиск ошибок в журнале
journalctl -u openvpn-server@server -n 50

Проблема №4: Конфликт nftables и iptables-nft

Суть проблемы: На системах с iptables-nft попытка использовать команды nft напрямую приводит к предупреждению:

Warning: table ip nat is managed by iptables-nft, do not touch!

Решение: Использовать только iptables команды, даже если за кулисами работает nftables:

WAN_IF="$(ip route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}')"

# Добавляем NAT через iptables
iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o "$WAN_IF" -j MASQUERADE

# Сохраняем правила
netfilter-persistent save

Проблема №5: Повреждённые клиентские профили (ГЛАВНАЯ ПРОБЛЕМА!)

Симптомы:

  • iOS-клиенты (Passepartout, OpenVPN Connect) зависают на «Активация»
  • Ошибка в логах клиента: PEM routines::no start line
  • В серверных логах нет попыток подключения от этого клиента
  • Роутеры подключаются нормально (используют старые корректные профили)

Диагностика:

# Проверка CA в профиле (должна быть OK)
awk '/<ca>/{flag=1;next}/<\/ca>/{flag=0}flag' client.ovpn | \
  openssl x509 -noout -text | head -5

# Проверка клиентского сертификата (здесь будет ошибка!)
awk '/<cert>/{flag=1;next}/<\/cert>/{flag=0}flag' client.ovpn | \
  openssl x509 -noout -text | head -5
# Unable to load certificate ← ПЛОХО!

Причина: Использование sed с heredoc и неправильное экранирование приводило к обрезанию PEM-блоков:

# НЕПРАВИЛЬНО - приводит к битым сертификатам
cat >profile.ovpn <<EOF
<cert>
$(sed -ne '/BEGIN CERTIFICATE/,\$p' "$CRT")  # Ошибка здесь!
</cert>
EOF

ПРАВИЛЬНОЕ решение: Использовать последовательные операции cat без подстановок:

# ПРАВИЛЬНО - гарантированно корректные PEM-блоки
cat >profile.ovpn <<'EOF'
<cert>
EOF

cat "$CRT" >> profile.ovpn

cat >>profile.ovpn <<'EOF'
</cert>
EOF

Архитектура финальной инфраструктуры

Internet
    │
    ├─→ VPS Server (X.X.X.X)
    │   ├─→ OpenVPN Server (11940/UDP)
    │   │   ├─→ tun0 (10.9.0.1/24)
    │   │   ├─→ NAT → eth0
    │   │   └─→ PKI (Easy-RSA)
    │   │
    │   └─→ /root/
    │       ├─→ bootstrap_openvpn.sh (установка)
    │       ├─→ make_client.sh (генерация клиентов)
    │       └─→ ovpn/
    │           ├─→ client1.ovpn
    │           ├─→ iphone-ios.ovpn
    │           └─→ laptop.ovpn
    │
    └─→ Clients
        ├─→ Router (10.9.0.2)
        ├─→ iPhone (10.9.0.3)
        ├─→ Laptop (10.9.0.4)
        └─→ ...

Полный установочный скрипт

Создайте файл /root/bootstrap_openvpn.sh:

#!/usr/bin/env bash
set -euo pipefail

# --- Настройки, можно изменить перед запуском ---
PORT="${PORT:-11940}"
SUBNET="${SUBNET:-10.9.0.0/24}"
DNS1="${DNS1:-94.140.14.14}"
DNS2="${DNS2:-94.140.15.15}"
CLIENT_NAME="${CLIENT_NAME:-client1}"

echo "==> Установка пакетов"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y openvpn easy-rsa iptables-persistent curl

# --- Easy-RSA / PKI ---
echo "==> Настройка Easy-RSA и PKI"
install -d -m 700 /etc/openvpn/easy-rsa
cd /etc/openvpn/easy-rsa

# Если скрипты Easy-RSA не скопированы — копируем из /usr/share/easy-rsa
if [ ! -f "./easyrsa" ]; then
  echo "==> Копирую шаблон Easy-RSA"
  cp -r /usr/share/easy-rsa/* .
fi

# Инициализируем PKI, если её ещё нет
if [ ! -d "pki" ]; then
  echo "==> init-pki"
  ./easyrsa init-pki
fi

# CA
if [ ! -f "pki/ca.crt" ]; then
  echo "==> build-ca"
  EASYRSA_BATCH=1 ./easyrsa build-ca nopass
fi

# Серверный сертификат
if [ ! -f "pki/issued/server.crt" ]; then
  echo "==> build-server-full server"
  EASYRSA_BATCH=1 ./easyrsa build-server-full server nopass
fi

# DH
if [ ! -f "pki/dh.pem" ]; then
  echo "==> gen-dh"
  ./easyrsa gen-dh
fi

# CRL
if [ ! -f "pki/crl.pem" ]; then
  echo "==> gen-crl"
  ./easyrsa gen-crl
fi

install -d -m 755 /etc/openvpn/easy-rsa/pki
install -m 644 pki/crl.pem /etc/openvpn/easy-rsa/pki/crl.pem

# --- tls-crypt и каталоги OpenVPN ---
echo "==> tls-crypt и каталоги OpenVPN"
install -d -m 755 /etc/openvpn/server
install -d -m 755 /etc/openvpn/ccd
install -d -m 755 /var/log/openvpn

if [ ! -f /etc/openvpn/server/tls-crypt.key ]; then
  openvpn --genkey --secret /etc/openvpn/server/tls-crypt.key
fi

# --- server.conf ---
echo "==> Создаю /etc/openvpn/server/server.conf"
BASE_NET="${SUBNET%/*}"

cat >/etc/openvpn/server/server.conf <<CONF
port ${PORT}
proto udp
dev tun

user nobody
group nogroup
persist-key
persist-tun
keepalive 10 120
topology subnet

server ${BASE_NET} 255.255.255.0

push "redirect-gateway def1"
push "dhcp-option DNS ${DNS1}"
push "dhcp-option DNS ${DNS2}"

tls-crypt /etc/openvpn/server/tls-crypt.key
dh /etc/openvpn/easy-rsa/pki/dh.pem
crl-verify /etc/openvpn/easy-rsa/pki/crl.pem
ca  /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key  /etc/openvpn/easy-rsa/pki/private/server.key

auth SHA256
cipher AES-128-GCM
ncp-ciphers AES-128-GCM
tls-server
tls-version-min 1.2

client-config-dir /etc/openvpn/ccd
status /var/log/openvpn/status.log
verb 3
CONF

# --- IPv4 forwarding ---
echo "==> Включаю IPv4 forwarding"
sysctl -w net.ipv4.ip_forward=1 >/dev/null
echo 'net.ipv4.ip_forward=1' >/etc/sysctl.d/99-openvpn.conf

# --- NAT через iptables ---
echo "==> Настройка NAT (iptables)"
WAN_IF="$(ip route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}')"
echo "    WAN_IF=${WAN_IF}"

# Маскарадинг для подсети VPN
if ! iptables -t nat -C POSTROUTING -s "${SUBNET}" -o "${WAN_IF}" -j MASQUERADE 2>/dev/null; then
  iptables -t nat -A POSTROUTING -s "${SUBNET}" -o "${WAN_IF}" -j MASQUERADE
fi

# Сохраняем правила
if command -v netfilter-persistent >/dev/null 2>&1; then
  netfilter-persistent save
else
  iptables-save >/etc/iptables/rules.v4
fi

# --- Запуск OpenVPN ---
echo "==> Запуск OpenVPN"
systemctl enable openvpn-server@server
systemctl restart openvpn-server@server

# Даём время на запуск
sleep 2

echo "==> Проверка слушателя (udp/${PORT}) и tun0"
ss -lunp | grep -w ":${PORT}" || echo "ВНИМАНИЕ: порт ${PORT}/udp пока не виден в ss"
ip addr show tun0 || echo "ВНИМАНИЕ: интерфейс tun0 пока не найден"

# --- Скрипт для клиентов /root/make_client.sh ---
echo "==> Создаю /root/make_client.sh"
cat >/root/make_client.sh <<'CLI'
#!/usr/bin/env bash
set -euo pipefail

NAME="${1:-client1}"
OUT_DIR="/root/ovpn"
PORT="${PORT:-11940}"
HOST="${HOST:-$(curl -4 -s ifconfig.me)}"
EASYRSA_DIR="/etc/openvpn/easy-rsa"
TLS_KEY="/etc/openvpn/server/tls-crypt.key"

install -d -m 755 "$OUT_DIR"

cd "$EASYRSA_DIR"

if [ ! -f "pki/issued/${NAME}.crt" ]; then
  echo "==> Выпускаю новый сертификат для клиента: ${NAME}"
  EASYRSA_BATCH=1 ./easyrsa build-client-full "${NAME}" nopass
else
  echo "==> Сертификат для ${NAME} уже существует, использую его"
fi

CRT="pki/issued/${NAME}.crt"
KEY="pki/private/${NAME}.key"
CA="pki/ca.crt"

OUT="${OUT_DIR}/${NAME}.ovpn"

echo "==> Собираю профиль: ${OUT}"

# КРИТИЧЕСКИ ВАЖНО: используем последовательные cat без подстановок!
cat >"$OUT" <<EOF
client
dev tun
proto udp
remote ${HOST} ${PORT}
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-128-GCM
auth SHA256
key-direction 1
verb 3

<ca>
EOF

cat "$CA" >>"$OUT"

cat >>"$OUT" <<'EOF'
</ca>
<cert>
EOF

cat "$CRT" >>"$OUT"

cat >>"$OUT" <<'EOF'
</cert>
<key>
EOF

cat "$KEY" >>"$OUT"

cat >>"$OUT" <<'EOF'
</key>
<tls-crypt>
EOF

cat "$TLS_KEY" >>"$OUT"

cat >>"$OUT" <<'EOF'
</tls-crypt>
EOF

echo "✅ Профиль создан: ${OUT}"
echo "   Пример копирования на Mac: scp root@${HOST}:${OUT} ./"
CLI

chmod +x /root/make_client.sh

# --- Первый клиент ---
echo "==> Создаю первого клиента: ${CLIENT_NAME}"
/root/make_client.sh "${CLIENT_NAME}"

echo
echo "✅ Готово!"
echo "  - Статус OpenVPN: systemctl status openvpn-server@server --no-pager -n 20"
echo "  - Порт:           ${PORT}/udp; сеть: ${SUBNET}; DNS: ${DNS1}, ${DNS2}"
echo "  - Клиентский .ovpn: /root/ovpn/${CLIENT_NAME}.ovpn"
echo "  - Скачать на Mac:  scp root@\$(curl -4 -s ifconfig.me):/root/ovpn/${CLIENT_NAME}.ovpn ./"
echo

Сделайте скрипт исполняемым:

chmod +x /root/bootstrap_openvpn.sh

Пошаговая установка

Шаг 1: Подготовка сервера

# Подключитесь к серверу по SSH
ssh root@YOUR_SERVER_IP

# Создайте установочный скрипт (скопируйте содержимое выше)
nano /root/bootstrap_openvpn.sh
chmod +x /root/bootstrap_openvpn.sh

Шаг 2: Запуск установки

С параметрами по умолчанию:

/root/bootstrap_openvpn.sh

С кастомными настройками:

PORT=1194 SUBNET=10.8.0.0/24 CLIENT_NAME=myrouter /root/bootstrap_openvpn.sh

Шаг 3: Проверка установки

# 1. Статус службы
systemctl status openvpn-server@server --no-pager -n 20
# Ожидаем: active (running) и "Initialization Sequence Completed"

# 2. Сетевой интерфейс
ip addr show tun0
# Ожидаем: inet 10.9.0.1/24

# 3. Прослушиваемый порт
ss -lunp | grep 11940
# Ожидаем: udp UNCONN 0 0 0.0.0.0:11940 ... users:(("openvpn",pid=...))

# 4. IP forwarding
sysctl net.ipv4.ip_forward
# Ожидаем: net.ipv4.ip_forward = 1

# 5. NAT правила
iptables -t nat -L POSTROUTING -n -v | grep 10.9.0.0
# Ожидаем: строку с MASQUERADE для 10.9.0.0/24

# 6. Клиентские конфигурации
ls -lh /root/ovpn/
# Ожидаем: client1.ovpn

Шаг 4: Создание дополнительных клиентов

# Для iPhone
/root/make_client.sh iphone-ios

# Для ноутбука
/root/make_client.sh laptop-work

# Для планшета
/root/make_client.sh ipad-home

# Проверить список
ls -lh /root/ovpn/

Шаг 5: Проверка корректности клиентских профилей

ОБЯЗАТЕЛЬНО проверяйте профили перед отправкой клиентам!

cd /root/ovpn

# Проверка CA (должна быть OK)
awk '/<ca>/{flag=1;next}/<\/ca>/{flag=0}flag' iphone-ios.ovpn | \
  openssl x509 -noout -text | head -5

# Проверка клиентского сертификата (должна быть OK)
awk '/<cert>/{flag=1;next}/<\/cert>/{flag=0}flag' iphone-ios.ovpn | \
  openssl x509 -noout -text | head -5

# Проверка ключа (должна быть OK)
awk '/<key>/{flag=1;next}/<\/key>/{flag=0}flag' iphone-ios.ovpn | \
  openssl rsa -noout -check 2>&1 | head -5

Хорошие результаты:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
        Signature Algorithm: sha256WithRSAEncryption

Плохие результаты (битый профиль!):

unable to load certificate
Could not read certificate from stdin
PEM routines::no start line

Использование клиентских конфигураций

Скачивание с сервера

На macOS/Linux:

scp root@YOUR_SERVER_IP:/root/ovpn/iphone-ios.ovpn ./

На Windows (PowerShell):

scp root@YOUR_SERVER_IP:/root/ovpn/laptop-work.ovpn C:\Users\YourName\Downloads\

Настройка клиентов

iOS (iPhone/iPad):

  1. Установите OpenVPN Connect или Passepartout из App Store
  2. Отправьте .ovpn файл через AirDrop или Files
  3. Откройте файл → выберите приложение VPN
  4. Импортируйте профиль и подключитесь

macOS:

  1. Установите Tunnelblick или OpenVPN Connect
  2. Импортируйте .ovpn файл
  3. Подключитесь к VPN

Android:

  1. Установите OpenVPN for Android
  2. Импортируйте .ovpn через меню приложения
  3. Подключитесь

Windows:

  1. Установите OpenVPN GUI
  2. Скопируйте .ovpn в C:\Program Files\OpenVPN\config\
  3. Запустите OpenVPN GUI и подключитесь

Linux:

sudo openvpn --config client1.ovpn

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

На клиенте после подключения:

# Проверка VPN-интерфейса
ip addr show tun0
# Должен быть адрес из диапазона 10.9.0.0/24

# Проверка маршрута
ip route | grep tun0
# Должен быть default через tun0

# Проверка DNS
cat /etc/resolv.conf | grep nameserver
# Должны быть DNS от VPN (94.140.14.14, 94.140.15.15)

# Проверка публичного IP
curl ifconfig.me
# Должен показать IP VPN-сервера, а не реальный IP клиента

На iPhone: Откройте Safari и перейдите на https://ifconfig.me — должен показать IP вашего сервера.

Диагностика проблем

Сервер не запускается

# Детальные логи
journalctl -u openvpn-server@server -n 100 --no-pager

# Проверка конфигурации
openvpn --config /etc/openvpn/server/server.conf --test-parse

# Проверка сертификатов
openssl x509 -in /etc/openvpn/easy-rsa/pki/issued/server.crt -noout -text
openssl rsa -in /etc/openvpn/easy-rsa/pki/private/server.key -check

Клиент не может подключиться

На сервере:

# Мониторинг логов в реальном времени
tail -f /var/log/openvpn/status.log
journalctl -u openvpn-server@server -f

# Проверка активных подключений
cat /var/log/openvpn/status.log | grep CLIENT_LIST

Типичные ошибки клиентов:

  1. PEM routines::no start line
    • Битый .ovpn профиль
    • Решение: пересоздать профиль через make_client.sh
  2. TLS Error: TLS key negotiation failed
    • Неправильный tls-crypt ключ
    • Решение: проверить, что ключ в профиле совпадает с серверным
  3. Connection timeout
    • Порт заблокирован файрволом
    • Решение: открыть порт через UFW/firewalld
  4. AUTH_FAILED
    • Сертификат отозван или истёк
    • Решение: проверить CRL, создать новый сертификат

Нет интернета через VPN

# Проверка IP forwarding
sysctl net.ipv4.ip_forward
# Должно быть = 1

# Проверка NAT
iptables -t nat -L POSTROUTING -n -v
# Должно быть правило MASQUERADE для 10.9.0.0/24

# Проверка интерфейсов
ip addr show tun0
ip addr show eth0  # или ваш WAN интерфейс

# Тест с клиента
ping -c 3 10.9.0.1  # должен пинговаться VPN-шлюз
ping -c 3 8.8.8.8   # должен пинговаться интернет

Обслуживание и мониторинг

Просмотр подключённых клиентов

# Текущий статус
cat /var/log/openvpn/status.log

# Только список клиентов
grep "^CLIENT_LIST" /var/log/openvpn/status.log | \
  awk '{print $2, $3, $4, $5}'

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

cd /etc/openvpn/easy-rsa

# Отозвать сертификат
./easyrsa revoke client-to-revoke

# Обновить CRL
./easyrsa gen-crl
install -m 644 pki/crl.pem /etc/openvpn/easy-rsa/pki/crl.pem

# Перезапустить сервер
systemctl restart openvpn-server@server

Ротация логов

Создайте /etc/logrotate.d/openvpn:

/var/log/openvpn/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        systemctl reload openvpn-server@server > /dev/null 2>&1 || true
    endscript
}

Мониторинг через systemd

# Автоматический перезапуск при падении
systemctl edit openvpn-server@server

# Добавить:
[Service]
Restart=always
RestartSec=10

Оптимизация производительности

Настройка MTU для мобильных сетей

В /etc/openvpn/server/server.conf:

tun-mtu 1400
fragment 1300
mssfix 1300

Увеличение буферов для высокоскоростных каналов

sndbuf 393216
rcvbuf 393216
push "sndbuf 393216"
push "rcvbuf 393216"

Использование TCP для обхода блокировок

Если UDP блокируется провайдером:

# В server.conf
proto tcp-server
port 443  # Маскируемся под HTTPS

# В клиентском профиле
proto tcp-client
remote SERVER_IP 443

Безопасность

Дополнительные меры защиты

1. Ограничение прав на конфиденциальные файлы:

chmod 600 /etc/openvpn/server/tls-crypt.key
chmod 600 /etc/openvpn/easy-rsa/pki/private/*.key

2. Автоматическое обновление CRL:

cat > /etc/cron.daily/openvpn-crl <<'EOF'
#!/bin/bash
cd /etc/openvpn/easy-rsa
./easyrsa gen-crl
install -m 644 pki/crl.pem /etc/openvpn/easy-rsa/pki/crl.pem
systemctl reload openvpn-server@server
EOF

chmod +x /etc/cron.daily/openvpn-crl

3. Fail2Ban для защиты от брутфорса:

apt-get install -y fail2ban

cat > /etc/fail2ban/filter.d/openvpn.conf <<'EOF'
[Definition]
failregex = ^.*TLS Error: TLS handshake failed.*<HOST>
            ^.*VERIFY ERROR.*<HOST>
ignoreregex =
EOF

cat > /etc/fail2ban/jail.d/openvpn.conf <<'EOF'

[openvpn]

enabled = true port = 11940 protocol = udp filter = openvpn logpath = /var/log/openvpn/*.log maxretry = 3 bantime = 3600 EOF systemctl restart fail2ban

4. Ограничение по количеству одновременных подключений:

В server.conf:

max-clients 10

5. Принудительное переподключение клиентов для применения обновлений:

# Отключить всех клиентов
systemctl restart openvpn-server@server

Резервное копирование

Что нужно сохранять

# Создать архив PKI и конфигов
tar czf openvpn-backup-$(date +%Y%m%d).tar.gz \
  /etc/openvpn/easy-rsa/pki \
  /etc/openvpn/server/server.conf \
  /etc/openvpn/server/tls-crypt.key \
  /root/make_client.sh

# Скачать на локальный компьютер
scp root@SERVER_IP:openvpn-backup-*.tar.gz ./

Восстановление на новом сервере

# Установить пакеты
apt-get install -y openvpn easy-rsa iptables-persistent

# Распаковать бэкап
tar xzf openvpn-backup-20240101.tar.gz -C /

# Запустить сервер
systemctl enable openvpn-server@server
systemctl start openvpn-server@server

# Настроить NAT (как в bootstrap скрипте)

Масштабирование

Несколько серверов OpenVPN

Для географически распределённой инфраструктуры:

# Сервер в Европе: 10.9.0.0/24
# Сервер в США: 10.10.0.0/24
# Сервер в Азии: 10.11.0.0/24

Каждый сервер работает независимо. Клиенты могут иметь профили для всех локаций.

Балансировка нагрузки

Round-robin DNS:

vpn.example.com → 1.2.3.4 (TTL 300)
vpn.example.com → 5.6.7.8 (TTL 300)

В клиентском профиле:

remote vpn.example.com 11940
remote-random

Чек-лист для развёртывания

  • [ ] Сервер Ubuntu 24.04 с root-доступом
  • [ ] Открыт порт в файрволе (UFW/firewalld)
  • [ ] Скопирован и запущен bootstrap_openvpn.sh
  • [ ] Служба active (running)
  • [ ] Интерфейс tun0 создан (10.9.0.1/24)
  • [ ] Порт слушается (ss -lunp | grep 11940)
  • [ ] IP forwarding включен (sysctl net.ipv4.ip_forward = 1)
  • [ ] NAT правило добавлено (iptables -t nat -L)
  • [ ] Создан и проверен клиентский профиль
  • [ ] Сертификаты в .ovpn корректны (openssl проверка)
  • [ ] Клиент успешно подключился
  • [ ] Клиент получил IP из VPN подсети
  • [ ] Интернет работает через VPN (curl ifconfig.me)
  • [ ] Настроено резервное копирование PKI
  • [ ] Настроен мониторинг (опционально)

Заключение

Это руководство основано на реальном опыте с подробным разбором всех возникших проблем. Основная «граблевая» проблема — повреждение PEM-блоков в клиентских конфигурациях при использовании sed с heredoc. Решение простое: использовать последовательные операции cat без подстановок.

Ключевые выводы

  1. Всегда используйте EASYRSA_BATCH=1 для автоматизации
  2. Не передавайте CN для server/client сертификатов через переменные
  3. Используйте iptables для NAT, даже если система использует nftables
  4. Собирайте .ovpn через последовательные cat, не через sed с подстановками
  5. Всегда проверяйте профили через openssl перед отправкой клиентам
  6. Разделяйте установку и генерацию клиентов на разные скрипты
  7. Делайте резервные копии PKI — это единственная точка отказа

Полезные ссылки