Настройка VPN-сервера с обфускацией трафика
Краткое руководство по настройке VPN-сервера OpenConnect на AlmaLinux в связке с SNI-прокси на NGINX для обфускации трафика.
SNI-прокси (Server Name Indication) даёт дополнительный слой обфускации: трафик выглядит как обычный HTTPS. Это особенно выручает в странах и сетях, где VPN-трафик активно блокируют и анализируют.
Важно понимать, что это решение — не панацея. С большинством сервисов, которыми я пользуюсь сам, обфускация работает, но некоторые её всё же распознают. Например, OpenAI довольно неплохо вычисляет VPN-трафик, а вот банковские сервисы его не видят, так что с ними всё работает гладко.
Для VPN я взял самый дешёвый VPS: 1 ядро, 2 ГБ оперативной памяти, 10 ГБ диска и канал 500 Мбит/с.
Шаг 1: установка необходимых пакетов
Сначала поставим пакеты, на которых мы соберём VPN и SNI-прокси. Нам понадобятся OpenConnect Server (ocserv), NGINX и OpenSSL.
sudo dnf install epel-release -y
sudo dnf install ocserv nginx openssl -y
Команда поставит на AlmaLinux свежие версии OpenConnect, NGINX и OpenSSL.
Шаг 2: создание SSL-сертификатов
И OpenConnect, и NGINX шифруют соединение, поэтому им нужны SSL-сертификаты. Можно обойтись самоподписанным, а если у вас есть домен — взять настоящий TLS-сертификат у центра сертификации.
Выполните команду — она создаст сертификат и приватный ключ:
sudo mkdir -p /etc/ocserv/ssl
sudo openssl req -newkey rsa:4096 -nodes -keyout /etc/ocserv/ssl/server.key -x509 -days 365 -out /etc/ocserv/ssl/server.crt -subj "/C=UA/ST=Kyiv/L=Kyiv/O=MyVPN/OU=IT/CN=$(hostname -I)"
Code language: JavaScript (javascript)
Сертификат ляжет в /etc/ocserv/ssl/server.crt, приватный ключ — в /etc/ocserv/ssl/server.key. Срок действия — год.
Шаг 3: настройка сервера OpenConnect
Теперь настроим сам OpenConnect — для этого нужен конфигурационный файл. По умолчанию он лежит в /etc/ocserv/ocserv.conf.
sudo tee /etc/ocserv/ocserv.conf > /dev/null <<EOF
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
tcp-port = 443
udp-port = 443
server-cert = /etc/ocserv/ssl/server.crt
server-key = /etc/ocserv/ssl/server.key
device = vpns
ipv4-network = 192.168.100.0
ipv4-netmask = 255.255.255.0
run-as-user = nobody
run-as-group = nobody
max-clients = 128
max-same-clients = 4
keepalive = 32400
dpd = 90
cisco-client-compat = true
tls-priorities = "normal"
socket-file = /var/run/ocserv-socket
dns = 8.8.8.8
dns = 8.8.4.4
EOF
Code language: JavaScript (javascript)
С такой конфигурацией OpenConnect принимает трафик на порту 443, держит до 128 клиентов и ходит за DNS к серверам Google.
Шаг 4: настройка NGINX в роли SNI-прокси
SNI-прокси на NGINX разводит трафик по имени сервера (SNI), которое клиент указал в запросе. VPN-запросы он отдаст OpenConnect, а обычный HTTP/HTTPS при необходимости уведёт на другой сервер.
sudo tee /etc/nginx/nginx.conf > /dev/null <<EOF
worker_processes 1;
events {
worker_connections 1024;
}
stream {
map $ssl_preread_server_name $backend {
vpn.example.com ocserv_backend;
default web_backend;
}
upstream ocserv_backend {
server 127.0.0.1:443;
}
upstream web_backend {
server 127.0.0.1:8443;
}
server {
listen 443;
proxy_pass $backend;
ssl_preread on;
}
}
EOF
Code language: PHP (php)
Вместо vpn.example.com подставьте свой домен или публичный IP сервера.
Шаг 5: запуск сервисов и добавление в автозагрузку
Осталось запустить оба сервиса и добавить их в автозагрузку.
sudo systemctl enable nginx
sudo systemctl enable ocserv
sudo systemctl restart nginx
sudo systemctl restart ocserv
Шаг 6: проверка состояния сервисов
Проверьте, что OpenConnect и NGINX запущены и работают:
systemctl status ocserv
systemctl status nginx
Шаг 7: добавление пользователей VPN
В OpenConnect заводятся свои пользователи VPN. Логины и пароли он держит в обычном текстовом файле (/etc/ocserv/ocpasswd). Кроме того, каждому пользователю нужен клиентский сертификат.
Добавляем пользователя и генерируем ему сертификат:
read -p "Enter VPN username: " vpn_user
sudo ocpasswd -c /etc/ocserv/ocpasswd $vpn_user
Code language: PHP (php)
Создание клиентских сертификатов и файлов PKCS#12
Каждому пользователю нужен клиентский сертификат и файл PKCS#12: в нём лежат и сертификат, и ключ, поэтому настроить клиента заметно проще:
sudo openssl req -newkey rsa:2048 -nodes -keyout /etc/ocserv/ssl/$vpn_user.key -x509 -days 365 -out /etc/ocserv/ssl/$vpn_user.crt -subj "/C=UA/ST=Kyiv/L=Kyiv/O=MyVPN/OU=IT/CN=$vpn_user"
sudo openssl pkcs12 -export -out /etc/ocserv/ssl/$vpn_user.p12 -inkey /etc/ocserv/ssl/$vpn_user.key -in /etc/ocserv/ssl/$vpn_user.crt -certfile /etc/ocserv/ssl/server.crt -password pass:$vpn_pass
Code language: PHP (php)
Файл .p12 передайте клиенту — он понадобится при настройке VPN.
Шаг 8: проверка VPN и SNI-прокси
Когда VPN-сервер настроен, проверьте, слушает ли он нужные порты:
sudo lsof -i :443 | grep LISTEN
Достучаться до VPN снаружи проще всего через curl:
curl -I https://$(hostname -I | awk '{print $1}') --insecure --max-time 10
Code language: JavaScript (javascript)
Если всё собрано верно, VPN ответит на HTTPS-запрос по порту 443.
Шаг 9: проверка шифрования VPN
Убедиться, что трафик действительно шифруется, можно перехватом через tcpdump:
sudo tcpdump -i any port 443
Между клиентом и сервером вы увидите только шифр. У любого клиента, который подключается по сертификату .p12, трафик зашифрован: вместо открытого текста в пакетах видны лишь заголовки и длина — содержимое наружу не выходит.
Скрипт автоматической установки
Если возиться вручную не хочется, возьмите готовый скрипт ниже.
Перед публикацией я прогнал этот скрипт на свежей виртуалке в Azure — вроде бы всё отработало нормально. Если наткнётесь на ошибки, напишите мне.
#!/bin/bash
# Automated OpenConnect Server and NGINX SNI Proxy Setup Script on AlmaLinux with Client Certificates (.crt, .p12)
echo "Starting the OpenConnect VPN Server and NGINX SNI Proxy installation on AlmaLinux..."
# Step 1: Install necessary packages
echo "Installing necessary packages: ocserv, nginx, and openssl..."
sudo dnf install epel-release -y
sudo dnf install ocserv nginx openssl -y
# Step 2: Check if required packages are installed
echo "Verifying package installation..."
if ! command -v ocserv &> /dev/null; then
echo "Error: OpenConnect Server (ocserv) is not installed."
exit 1
fi
if ! command -v nginx &> /dev/null; then
echo "Error: NGINX is not installed."
exit 1
fi
if ! command -v openssl &> /dev/null; then
echo "Error: OpenSSL is not installed."
exit 1
fi
echo "All required packages are installed."
# Step 3: Generate SSL certificate for OpenConnect Server and NGINX
echo "Generating SSL certificates..."
sudo mkdir -p /etc/ocserv/ssl
sudo openssl req -newkey rsa:4096 -nodes -keyout /etc/ocserv/ssl/server.key -x509 -days 365 -out /etc/ocserv/ssl/server.crt -subj "/C=US/ST=California/L=SanFrancisco/O=MyVPN/OU=IT/CN=$(hostname -I)"
# Step 4: Configure OpenConnect Server
echo "Configuring OpenConnect Server (ocserv)..."
sudo tee /etc/ocserv/ocserv.conf > /dev/null <<EOF
auth = "plain[passwd=/etc/ocserv/ocpasswd]"
tcp-port = 443
udp-port = 443
server-cert = /etc/ocserv/ssl/server.crt
server-key = /etc/ocserv/ssl/server.key
device = vpns
ipv4-network = 192.168.100.0
ipv4-netmask = 255.255.255.0
run-as-user = nobody
run-as-group = nobody
max-clients = 128
max-same-clients = 4
keepalive = 32400
dpd = 90
cisco-client-compat = true
tls-priorities = "normal"
socket-file = /var/run/ocserv-socket
dns = 8.8.8.8
dns = 8.8.4.4
EOF
# Step 5: Configure NGINX as SNI Proxy
echo "Configuring NGINX as SNI Proxy..."
sudo tee /etc/nginx/nginx.conf > /dev/null <<EOF
worker_processes 1;
events {
worker_connections 1024;
}
stream {
map $ssl_preread_server_name $backend {
vpn.example.com ocserv_backend;
default web_backend;
}
upstream ocserv_backend {
server 127.0.0.1:443;
}
upstream web_backend {
server 127.0.0.1:8443;
}
server {
listen 443;
proxy_pass $backend;
ssl_preread on;
}
}
EOF
# Step 6: Enable and restart services
echo "Enabling and restarting services (NGINX and OCserv)..."
sudo systemctl enable nginx
sudo systemctl enable ocserv
sudo systemctl restart nginx
sudo systemctl restart ocserv
# Step 7: Verify services
echo "Verifying the status of OCserv and NGINX..."
if systemctl is-active --quiet ocserv; then
echo "OCserv is running."
else
echo "Error: OCserv is not running."
exit 1
fi
if systemctl is-active --quiet nginx; then
echo "NGINX is running."
else
echo "Error: NGINX is not running."
exit 1
fi
# Step 8: Check if port 443 is being listened on
echo "Checking if port 443 is being listened on..."
if sudo lsof -i :443 | grep LISTEN; then
echo "Port 443 is listening."
else
echo "Error: Port 443 is not listening."
exit 1
fi
# Step 9: Adding VPN users and creating certificates
echo "Adding VPN users..."
while true; do
read -p "Enter a username for VPN (or type 'exit' to quit): " vpn_user
if [[ "$vpn_user" == "exit" ]]; then
echo "Exiting user creation."
break
fi
read -sp "Enter password for $vpn_user: " vpn_pass
echo
sudo ocpasswd -c /etc/ocserv/ocpasswd $vpn_user <<EOF
$vpn_pass
$vpn_pass
EOF
echo "User $vpn_user has been added."
# Step 10: Create client certificate
echo "Generating client certificate for $vpn_user..."
sudo openssl req -newkey rsa:2048 -nodes -keyout /etc/ocserv/ssl/$vpn_user.key -x509 -days 365 -out /etc/ocserv/ssl/$vpn_user.crt -subj "/C=US/ST=California/L=SanFrancisco/O=MyVPN/OU=IT/CN=$vpn_user"
# Step 11: Create PKCS#12 (.p12) file for client
echo "Creating .p12 certificate bundle for $vpn_user..."
sudo openssl pkcs12 -export -out /etc/ocserv/ssl/$vpn_user.p12 -inkey /etc/ocserv/ssl/$vpn_user.key -in /etc/ocserv/ssl/$vpn_user.crt -certfile /etc/ocserv/ssl/server.crt -password pass:$vpn_pass
echo "Client certificate (.crt), private key (.key), and PKCS#12 (.p12) bundle have been created for user $vpn_user."
echo "Files for $vpn_user are located at /etc/ocserv/ssl/"
done
# Step 12: Verify VPN connection availability via curl
echo "Verifying VPN connection availability via curl..."
curl -I https://$(hostname -I | awk '{print $1}') --insecure --max-time 10 >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "VPN is accessible via HTTPS."
else
echo "Error: Unable to access VPN via HTTPS."
exit 1
fi
echo "Setup complete. Client certificates and .p12 bundles are located in /etc/ocserv/ssl/"
Code language: PHP (php)
Не забудьте выдать права на запуск:
chmod +x vpn-setup.sh Code language: CSS (css)
Теперь установите клиент Cisco AnyConnect
Для Android: https://play.google.com/store/apps/details?id=com.cisco.anyconnect.vpn.android.avf
Для iOS: https://apps.apple.com/us/app/cisco-secure-client/id1135064690
Для Windows: https://apps.microsoft.com/detail/9wzdncrdj8lh
Не забудьте поставить на клиент сертификат, который вы сгенерировали на шаге 7.
Надеюсь, пригодится.