wireguard modding guide

This commit is contained in:
bolvan
2019-04-29 12:50:56 +03:00
parent dec5ee4a91
commit 674fa53b19
3 changed files with 343 additions and 0 deletions

138
wireguard/010-wg-mod.patch Normal file
View File

@@ -0,0 +1,138 @@
Index: WireGuard-0.0.20190123/src/cookie.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/cookie.c
+++ WireGuard-0.0.20190123/src/cookie.c
@@ -193,6 +193,8 @@ void wg_cookie_message_create(struct mes
xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN,
macs->mac1, COOKIE_LEN, dst->nonce,
checker->cookie_encryption_key);
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
}
void wg_cookie_message_consume(struct message_handshake_cookie *src,
Index: WireGuard-0.0.20190123/src/messages.h
===================================================================
--- WireGuard-0.0.20190123.orig/src/messages.h
+++ WireGuard-0.0.20190123/src/messages.h
@@ -53,23 +53,41 @@ enum limits {
MAX_QUEUED_PACKETS = 1024 /* TODO: replace this with DQL */
};
+/*
enum message_type {
- MESSAGE_INVALID = 0,
- MESSAGE_HANDSHAKE_INITIATION = 1,
- MESSAGE_HANDSHAKE_RESPONSE = 2,
- MESSAGE_HANDSHAKE_COOKIE = 3,
- MESSAGE_DATA = 4
+ MESSAGE_INVALID = 0,
+ MESSAGE_HANDSHAKE_INITIATION = 1,
+ MESSAGE_HANDSHAKE_RESPONSE = 2,
+ MESSAGE_HANDSHAKE_COOKIE = 3,
+ MESSAGE_DATA = 4
};
+*/
+
+// MOD : message type
+enum message_type {
+ MESSAGE_INVALID = 0xE319CCD0,
+ MESSAGE_HANDSHAKE_INITIATION = 0x48ADE198,
+ MESSAGE_HANDSHAKE_RESPONSE = 0xFCA6A8F3,
+ MESSAGE_HANDSHAKE_COOKIE = 0x64A3BB18,
+ MESSAGE_DATA = 0x391820AA
+};
+
+// MOD : generate fast trash without true RNG
+__le32 gen_trash(void);
struct message_header {
- /* The actual layout of this that we want is:
- * u8 type
- * u8 reserved_zero[3]
- *
- * But it turns out that by encoding this as little endian,
- * we achieve the same thing, and it makes checking faster.
- */
- __le32 type;
+ /* The actual layout of this that we want is:
+ * u8 type
+ * u8 reserved_zero[3]
+ *
+ * But it turns out that by encoding this as little endian,
+ * we achieve the same thing, and it makes checking faster.
+ */
+
+ // MOD : trash field to change message size and add 4 byte offset to all fields
+ __le32 trash;
+
+ __le32 type;
};
struct message_macs {
Index: WireGuard-0.0.20190123/src/noise.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/noise.c
+++ WireGuard-0.0.20190123/src/noise.c
@@ -17,6 +17,24 @@
#include <linux/highmem.h>
#include <crypto/algapi.h>
+
+// MOD : trash generator
+__le32 gtrash = 0;
+__le32 gen_trash(void)
+{
+ if (gtrash)
+ {
+ gtrash = gtrash*1103515243 + 12345;
+ }
+ else
+ {
+ // first value is true random
+ wait_for_random_bytes();
+ get_random_bytes_wait(&gtrash, sizeof(gtrash));
+ }
+ return gtrash;
+}
+
/* This implements Noise_IKpsk2:
*
* <- s
@@ -515,6 +533,10 @@ wg_noise_handshake_create_initiation(str
&handshake->entry);
handshake->state = HANDSHAKE_CREATED_INITIATION;
+
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
+
ret = true;
out:
@@ -655,6 +677,10 @@ bool wg_noise_handshake_create_response(
&handshake->entry);
handshake->state = HANDSHAKE_CREATED_RESPONSE;
+
+ // MOD : randomize trash
+ dst->header.trash = gen_trash();
+
ret = true;
out:
Index: WireGuard-0.0.20190123/src/send.c
===================================================================
--- WireGuard-0.0.20190123.orig/src/send.c
+++ WireGuard-0.0.20190123/src/send.c
@@ -200,6 +200,10 @@ static bool encrypt_packet(struct sk_buf
header->header.type = cpu_to_le32(MESSAGE_DATA);
header->key_idx = keypair->remote_index;
header->counter = cpu_to_le64(PACKET_CB(skb)->nonce);
+
+ // MOD : randomize trash
+ header->header.trash = gen_trash();
+
pskb_put(skb, trailer, trailer_len);
/* Now we can encrypt the scattergather segments */

205
wireguard/wireguard-mod.txt Normal file
View File

@@ -0,0 +1,205 @@
Посвящено возможной блокировке в РФ VPN протоколов через DPI.
Предпосылками являются последние законодательные акты и во всю сочащиеся "секретные" записки.
В РФ разрабатываются и готовятся к применению более продвинутые решения по блокировке трафика.
Вполне вероятно будут резать стандартные VPN протоколы. Нам надо быть к этому готовыми.
Один из возможных и перспективных путей решения данного вопроса - кустомная модификация
исходников VPN с целью незначительного изменения протокола, ломающего стандартные модули обнаружения в DPI.
Это относительно сложно, доступно только для гиков.
Никто не будет разрабатывать специальные модули обнаружения в DPI, если только кто-то не сделает простое и
удобное решение для всех, и его станут широко применять. Но это маловероятно, и даже если и так,
то всегда можно модифицировать протокол чуток по другому. Делать моды для DPI несравненно дольше
и дороже, чем клепать на коленке изменения протокола для wireguard.
Рассмотрю что нам надо пропатчить в wireguard. Модифицированный wireguard проверен на виртуалках
с десктопным linux, он работает, сообщения в wireshark действительно не вписываются в стандартный
протокол и не опознаются.
Wireguard протокол очень простой. Все сообщения описаны в messages.h
Поставим себе целью сделать 2 простые модификации :
1) Добавим в начало всех сообщений немного мусора, чтобы изменить размер сообщений и смещения полей
2) Изменим коды типов сообщений
Этого может быть вполне достаточно для обмана DPI
--messages.h--------------------------
/*
enum message_type {
MESSAGE_INVALID = 0,
MESSAGE_HANDSHAKE_INITIATION = 1,
MESSAGE_HANDSHAKE_RESPONSE = 2,
MESSAGE_HANDSHAKE_COOKIE = 3,
MESSAGE_DATA = 4
};
*/
// MOD : message type
enum message_type {
MESSAGE_INVALID = 0xE319CCD0,
MESSAGE_HANDSHAKE_INITIATION = 0x48ADE198,
MESSAGE_HANDSHAKE_RESPONSE = 0xFCA6A8F3,
MESSAGE_HANDSHAKE_COOKIE = 0x64A3BB18,
MESSAGE_DATA = 0x391820AA
};
// MOD : generate fast trash without true RNG
__le32 gen_trash(void);
struct message_header {
/* The actual layout of this that we want is:
* u8 type
* u8 reserved_zero[3]
*
* But it turns out that by encoding this as little endian,
* we achieve the same thing, and it makes checking faster.
*/
// MOD : trash field to change message size and add 4 byte offset to all fields
__le32 trash;
__le32 type;
};
--------------------------------------
Напишем функцию для генерации trash. Функция должна быть быстрая, важно не замедлить скорость.
Мы не расчитываем, что нас будут специально ловить, иначе бы пришлось делать полноценный обфускатор.
Задача лишь сломать стандартный модуль обнаружения протокола wireguard. Потому истинная рандомность
trash не важна.
Но все же немного "трэша" не повредит. Гонки между тредами так же пофигистичны. Это же трэш.
--noise.c-----------------------------
// MOD : trash generator
__le32 gtrash = 0;
__le32 gen_trash(void)
{
if (gtrash)
{
gtrash = gtrash*1103515243 + 12345;
}
else
{
// first value is true random
wait_for_random_bytes();
get_random_bytes_wait(&gtrash, sizeof(gtrash));
}
return gtrash;
}
--------------------------------------
Теперь осталось найти все места, где создаются сообщения и внести туда заполнение поля trash.
Сообщений всего 4. Их можно найти по присваиванию полю type одного из значений enum message_type.
2 места в noise.c в функциях wg_noise_handshake_create_initiation и wg_noise_handshake_create_response,
1 место в cookie.c в функции wg_cookie_message_create
Дописываем в конец инициализации структуры сообщения :
--------------------------------------
// MOD : randomize trash
dst->header.trash = gen_trash();
--------------------------------------
и 1 место в send.c в функции encrypt_packet
--------------------------------------
// MOD : randomize trash
header->header.trash = gen_trash();
--------------------------------------
Вот и весь патчинг. Полный patch (версия wireguard 0.0.20190123) лежит в 010-wg-mod.patch.
Патчинг кода - самое простое. Для десктопного linux дальше все просто.
Пересобираем через make, устанавливаем через make install, перегружаем
модуль wireguard, перезапускаем интерфейсы, и все готово.
Настоящий геморой начнется когда вы это попытаетесь засунуть на роутер под openwrt.
Одна из больших проблем linux - отсутствие совместимости драйверов на уровне бинариков.
Поэтому собирать необходимо в точности под вашу версию ядра и в точности под его .config.
Вам придется либо полностью самостоятельно собирать всю прошивку, либо найти SDK в точности
от вашей версии прошивки для вашей архитектуры и собрать модуль с помощью этого SDK.
Последний вариант более легкий.
Для сборки вам понадобится система на linux x86_64. Ее можно установить в виртуалке.
Теоретически можно пользоваться WSL из win10, но на практике там очень медленное I/O,
по крайней мере на старых версиях win10. Безумно медленное. Будете собирать вечность.
Может в новых win10 что-то и улучшили, но я бы сразу расчитывал на полноценный linux.
Находим здесь вашу версию : https://downloads.openwrt.org/
Скачиваем файл openwrt-sdk-*.tar.xz или lede-sdk-*.tar.xz
Например : https://downloads.openwrt.org/releases/18.06.2/targets/ar71xx/generic/openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64.tar.xz
Если ваша версия непонятна или стара, то проще будет найти последнюю прошивку и перешить роутер.
Распаковываем SDK. Следующими командами можно собрать оригинальный вариант wireguard :
# scripts/feeds update -a
# scripts/feeds install -a
# make defconfig
# make -j 4 package/wireguard
Сборка будет довольно долгой. Ведь придется подтащить ядро, собрать его, собрать зависимости.
"-j 4" означает использовать 4 потока. Впишите вместо 4 количество доступных cpu cores.
Получим следующие файлы :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/bin/targets/ar71xx/generic/packages/kmod-wireguard_4.9.152+0.0.20190123-1_mips_24kc.ipk
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/bin/packages/mips_24kc/base/wireguard-tools_0.0.20190123-1_mips_24kc.ipk
Но это будет оригинальный wireguard. Нам нужен патченый.
Установим quilt и mc для нормального редактора вместо vim :
# sudo apt-get update
# sudo apt-get install quilt mc
# make package/wireguard/clean
# make package/wireguard/prepare V=s QUILT=1
Сорцы приготовлены для сборки в :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/src
# cd build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/src
# quilt push -a
# quilt new 010-wg-mod.patch
# export EDITOR=mcedit
Далее будет открываться редактор mcedit, в который нужно вносить изменения в каждый файл :
# quilt edit messages.h
# quilt edit cookie.c
# quilt edit noise.c
# quilt edit send.c
# quilt diff
# quilt refresh
Получили файл патча в :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/build_dir/target-mips_24kc_musl/linux-ar71xx_generic/WireGuard-0.0.20190123/patches/010-wg-mod.patch
Выходим в корень SDK.
# make package/wireguard/compile V=99
Если не было ошибок, то получили измененные ipk.
Патч можно зафиксировать в описании пакета :
# make package/wireguard/update
Получим :
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/feeds/base/package/network/services/wireguard/patches/010-wg-mod.patch
При последующей очистке и пересборке он будет автоматом применяться.
Полученные ipk копируем на роутер в /tmp, устанавливаем через
# cd /tmp
# opkg install *.ipk
Если требует зависимостей, то
# opkg update
# opkg install .... <зависимости>
# opkg install *.ipk
Если раньше уже был wireguard, то проще всего будет на всякий случай ребутнуться.
Когда поднимите линк, и вдруг ничего не будет работать, то посмотрите в wireshark udp пакеты
на порт endpoint. Они не должны начинаться с 0,1,2,3,4. В первых 4 байтах должны быть
значения из измененного enum message_type. Если там все еще 0..4, значит модуль wireguard
оригинальный, что-то не собралось, не скопировалось, не перезапустилось.
В противном случае должен подняться линк, пинги ходить. Значит вы победили, поздравляю.
Регулятору будет намного сложнее поймать ваш VPN.

