mirror of
https://github.com/bol-van/zapret.git
synced 2025-04-19 05:22:58 +03:00
353 lines
23 KiB
Plaintext
353 lines
23 KiB
Plaintext
Есть возможность поднять свой 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.
|
||
|
||
Отсутствие двойного 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 name 'IPERF'
|
||
------------------------------------------------
|
||
|
||
# fw3 restart
|
||
|
||
--/etc/network/interfaces.d/wgvps-------------
|
||
post-up iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport --ports 5001,5201 -j DNAT --to-destination 192.168.2.2
|
||
post-up iptables -t nat -A POSTROUTING -o wgvps -d 192.168.2.2 -p tcp -m multiport --dports 5001,5201 -j MASQUERADE
|
||
post-down iptables -t nat -D PREROUTING -i eth0 -p tcp -m multiport --ports 5001,5201 -j DNAT --to-destination 192.168.2.2
|
||
post-down iptables -t nat -D POSTROUTING -o wgvps -d 192.168.2.2 -p tcp -m multiport --dports 5001,5201 -j MASQUERADE
|
||
----------------------------------------------
|
||
|
||
Аналогично можно поступить и с 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. В умелых руках творят чудеса.
|