Дворниченко Михайло

Blog

vpn

Піднімаємо 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.

Сподіваюсь інформація була корисною.

Leave a Reply

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *