Піднімаємо VPN сервер з маскуванням трафіку
Дуже коротко, як встановити OpenConnect VPN сервер на 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
Це встановить останні доступні версії 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)
Це створить SSL-сертифікат у /etc/ocserv/ssl/server.crt
і приватний ключ у /etc/ocserv/ssl/server.key
, що діятиме протягом одного року (365 днів).
Крок 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)
Ця конфігурація налаштовує сервер для обробки трафіку на порту 443, ми додали підтримує до 128 клієнтів і зробили використання DNS-серверів від Google (ЦЕ ВАЖЛИВО).
Крок 4: Налаштування NGINX як SNI-проксі
SNI-проксі на NGINX буде пересилати трафік залежно від імені сервера (SNI), використаного в запиті. Він пересилатиме VPN-запити на OpenConnect і HTTP/HTTPS-трафік на інший сервер (якщо це необхідно). Для цього редагуємо конфиг файл nginx.conf:
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: Запуск та активація сервісів
Після налаштування OpenConnect та NGINX давайте запустимо обидва сервіси.
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
Тепер давайте створимо VPN-користувачів. OpenConnect використовує простий файл з паролями (/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
Щоб підтвердити, що VPN шифрує трафік, ви можете використовувати інструмент tcpdump
для перехоплення трафіку:
sudo tcpdump -i any port 443
Ви повинні побачити зашифрований трафік між клієнтом і сервером. Будь-який VPN-клієнт, який підключається через сертифікат .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.
Сподіваюсь інформація була корисною.