View File

@@ -0,0 +1,377 @@
Есть возможность поднять свой VPN сервер ? Не хотим использовать redsocks ?
Хотим завертывать на VPN только часть трафика ?
Например, из ipset zapret только порт tcp:443, из ipban - весь трафик, не только tcp ?
Да, с VPN такое возможно.
Опишу понятийно как настраивается policy based routing в openwrt на примере wireguard.
Вместо wireguard можно использовать openvpn или любой другой. Но wireguard прекрасен сразу несколькими вещами.
Главная из которых - в разы большая скорость, даже немного превышающая ipsec.
Ведь openvpn основан на tun, а tun - всегда в разы медленнее решения в kernel mode,
и если для PC оно может быть не так актуально, для soho роутеров - более чем.
Wireguard может дать 50 mbps там, где openvpn еле тащит 10.
Но есть и дополнительное требование. Wireguard работает в ядре, значит ядро должно
быть под вашим контролем. vps на базе openvz не подойдет ! Нужен xen, kvm,
любой другой вариант, где загружается ваше собственное ядро, а не используется
общее, разделяемое на множество vps. В openvz вам никто не даст лезть в ядро.
Если вдруг окажется, что основные VPN протоколы блокируется DPI, включая wireguard,
то стоит смотреть в сторону либо обфускации трафика до состояния нераспознаваемого
мусора, либо маскировки под TLS (лучше на порт 443). Скорость, конечно, вы потеряете, но это
та самая ситуация, которая описывается словами "медленно или никак".
Маскированные под TLS протоколы DPI может распознать двумя действиями :
пассивно через анализ статистических характеристик пакетов (время, размер, периодичность, ..)
или активно через подключение к вашему серверу от себя и попытку поговорить с сервером по
известным протоколам (называется active probing). Если вы подключаетесь к серверу
с фиксированных IP, то активный пробинг можно надежно заблокировать через ограничение
диапазонов IP адресов, с которых можно подключаться к серверу. В ином случае можно использовать
технику "port knocking".
Перспективным направлением так же считаю легкую собственную модификацию исходников
существующих VPN с целью незначительного изменения протокола, которая ломает стандартные
модули обнаружения в DPI. В wireguard можно добавить в начало пакета handshake лишнее поле,
заполненное случайным мусором. Разумеется, в таком случае требуется держать измененную версию
как на сервере, так и на клиенте. Если затея срабатывает, то вы получаете максимальную
скорость, при этом полностью нагибая регулятора.
Полезная инфа по теме : https://habr.com/ru/post/415977/
Понятийно необходимо выполнить следующие шаги :
1) Поднять vpn сервер.
2) Настроить vpn клиент. Результат этого шага - получение поднятого интерфейса vpn.
Будь то wireguard, openvpn или любой другой тип vpn.
3) Создать такую схему маршрутизации, при которой пакеты, помечаемые особым mark,
попадают на vpn, а остальные идут обычным способом.
4) Создать правила, выставляющие mark для всего трафика, который необходимо рулить на vpn.
Критерии могут быть любые, ограниченные лишь возможностями iptables и вашим воображением.
Будем считать наш vpn сервер находится на ip 91.15.68.202.
Вешать его будем на udp порт 12345. На этот же порт будем вешать и клиентов.
Сервер работает под debian 9. Клиент работает под openwrt.
Для vpn отведем подсеть 192.168.254.0/24.
--- Поднятие сервера ---
На сервере должны быть установлены заголовки ядра (linux-headers-...) и компилятор gcc.
Качаем последний tar.xz с wireguard отсюда : https://git.zx2c4.com/WireGuard/
# tar xf WireGuard*.tar.xz
# cd WireGuard-*/src
# make
# strip --strip-debug wireguard.ko
# sudo make install
wireguard основан на понятии криптороутинга. Каждый пир (сервер - тоже пир)
имеет пару открытый/закрытый ключ. Закрытый ключ остается у пира,
открытый прописывается у его партнера. Каждый пир авторизует другого
по знанию приватного ключа, соответствующего прописанному у него публичному ключу.
Протокол построен таким образом, что на все неправильные udp пакеты не следует ответа.
Не знаешь приватный ключ ? Не смог послать правильный запрос ? Долбись сколько влезет,
я тебе ничего не отвечу. Это защищает от активного пробинга со стороны DPI и просто
экономит ресурсы.
Значит первым делом нужно создать 2 пары ключей : для сервера и для клиента.
wg genkey генерит приватный ключ, wg pubkey получает из него публичный ключ.
# wg genkey
oAUkmhoREtFQ5D5yZmeHEgYaSWCcLYlKe2jBP7EAGV0=
# echo oAUkmhoREtFQ5D5yZmeHEgYaSWCcLYlKe2jBP7EAGV0= | wg pubkey
bCdDaPYSTBZVO1HTmKD+Tztuf3PbOWGDWfz7Lb1E6C4=
# wg genkey
OKXX0TSlyjJmGt3/yHlHxi0AqjJ0vh+Msne3qEHk0VM=
# echo OKXX0TSlyjJmGt3/yHlHxi0AqjJ0vh+Msne3qEHk0VM= | wg pubkey
EELdA2XzjcKxtriOCPBXMOgxlkgpbRdIyjtc3aIpkxg=
Пишем конфиг
--/etc/wireguard/wgvps.conf-------------------
[Interface]
PrivateKey = OKXX0TSlyjJmGt3/yHlHxi0AqjJ0vh+Msne3qEHk0VM=
ListenPort = 12345
[Peer]
#Endpoint =
PublicKey = bCdDaPYSTBZVO1HTmKD+Tztuf3PbOWGDWfz7Lb1E6C4=
AllowedIPs = 192.168.254.3
PersistentKeepalive=20
----------------------------------------------
Wireguard - минималистичный vpn. В нем нет никаких средств для автоконфигурации ip.
Все придется прописывать руками.
В wgvps.conf должны быть перечислены все пиры с их публичными ключами,
а так же прописаны допустимые для них ip адреса.
Назначим нашему клиенту 192.168.254.3. Сервер будет иметь ip 192.168.254.1.
Endpoint должен быть прописан хотя бы на одном пире.
Если endpoint настроен для пира, то wireguard будет периодически пытаться к нему подключиться.
В схеме клиент/сервер у сервера можно не прописывать endpoint-ы пиров, что позволит
менять ip и быть за nat. Endpoint пира настраивается динамически после успешной фазы
проверки ключа.
Включаем маршрутизцию :
# echo net.ipv4.ip_forward = 1 >>/etc/sysctl.conf
# sysctl -p
Интерфейс конфигурится стандартно для дебианоподобных систем :
--/etc/network/interfaces.d/wgvps-------------
auto wgvps
iface wgvps inet static
address 192.168.254.1
netmask 255.255.255.0
pre-up ip link add $IFACE type wireguard
pre-up wg setconf $IFACE /etc/wireguard/$IFACE.conf
post-up iptables -t nat -A POSTROUTING -o eth0 -s 192.168.254.0/24 -j MASQUERADE
post-up iptables -A FORWARD -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
post-down iptables -D FORWARD -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
post-down iptables -t nat -D POSTROUTING -o eth0 -s 192.168.254.0/24 -j MASQUERADE
post-down ip link del $IFACE
----------------------------------------------
Поднятие через ifup wgvps, опускание через ifdown wgvps.
При поднятии интерфейса заодно настраивается nat. eth0 здесь означает интерфейс vpn сервера с инетовским ip адресом.
Если у вас какая-то система управления фаерволом, то надо настройку nat прикручивать туда.
Пример написан для простейшего случая, когда никаких ограничений нет, таблицы iptables пустые.
Чтобы посмотреть текущие настройки wireguard, запустите 'wg' без параметров.
--- Поднятие клиента ---
# opkg update
# opkg install wireguard
Добавляем записи в конфиги.
--/etc/config/network--------------------------
config interface 'wgvps'
option proto 'wireguard'
option auto '1'
option private_key 'oAUkmhoREtFQ5D5yZmeHEgYaSWCcLYlKe2jBP7EAGV0='
option listen_port '12345'
option metric '9'
option mtu '1420'
config wireguard_wgvps
option public_key 'EELdA2XzjcKxtriOCPBXMOgxlkgpbRdIyjtc3aIpkxg=
list allowed_ips '0.0.0.0/0'
option endpoint_host '91.15.68.202'
option endpoint_port '12345'
option route_allowed_ips '0'
option persistent_keepalive '20'
config interface 'wgvps_ip'
option proto 'static'
option ifname '@wgvps'
list ipaddr '192.168.254.3/24'
config route
option interface 'wgvps'
option target '0.0.0.0/0'
option table '100'
config rule
option mark '0x800/0x800'
option priority '100'
option lookup '100'
------------------------------------------------
--/etc/config/firewall--------------------------
config zone
option name 'tunvps'
option output 'ACCEPT'
option input 'REJECT'
option masq '1'
option mtu_fix '1'
option forward 'REJECT'
option network 'wgvps wgvps_ip'
config forwarding
option dest 'tunvps'
option src 'lan'
config rule
option name 'Allow-ICMP-tunvps'
option src 'tunvps'
option proto 'icmp'
option target 'ACCEPT'
config rule
option target 'ACCEPT'
option src 'wan'
option proto 'udp'
option family 'ipv4'
option src_port '12345'
option src_ip '91.15.68.202'
option name 'WG-VPS'
------------------------------------------------
Что тут было сделано :
*) Настроен интерфейс wireguard. Указан собственный приватный ключ.
*) Настроен пир-партнер с указанием его публичнго ключа и endpoint (ip:port нашего сервера)
такая настройка заставит периодически долбиться на сервер по указанному ip
route_allowed_ip '0' запрещает автоматическое создание маршрута
allowed_ips '0.0.0.0/0' разрешает пакеты с любым адресом источника.
ведь мы собираемся подключаться к любым ip в инете
persistent_keepalive '20' помогает исключить дропание mapping на nat-е, если мы сидим за ним,
да и вообще полезная вещь, чтобы не было подвисших пиров
*) Статическая конфигурация ip интерфейса wgvps.
*) Маршрут default route на wgvps в отдельной таблице маршрутизации с номером 100. Аналог команды ip route add .. table 100
*) Правило использовать таблицу 100 при выставлении в mark бита 0x800. Аналог команды ip rule.
*) Отдельная зона фаервола для VPN - 'tunvps'. В принципе ее можно не создавать, можете приписать интерфейс к зоне wan.
Но в случае с отдельной зоной можно настроить особые правила на подключения с vpn сервера в сторону клиента.
*) Разрешение форвардинга между локалкой за роутером и wgvps.
*) Разрешение принимать icmp от vpn сервера, включая пинги. ICMP жизненно важны для правильного функционирования ip сети !
*) И обязательно проткнуть дырку в фаерволе, чтобы принимать пакеты wireguard со стороны инетовского ip vpn сервера.
# fw3 restart
# ifup wgvps
# ifconfig wgvps
# ping 192.168.254.1
Если все хорошо, должны ходить пинги.
С сервера не помешает :
# ping 192.168.254.3
--- Маркировка трафика ---
Завернем на vpn все из ipset zapret на tcp:443 и все из ipban.
OUTPUT относится к исходящим с роутера пакетам, PREROUTING - ко всем остальным.
Если с роутера ничего заруливать не надо, можно опустить все до команд с PREROUTING.
--/etc/firewall.user----------------------------
. /lib/functions/network.sh
network_find_wan wan_iface
for ext_iface in $wan_iface; do
network_get_device DEVICE $ext_iface
iptables -t mangle -C OUTPUT -p tcp --dport 443 -o $DEVICE -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800 ||
iptables -t mangle -I OUTPUT -p tcp --dport 443 -o $DEVICE -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
iptables -t mangle -C OUTPUT -o $DEVICE -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800 ||
iptables -t mangle -I OUTPUT -o $DEVICE -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800
done
iptables -t mangle -C PREROUTING -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800 ||
iptables -t mangle -I PREROUTING -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
iptables -t mangle -C PREROUTING -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800 ||
iptables -t mangle -I PREROUTING -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800
------------------------------------------------
# fw3 restart
--- По поводу двойного NAT ---
В описанной конфигурации nat выполняется дважды : на роутере-клиенте происходит замена адреса источника из LAN
на 192.168.254.3 и на сервере замена 192.168.254.3 на внешний адрес сервера в инете.
Зачем так делать ? Исключительно для простоты настройки. Но если вы готовы чуток еще поднапрячься и не хотите двойного nat,
то можете вписать в /etc/config/firewall "masq '0'", на сервер дописать маршрут до вашей подсети lan.
Чтобы не делать это для каждого клиента, можно отвести под всех клиентов диапазон 192.168.0.0-192.168.127.255
и прописать его одним маршрутом.
--/etc/network/interfaces.d/wgvps-------------
post-up ip route add dev $IFACE 192.168.0.0/17
post-down ip route del dev $IFACE 192.168.0.0/17
----------------------------------------------
Так же необходимо указать wireguard дополнительные разрешенные ip для peer :
--/etc/wireguard/wgvps.conf-------------------
[Peer]
PublicKey = bCdDaPYSTBZVO1HTmKD+Tztuf3PbOWGDWfz7Lb1E6C4=
AllowedIPs = 192.168.254.3, 192.168.2.0/24
----------------------------------------------
Всем клиентам придется назначать различные диапазоны адресов в lan и индивидуально прописывать AllowedIPs
для каждого peer.
# ifdown wgvps ; ifup wgvps
На клиенте разрешим форвард icmp, чтобы работал пинг и корректно определялось mtu.
--/etc/config/firewall--------------------------
config rule
option name 'Allow-ICMP-tunvps'
option src 'tunvps'
option dest 'lan'
option proto 'icmp'
option target 'ACCEPT'
------------------------------------------------
# fw3 restart
Сейчас уже можно с vpn сервера пингануть ip адрес внутри локалки клиента. Пинги должны ходить.
Отсутствие двойного NAT значительно облегчает проброс портов с внешнего IP vpn сервера в локалку какого-либо клиента.
Для этого надо выполнить 2 действия : добавить разрешение в фаервол на клиенте и сделать dnat на сервере.
Пример форварда портов 5001 и 5201 на 192.168.2.2 :
--/etc/config/firewall--------------------------
config rule
option target 'ACCEPT'
option src 'tunvps'
option dest 'lan'
option proto 'tcp udp'
option dest_port '5001 5201'
option dest_ip '192.168.2.2'
option name 'IPERF'
------------------------------------------------
# fw3 restart
--/etc/network/interfaces.d/wgvps-------------
post-up iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2
post-up iptables -t nat -A POSTROUTING -o $IFACE -d 192.168.2.2 -p tcp -m multiport --dports 5001,5201 -j MASQUERADE
post-up iptables -t nat -A PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2
post-up iptables -t nat -A POSTROUTING -o $IFACE -d 192.168.2.2 -p udp -m multiport --dports 5001,5201 -j MASQUERADE
post-down iptables -t nat -D PREROUTING -i eth0 -p tcp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2
post-down iptables -t nat -D POSTROUTING -o $IFACE -d 192.168.2.2 -p tcp -m multiport --dports 5001,5201 -j MASQUERADE
post-down iptables -t nat -D PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2
post-down iptables -t nat -D POSTROUTING -o $IFACE -d 192.168.2.2 -p udp -m multiport --dports 5001,5201 -j MASQUERADE
----------------------------------------------
# ifdown wgvps ; ifup wgvps
Пример приведен для iperf и iperf3, чтобы показать как пробрасывать несколько портов tcp+udp с минимальным количеством команд.
Проброс tcp и udp порта так же необходим для полноценной работы bittorrent клиента, чтобы работали входящие.
--- Как мне отправлять на vpn весь трафик с bittorrent ? ---
Можно поступить так : посмотрите порт в настройках torrent клиента, убедитесь, что не поставлено "случайный порт",
добавьте на роутер правило маркировки по порту источника.
Но мне предпочтительно иное решение. На windows есть замечательная возможность
прописать правило установки поля качества обслуживания в заголовках ip пакетов в зависимости от процесса-источника.
Для windows 7/2008R2 необходимо будет установить ключик реестра и перезагрузить комп :
# reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\QoS /v "Do not use NLA" /t REG_SZ /d "1"
Редактировать политику можно в : gpedit.msc -> Computer Configuration -> Windows Settings -> Policy-based QoS
На win 10 ключик реестра больше не работает, правила qos в gpedit применяются только для профиля домена.
Необходимо пользоваться командой powershell New-NetQosPolicy. Гуглите хелп по ней. Пример :
# powershell New-NetQosPolicy -Name "torrent" -AppPathNameMatchCondition "qbittorrent.exe" -DSCPAction 1
Однозначно требуется проверка в wireshark или netmon успешности установки поля dscp. Если там по-прежнему 0x00,
значит что-то не сработало. 0x04 означает DSCP=1 (dscp находится в старших 6 битах).
На роутере в фаер прописываем правило :
--/etc/config/firewall--------------------------
config rule
option target 'MARK'
option src 'lan'
option proto 'all'
option extra '-m dscp --dscp 1'
option name 'route-dscp-1'
option set_mark '0x0800/0x0800'
------------------------------------------------
# fw3 restart
Теперь все с полем dscp "1" идет на vpn. Клиент сам решает какой трафик ему нужно забрасывать
на vpn, перенастраивать роутер не нужно.
На linux клиенте проще всего будет выставлять dscp в iptables по номеру порта источника :
--/etc/rc.local---------------------------------
iptables -t mangle -A OUTPUT -p tcp --sport 23444 -j DSCP --set-dscp 1
iptables -t mangle -A OUTPUT -p udp --sport 23444 -j DSCP --set-dscp 1
------------------------------------------------
можно привязываться к pid процесса, но тогда нужно перенастраивать iptables при каждом перезапуске
торент клиента, это требует рута, и все становится очень неудобно.
--- А если не заработало ? ---
Мануал пишется не как копипастная инструкция, а как помощь уже соображающему.
В руки вам ifconfig, ip, iptables, tcpdump, ping. В умелых руках творят чудеса.