В статье приводится настройка каскадирования двух VPN серверов через Amnezia WireGuard 2.0 + клиентский OpenVPN
0. Входные данные
Сервер А:
- Debian 13.
- Месторасположение: «Тут»
- OpenVPN + PKI + скрипты для управления конфигурациями пользователей. Подсеть 10.8.0.0/24
- Клиент Amnezia Wireguard
- Используется policy-based routing, весь трафик из подсети OpenVPN туннелируется на сервер B
- NAT не используется
- Внешний интерфейс eth0
Сервер B:
- Debian 13
- Месторасположение: «Там»
- Сервер Amnezia Wireguard. Подсеть 192.168.100.0/30 (линковая), можно использовать 24 маску, не принципиально
- Весь трафик, пришедший через AWG туннель из подсети OpenVPN сервера A NAT-ится во внешний интерфейс
- Внешний интерфейс eth0
На обоих серверах необходимо разрешить IP Forwarding:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-forward.conf
sysctl --system
(не sysctl -p, в новых дистрибутивах ругается на отсутствующий рудимент /etc/sysctl.conf)
Проверяем. Команда cat /proc/sys/net/ipv4/ip_forward должна вернуть «1»
В статье не рассматривается настройка файрвола. Предполагается, что все политики имеют дефолтное значение ACCEPT. Также не затрагивается настройка DNS, хотя это очень важный момент (но не в рамках данной тематики).
1. Настраиваем OpenVPN на сервере A
Настройка типовая, ничего особенного.
Устанавливаем пакеты:
apt install openvpn easy-rsa
- Создаем инфраструктуру открытых ключей (PKI)
mkdir -p /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa
./easyrsa init-pki
- Генерируем CA-ключ
Выполняем либо ./easyrsa build-ca — сертификат будет защищен паролем, если секьюрность не важна — можно выполнить команду ./easyrsa build-ca nopassУтилита попросит ввести Common Name — можно вводить что угодно, либо согласиться с дефолтным значением.
- Создаем сертификат сервера
Выполняем ./easyrsa build-server-full server nopassПо умолчанию срок действия сертификата составляет 825 дней.
- Создаем DH
./easyrsa gen-dh
- Создаем TLS ключ
openvpn --genkey secret ta.key
- Находясь в директории /etc/openvpn/easy-rsa, копируем в /etc/openvpn/server ключи и сертификаты.
cp pki/ca.crt /etc/openvpn/server/
cp pki/private/server.key /etc/openvpn/server/
cp pki/issued/server.crt /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp ta.key /etc/openvpn/server/
- Пилим конфигурационный файл сервера /etc/openvpn/server/server.conf
port 1194
proto udp
dev tunca ca.crt
cert server.crt
key server.key
dh dh.pemtls-auth ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push «redirect-gateway def1 bypass-dhcp»
keepalive 10 120
persist-key
persist-tunuser nobody
group nogroupcipher AES-256-GCM
data-ciphers AES-256-GCM:AES-128-GCMauth SHA256
explicit-exit-notify 1
verb 3
- Запускаем и проверяем OpenVPN сервер
systemctl enable --now openvpn-server@server
systemctl status openvpn-server@serverДолжно быть active (running), а также должен появиться интерфейс tun0 с адресом 10.8.0.1/24
- Создаем клиентов OpenVPN
Можно либо вручную сгенерировать сертификаты и ключи и сделать конфиг
Из каталога /etc/openvpn/easy-rsa запустить ./easyrsa build-client-full client1 nopass, где client1 — имя клиента
Конфиг клиента примет вид
client
dev tun
proto udpremote <IP_СЕРВЕРА А> 1194
resolv-retry infinite
nobindpersist-key
persist-tunremote-cert-tls server
cipher AES-256-GCM
data-ciphers AES-256-GCM:AES-128-GCMauth SHA256
key-direction 1
verb 3
<ca>
Здесь содержимое pki/ca.crt
</ca><cert>
Здесь содержимое pki/issued/client1.crt
</cert><key>
Здесь содержимое pki/private/client1.key
</key><tls-auth>
Здесь содержимое ta.key
</tls-auth>
Либо можно воспользоваться скриптом
<здесь должен быть скрипт, но он gone away…>
2. Развертываем AmneziaWG
Будем собирать из исходников — DKMS-модуль и утилиты awg-tools. Можно подключить PPA репозитории от ubuntu, если не хочется возиться с сорцами. Пока выполняем на обоих серверах.
- Ставим кухню
apt install git dkms build-essential linux-headers-$(uname -r)
cd /usr/src
git clone https://github.com/amnezia-vpn/amneziawg-linux-kernel-module.git amneziawg
- Ставим модуль через DKMS:
cd /usr/src/amneziawg/srс
make dkms-install
dkms add -m amneziawg -v 1.0.0
dkms build -m amneziawg -v 1.0.0
dkms install -m amneziawg -v 1.0.0
- Проверяем и загружаем модуль
dkms status должно вернуть что-то типа amneziawg/1.0.0, 6.12.95+deb13-cloud-amd64, x86_64: installed
modprobe amneziawg
lsmod | grep amneziawg должна вернуть список с модулем amneziawg и его дочерними модулями (libchacha20poly1305, udp_tunnel и прочие)
- Ставим awg-tools
cd /usr/src/
git clone https://github.com/amnezia-vpn/amneziawg-tools.git
cd amneziawg-tools/src
make install
- Здесь наши пути расходятся. Пилим конфиг сервера (Сервер B)
Начало ничем не отличается от классического WG — генерация пары ключей
awg genkey | tee /etc/amnezia/amneziawg/server_privatekey | awg pubkey | tee /etc/amnezia/amneziawg/server_publickey
Далее создаем /etc/amnezia/amneziawg/awg0.conf
[Interface]
PrivateKey = <Содержимое /etc/amnezia/amneziawg/server_privatekey>
Address = 192.168.100.1/30
# В принципе можно использовать любой порт
ListenPort = 39743
# Маскарадим трафик, пришедший с сети OpenVPN через внешний сетевой интерфейс
PostUp = iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
# Ниже параметры задают обфускацию.
Jc = 4
Jmin = 77
Jmax = 148
S1 = 72
S2 = 82
S3 = 13
S4 = 23
H1 = 686090309-771938546
H2 = 980996358-1363648663
H3 = 1371752148-1574630916
H4 = 1607849087-1706193491
I1 = <r 111>
Про параметры вкратце ниже:
| Параметр | Описание | Диапазон | Пример |
|---|---|---|---|
Jc |
Количество junk-пакетов | 3-6 | 5 |
Jmin |
Мин. размер junk (байт) | 40-89 | 55 |
Jmax |
Макс. размер junk (байт) | Jmin+50..Jmin+250 | 200 |
S1 |
Padding init-сообщения (байт) | 15-150 | 72 |
S2 |
Padding response-сообщения (байт) | 15-150, S1+56≠S2 | 56 |
S3 |
Padding cookie-сообщения (байт) | 8-55 | 32 |
S4 |
Padding data-сообщения (байт) | 4-27 | 16 |
H1 |
Идентификатор init-сообщения | Диапазон uint32 | 134567-245678 |
H2 |
Идентификатор response-сообщения | Диапазон uint32 | 3456789-4567890 |
H3 |
Идентификатор cookie-сообщения | Диапазон uint32 | 56789012-67890123 |
H4 |
Идентификатор data-сообщения | Диапазон uint32 | 456789012-567890123 |
I1 |
CPS concealment packet | Формат <r N> |
<r 128> |
I2—I5 |
Доп. CPS / special-junk пакеты, опциональны | Теги <r N> / <b 0xHEX> / <c> / <t> |
<b 0xf1> |
Критические ограничения:
- H1-H4 диапазоны не должны пересекаться.
S1 + 56 ≠ S2— предотвращает одинаковый размер init и response сообщений.- Все узлы (сервер + клиенты) должны использовать одинаковые параметры (вплоть до регистра).
Подробно можно почитать тут https://habr.com/ru/companies/amnezia/articles/1014636/ или тут https://github.com/bivlked/amneziawg-installer/blob/main/ADVANCED.md#awg2-params-adv
Добавляем клиента. Генерим ключи:
awg genkey | tee /etc/amnezia/amneziawg/client_privatekey | awg pubkey | tee /etc/amnezia/amneziawg/client_publickey
В конец файла /etc/amnezia/amneziawg/awg0.conf добавляем секцию
# Name = Server A
[Peer]
PublicKey = <Содержимое/etc/amnezia/amneziawg/client_publickey>
# Разрешаем линковую сеть и сеть OpenVPN сервера A. Заодно пропишется обратный маршрут к подсети OpenVPN
AllowedIPs = 192.168.100.2/30, 10.8.0.0/24
- Пилим конфиг клиента /etc/amnezia/amneziawg/awg0.conf — на сервере A
[Interface]
PrivateKey = <Содержимое /etc/amnezia/amneziawg/client_privatekey с Сервера B>
Address = 192.168.100.2/30
# В принципе можно использовать любой порт
ListenPort = 31764
# Отключаем добавление маршрутов в системные таблицы маршрутизации
Table = off
# Задаём route policy — весь трафик с сети OpenVPN загоняем в таблицу маршрутизации с номером 100
PostUp = ip route replace default via 192.168.100.1 dev awg0 table 100
PostUp = ip rule add from 10.8.0.0/24 table 100
PostDown = ip rule del from 10.8.0.0/24 table 100
# Ниже параметры задают обфускацию. Точно такие же, как на сервере A
Jc = 4
Jmin = 77
Jmax = 148
S1 = 72
S2 = 82
S3 = 13
S4 = 23
H1 = 686090309-771938546
H2 = 980996358-1363648663
H3 = 1371752148-1574630916
H4 = 1607849087-1706193491
I1 = <r 111>[Peer]
PublicKey = <Содержимое/etc/amnezia/amneziawg/server_publickeyс Сервера B>
# Разрешаем любой адрес. Чтобы не переписывался default маршрут — выше параметр Table = off
AllowedIPs = 0.0.0.0/0
Endpoint = <Адрес:порт сервера B>
- Запуск и проверка
На обоих серверах запускаем демона
systemctl enable --now awg-quick@awg0
Должен создаться интерфейс awg0 с соответствующими IP
Пингуем сервера друг с друга по туннельным адресам — должно работать.
На сервере А (который «тут», который клиент AmneziaWG) должна создаться таблица маршрутизации 100, правило и политика маршрутизации:
ip rule show
32765: from 10.8.0.0/24 lookup 100
ip route list table 100
default via 192.168.100.1 dev awg0
На сервере B должно создаться правило NAT (можно сделать маскарадинг по-другому — «покрасить» входящий трафик с интерфейса awg0 и потом по этой маркировке сделать NAT наружу, но в данном случае это лишнее)
iptables -t nat -L
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all — 10.8.0.0/24 anywhere
или iptables-save
*nat
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
Ну и маршрут должен быть в OpenVPN сеть
10.8.0.0/24 dev awg0 scope link
3. Финиш
Подключаемся OpenVPN клиентом — и «Мы оказались за кордоном. Линять надо быстро и тихо»
Для тех, кто в танке не понял как работает: клиент OpenVPN при подключении командой с сервера push «redirect-gateway def1 bypass-dhcp» переписывает дефолтный маршрут на маршрут в OpenVPN-туннель. На сервере А в соответствии с политикой маршрутизации — всё, что пришло из сети OpenVPN, попадает в таблицу 100, где присутствует маршрут по-умолчанию на сервер B через интерфейс awg0. На сервере B файрволом осуществляется NAT-ирование (маскарадинг трафика) из сети OpenVPN через внешний интерфейс.
