mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
history purge
This commit is contained in:
154
docs/changes.txt
Normal file
154
docs/changes.txt
Normal file
@@ -0,0 +1,154 @@
|
||||
v1
|
||||
|
||||
Initial release
|
||||
|
||||
v2
|
||||
|
||||
nfqws : command line options change. now using standard getopt.
|
||||
nfqws : added options for window size changing and "Host:" case change
|
||||
ISP support : tested on mns.ru and beeline (corbina)
|
||||
init scripts : rewritten init scripts for simple choise of ISP
|
||||
create_ipset : now using 'ipset restore', it works much faster
|
||||
readme : updated. now using UTF-8 charset.
|
||||
|
||||
v3
|
||||
|
||||
tpws : added transparent proxy (supports TPROXY and DNAT).
|
||||
can help when ISP tracks whole HTTP session, not only the beginning
|
||||
ipset : added zapret-hosts-user.txt which contain user defined host names to be resolved
|
||||
and added to zapret ip list
|
||||
ISP support : dom.ru support via TPROXY/DNAT
|
||||
ISP support : successfully tested sknt.ru on 'domru' configuration
|
||||
other configs will probably also work, but cannot test
|
||||
compile : openwrt compile howto
|
||||
|
||||
v4
|
||||
|
||||
tpws : added ability to insert extra space after http method : "GET /" => "GET /"
|
||||
ISP support : TKT support
|
||||
|
||||
v5
|
||||
|
||||
nfqws : ipv6 support in nfqws
|
||||
|
||||
v6
|
||||
|
||||
ipset : added "get_antizapret.sh"
|
||||
|
||||
v7
|
||||
|
||||
tpws : added ability to insert "." after Host: name
|
||||
|
||||
v8
|
||||
|
||||
openwrt init : removed hotplug.d/firewall because of race conditions. now only use /etc/firewall.user
|
||||
|
||||
v9
|
||||
|
||||
ipban : added ipban ipset. place domains banned by ip to zapret-hosts-user-ipban.txt
|
||||
these IPs must be soxified for both http and https
|
||||
ISP support : tiera support
|
||||
ISP support : added DNS filtering to ubuntu and debian scripts
|
||||
|
||||
v10
|
||||
|
||||
tpws : added split-pos option. split every message at specified position
|
||||
|
||||
v11
|
||||
|
||||
ipset : scripts optimizations
|
||||
|
||||
v12
|
||||
|
||||
nfqws : fix wrong tcp checksum calculation if packet length is odd and platform is big-endian
|
||||
|
||||
v13
|
||||
|
||||
added binaries
|
||||
|
||||
v14
|
||||
|
||||
change get_antizapret script to work with https://github.com/zapret-info/z-i/raw/master/dump.csv
|
||||
filter out 192.168.*, 127.*, 10.* from blocked ips
|
||||
|
||||
v15
|
||||
|
||||
added --hostspell option to nfqws and tpws
|
||||
ISP support : beeline now catches "host" but other spellings still work
|
||||
openwrt/LEDE : changed init script to work with procd
|
||||
tpws, nfqws : minor cosmetic fixes
|
||||
|
||||
v16
|
||||
|
||||
tpws: split-http-req=method : split inside method name, not after
|
||||
ISP support : mns.ru changed split pos to 3 (got redirect page with HEAD req : curl -I ej.ru)
|
||||
|
||||
v17
|
||||
|
||||
ISP support : athome moved from nfqws to tpws because of instability and http request hangs
|
||||
tpws : added options unixeol,methodeol,hosttab
|
||||
|
||||
v18
|
||||
|
||||
tpws,nfqws : added hostnospace option
|
||||
|
||||
v19
|
||||
|
||||
tpws : added hostlist option
|
||||
|
||||
v20
|
||||
|
||||
added ip2net. ip2net groups ips from iplist into subnets and reduces ipset size twice
|
||||
|
||||
v21
|
||||
|
||||
added mdig. get_reestr.sh is *real* again
|
||||
|
||||
v22
|
||||
|
||||
total review of init script logic
|
||||
dropped support of older debian 7 and ubuntu 12/14 systems
|
||||
install_bin.sh : auto binaries preparation
|
||||
docs: readme review. some new topics added, others deleted
|
||||
docs: VPN setup with policy based routing using wireguard
|
||||
docs: wireguard modding guide
|
||||
|
||||
v23
|
||||
|
||||
major init system rewrite
|
||||
openwrt : separate firewall include /etc/firewall.zapret
|
||||
install_easy.sh : easy setup on openwrt, debian, ubuntu, centos, fedora, opensuse
|
||||
|
||||
v24
|
||||
|
||||
separate config from init scripts
|
||||
gzip support in ipset/*.sh and tpws
|
||||
|
||||
v25
|
||||
|
||||
init : move to native systemd units
|
||||
use links to units, init scripts and firewall includes, no more copying
|
||||
|
||||
v26
|
||||
|
||||
ipv6 support
|
||||
tpws : advanced bind options
|
||||
|
||||
v27
|
||||
|
||||
tpws : major connection code rewrite. originally it was derived from not top quality example , with many bugs and potential problems.
|
||||
next generation connection code uses nonblocking sockets. now its in EXPERIMENTAL state.
|
||||
|
||||
v28
|
||||
|
||||
tpws : added socks5 support
|
||||
ipset : major RKN getlist rewrite. added antifilter.network support
|
||||
|
||||
v29
|
||||
|
||||
nfqws : DPI desync attack
|
||||
ip exclude system
|
||||
|
||||
v30
|
||||
|
||||
nfqws : DPI desync attack modes : fake,rst
|
42
docs/compile/build_howto_openwrt.txt
Normal file
42
docs/compile/build_howto_openwrt.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
How to compile native programs for use in openwrt
|
||||
-------------------------------------------------
|
||||
|
||||
1) <fetch correct version of openwrt>
|
||||
|
||||
cd ~
|
||||
|
||||
<chaos calmer>
|
||||
git clone git://git.openwrt.org/15.05/openwrt.git
|
||||
<barrier breaker>
|
||||
git clone git://git.openwrt.org/14.07/openwrt.git
|
||||
<trunk>
|
||||
git clone git://git.openwrt.org/openwrt.git
|
||||
|
||||
cd openwrt
|
||||
|
||||
2) ./scripts/feeds update -a
|
||||
./scripts/feeds install -a
|
||||
|
||||
3) #add zapret packages to build root
|
||||
#copy package descriptions
|
||||
copy compile/openwrt/* to ~/openwrt
|
||||
#copy source code of tpws
|
||||
copy tpws to ~/openwrt/package/zapret/tpws
|
||||
#copy source code of nfq
|
||||
copy nfq to ~/openwrt/package/zapret/nfq
|
||||
#copy source code of ip2net
|
||||
copy ip2net to ~/openwrt/package/zapret/ip2net
|
||||
|
||||
4) make menuconfig
|
||||
#select your target architecture
|
||||
#select packages Network/Zapret/* as "M"
|
||||
|
||||
5) make toolchain/compile
|
||||
|
||||
6) make package/tpws/compile
|
||||
make package/nfqws/compile
|
||||
make package/ip2net/compile
|
||||
make package/mdig/compile
|
||||
|
||||
7) find bin -name tpws*.ipk
|
||||
#take your tpws*.ipk , nfqws*.ipk , ip2net*.ipk, mdig*.ipk from there
|
32
docs/compile/openwrt/package/zapret/ip2net/Makefile
Normal file
32
docs/compile/openwrt/package/zapret/ip2net/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ip2net
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/ip2net
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=ip2net
|
||||
SUBMENU:=Zapret
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./ip2net/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
|
||||
endef
|
||||
|
||||
define Package/ip2net/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/ip2net
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/ip2net
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ip2net))
|
||||
|
1
docs/compile/openwrt/package/zapret/ip2net/readme.txt
Normal file
1
docs/compile/openwrt/package/zapret/ip2net/readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
Copy "ip2net" folder here !
|
32
docs/compile/openwrt/package/zapret/mdig/Makefile
Normal file
32
docs/compile/openwrt/package/zapret/mdig/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=mdig
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/mdig
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=mdig
|
||||
SUBMENU:=Zapret
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./mdig/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
|
||||
endef
|
||||
|
||||
define Package/mdig/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/mdig
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/mdig
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mdig))
|
||||
|
1
docs/compile/openwrt/package/zapret/mdig/readme.txt
Normal file
1
docs/compile/openwrt/package/zapret/mdig/readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
Copy "mdig" folder here !
|
34
docs/compile/openwrt/package/zapret/nfqws/Makefile
Normal file
34
docs/compile/openwrt/package/zapret/nfqws/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=nfqws
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/nfqws
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=nfqws
|
||||
SUBMENU:=Zapret
|
||||
DEPENDS:=+libnetfilter-queue +libcap +zlib
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./nfq/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
|
||||
endef
|
||||
|
||||
define Package/nfqws/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/nfq
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/nfq
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,nfqws))
|
||||
|
||||
|
1
docs/compile/openwrt/package/zapret/nfqws/readme.txt
Normal file
1
docs/compile/openwrt/package/zapret/nfqws/readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
Copy "nfq" folder here !
|
33
docs/compile/openwrt/package/zapret/tpws/Makefile
Normal file
33
docs/compile/openwrt/package/zapret/tpws/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=tpws
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/tpws
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
TITLE:=tpws
|
||||
SUBMENU:=Zapret
|
||||
DEPENDS:=+zlib +libcap
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./tpws/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS)
|
||||
endef
|
||||
|
||||
define Package/tpws/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/tpws
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/tpws
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,tpws))
|
||||
|
1
docs/compile/openwrt/package/zapret/tpws/readme.txt
Normal file
1
docs/compile/openwrt/package/zapret/tpws/readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
Copy "tpws" folder here !
|
159
docs/https.txt
Normal file
159
docs/https.txt
Normal file
@@ -0,0 +1,159 @@
|
||||
Расскажу как я решал вопрос с блокировкой https на роутере.
|
||||
На тех провайдерах, что мне доступны, все, кроме одного либо банили https по IP (вообще нет конекта), либо захватывали TLS сессию и она намертво зависала - пакеты больше не приходили. На домру удалось выяснить, что DPI цепляется к SNI (Server Name Indication) в TLS, но сплит TLS запроса не помог. Я пришел к выводу, что https самым разумным будет прозрачно заворачивать в socks.
|
||||
Tor поддерживает "из коробки" режим transparent proxy. Это можно использовать в теории, но практически - только на роутерах с 128 мб памяти и выше. Таких роутеров не так много. В основном объем памяти 32 или 64 мб. И тор еще и тормозной.
|
||||
Другой вариант напрашивается, если у вас есть доступ к какой-нибудь unix системе с SSH, где сайты не блокируются. Например, у вас есть VPS вне России. Именно так и поступил.
|
||||
Понятийно требуются следующие шаги :
|
||||
1) Выделять IP, на которые надо проксировать трафик. У нас уже имеется ipset "zapret", технология создания которого отработана.
|
||||
2) Сделать так, чтобы все время при загрузке системы на некотором порту возникал socks.
|
||||
3) Установить transparent соксификатор. Redsocks прекрасно подошел на эту роль.
|
||||
4) Завернуть через iptables трафик с порта назначения 443 и на ip адреса из ipset 'zapret' на соксификатор
|
||||
Буду рассматривать систему на базе openwrt, где уже установлена система обхода dpi "zapret".
|
||||
По крайней мере нужно иметь заполненный ipset 'zapret', устанавливать tpws или nfqws не обязательно.
|
||||
Более того, если они на вашей системе не срабатывают, то можно соксифицировать не только https, но и http.
|
||||
|
||||
* Сделать так, чтобы все время при загрузке системы на некотором порту возникал socks
|
||||
|
||||
Т.к. дефолтный dropbear клиент не поддерживает создание socks, то для начала придется заменить dropbear ssh client на openssh : пакеты openssh-client и openssh-client-utils.
|
||||
Устанавливать их нужно с опцией opkg --force-overwrite, поскольку они перепишут ssh клиент от dropbear.
|
||||
После установки пакетов расслабим неоправданно жестокие права : chmod 755 /etc/ssh.
|
||||
Следует создать пользователя, под которым будем крутить ssh client. Допустим, это будет 'proxy'.
|
||||
Сначала установить пакет shadow-useradd.
|
||||
------------------
|
||||
useradd -d /home/proxy proxy
|
||||
mkdir -p /home/proxy
|
||||
chown proxy:proxy /home/proxy
|
||||
------------------
|
||||
Openssh ловит разные глюки, если у него нет доступа к /dev/tty.
|
||||
Добавим в /etc/rc.local строчку : "chmod 666 /dev/tty"
|
||||
Сгенерируем для него ключ RSA для доступа к ssh серверу.
|
||||
------------------
|
||||
su proxy
|
||||
cd
|
||||
mkdir -m 700 .ssh
|
||||
cd .ssh
|
||||
ssh-keygen
|
||||
ls
|
||||
exit
|
||||
------------------
|
||||
Должны получиться файлы id_rsa и id_rsa.pub.
|
||||
Строчку из id_rsa.pub следует добавить на ssh сервер в файл $HOME/.ssh/authorized_keys.
|
||||
Более подробно о доступе к ssh через авторизацию по ключам : https://beget.com/ru/articles/ssh_by_key
|
||||
Предположим, ваш ssh сервер - vps.mydomain.com, пользователь называется 'proxy'.
|
||||
Проверить подключение можно так : ssh -N -D 1098 -l proxy vps.mydomain.com.
|
||||
Сделайте это под пользователем "proxy", поскольку при первом подключении ssh спросит о правильности hostkey.
|
||||
Соединение может отвалиться в любой момент, поэтому нужно зациклить запуск ssh.
|
||||
Для этого лучший вариант - использовать procd - упрощенная замена systemd на openwrt версий BB и выше.
|
||||
--- /etc/init.d/socks_vps ---
|
||||
#!/bin/sh /etc/rc.common
|
||||
START=50
|
||||
STOP=50
|
||||
USE_PROCD=1
|
||||
USERNAME=proxy
|
||||
COMMAND="ssh -N -D 1098 -l proxy vps.mydomain.com"
|
||||
start_service() {
|
||||
procd_open_instance
|
||||
procd_set_param user $USERNAME
|
||||
procd_set_param respawn 10 10 0
|
||||
procd_set_param command $COMMAND
|
||||
procd_close_instance
|
||||
}
|
||||
-----------------------------
|
||||
Этому файлу нужно дать права : chmod +x /etc/init.d/socks_vps
|
||||
Запуск : /etc/init.d/socks_vps start
|
||||
Останов : /etc/init.d/socks_vps stop
|
||||
Включить автозагрузку : /etc/init.d/socks_vps enable
|
||||
Проверка : curl -4 --socks5 127.0.0.1:1098 https://rutracker.org
|
||||
|
||||
* Организовать прозрачную соксификацию
|
||||
|
||||
Установить пакет redsocks.
|
||||
Конфиг :
|
||||
-- /etc/redsocks.conf : ---
|
||||
base {
|
||||
log_debug = off;
|
||||
log_info = on;
|
||||
log = "syslog:local7";
|
||||
daemon = on;
|
||||
user = nobody;
|
||||
group = nogroup;
|
||||
redirector = iptables;
|
||||
}
|
||||
redsocks {
|
||||
local_ip = 127.0.0.1;
|
||||
local_port = 1099;
|
||||
ip = 127.0.0.1;
|
||||
port = 1098;
|
||||
type = socks5;
|
||||
}
|
||||
---------------------------
|
||||
После чего перезапускаем : /etc/init.d/redsocks restart
|
||||
Смотрим появился ли листенер : netstat -tnlp | grep 1099
|
||||
Автостарт redsocks при таком конфиге не работает, потому что на момент запуска сеть не инициализирована, и у нас даже нет 127.0.0.1.
|
||||
Вместо штатного автостарта будем вешаться на события поднятия интерфейса. Разберем это позже.
|
||||
Пока что отключим автостарт : /etc/init.d/redsocks disable
|
||||
|
||||
* Завертывание соединений через iptables
|
||||
|
||||
Будем завертывать любые tcp соединения на ip из ipset "ipban" и https на ip из ipset "zapret".
|
||||
|
||||
--- /etc/firewall.user -----
|
||||
SOXIFIER_PORT=1099
|
||||
|
||||
. /opt/zapret/init.d/openwrt/functions
|
||||
|
||||
create_ipset no-update
|
||||
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device ext_device $ext_iface
|
||||
ipt OUTPUT -t nat -o $ext_device -p tcp --dport 443 -m set --match-set zapret dst -j REDIRECT --to-port $SOXIFIER_PORT
|
||||
ipt OUTPUT -t nat -o $ext_device -p tcp -m set --match-set ipban dst -j REDIRECT --to-port $SOXIFIER_PORT
|
||||
done
|
||||
|
||||
network_get_device DEVICE lan
|
||||
sysctl -w net.ipv4.conf.$DEVICE.route_localnet=1
|
||||
ipt prerouting_lan_rule -t nat -p tcp --dport 443 -m set --match-set zapret dst -j DNAT --to 127.0.0.1:$SOXIFIER_PORT
|
||||
ipt prerouting_lan_rule -t nat -p tcp -m set --match-set ipban dst -j DNAT --to 127.0.0.1:$SOXIFIER_PORT
|
||||
----------------------------
|
||||
|
||||
Внести параметр "reload" в указанное место :
|
||||
--- /etc/config/firewall ---
|
||||
config include
|
||||
option path '/etc/firewall.user'
|
||||
option reload '1'
|
||||
----------------------------
|
||||
|
||||
Перезапуск : /etc/init.d/firewall restart
|
||||
Все, теперь можно проверять :
|
||||
/etc/init.d/redsocks stop
|
||||
curl -4 https://rutracker.org
|
||||
# должно обломаться с надписью "Connection refused". если не обламывается - значит ip адрес rutracker.org не в ipset,
|
||||
# либо не сработали правила фаервола. например, из-за не установленных модулей ipt
|
||||
/etc/init.d/redsocks start
|
||||
curl -4 https://rutracker.org
|
||||
# должно выдать страницу
|
||||
|
||||
* Автозапуск redsocks
|
||||
|
||||
Я сделал для себя небольшой скриптик, вешающийся на события поднятия и опускания интерфейсов.
|
||||
|
||||
--- /etc/hotplug.d/iface/99-exec-on-updown ---
|
||||
#!/bin/sh
|
||||
if [ "$ACTION" = ifup ]; then
|
||||
cmd=$(uci get network.$INTERFACE.exec_on_up)
|
||||
[ -n "$cmd" ] && $cmd
|
||||
fi
|
||||
if [ "$ACTION" = ifdown ]; then
|
||||
cmd=$(uci get network.$INTERFACE.exec_on_down)
|
||||
[ -n "$cmd" ] && $cmd
|
||||
fi
|
||||
----------------------------------------------
|
||||
|
||||
Теперь можно в описания интерфейсов внести в соответствующий раздел :
|
||||
--- /etc/config/nework ---
|
||||
config interface 'wan'
|
||||
........
|
||||
option exec_on_up '/etc/init.d/redsocks start'
|
||||
--------------------------
|
||||
reboot. Заходим снова, смотрим, что есть redsocks, есть ssh, опять проверяем curl -4 https://rutracker.org.
|
||||
Пробуем зайти на https://rutracker.org с компа внутри локалки.
|
62
docs/iptables.txt
Normal file
62
docs/iptables.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
For window size changing :
|
||||
|
||||
iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
For outgoing data manipulation ("Host:" case changing) :
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
For dpi desync attack :
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
|
||||
For TPROXY :
|
||||
|
||||
sysctl -w net.ipv4.ip_forward=1
|
||||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
ip -f inet rule add fwmark 1 lookup 100
|
||||
ip -f inet route add local default dev lo table 100
|
||||
# prevent loop
|
||||
iptables -t filter -I INPUT -p tcp --dport 1188 -j REJECT
|
||||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j MARK --set-mark 1
|
||||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188
|
||||
|
||||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m set --match-set zapret dst -j MARK --set-mark 1
|
||||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m mark --mark 0x1/0x1 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188
|
||||
|
||||
For DNAT :
|
||||
|
||||
# run tpws as user "tpws". its required to avoid loops.
|
||||
sysctl -w net.ipv4.conf.eth1.route_localnet=1
|
||||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188
|
||||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188
|
||||
|
||||
|
||||
Reset all iptable rules :
|
||||
|
||||
iptables -F
|
||||
iptables -X
|
||||
iptables -t nat -F
|
||||
iptables -t nat -X
|
||||
iptables -t mangle -F
|
||||
iptables -t mangle -X
|
||||
iptables -t raw -F
|
||||
iptables -t raw -X
|
||||
|
||||
Reset iptable policies :
|
||||
|
||||
iptables -P INPUT ACCEPT
|
||||
iptables -P FORWARD ACCEPT
|
||||
iptables -P OUTPUT ACCEPT
|
||||
iptables -t mangle -P POSTROUTING ACCEPT
|
||||
iptables -t mangle -P PREROUTING ACCEPT
|
||||
iptables -t mangle -P INPUT ACCEPT
|
||||
iptables -t mangle -P FORWARD ACCEPT
|
||||
iptables -t mangle -P OUTPUT ACCEPT
|
||||
iptables -t raw -P PREROUTING ACCEPT
|
||||
iptables -t raw -P OUTPUT ACCEPT
|
475
docs/readme.eng.txt
Normal file
475
docs/readme.eng.txt
Normal file
@@ -0,0 +1,475 @@
|
||||
What is it for
|
||||
--------------
|
||||
|
||||
Bypass the blocking of web sites http.
|
||||
The project is mainly aimed at the Russian audience to fight russian regulator named "Roskomnadzor".
|
||||
Some features of the project are russian reality specific (such as getting list of sites
|
||||
blocked by Roskomnadzor), but most others are common.
|
||||
|
||||
How it works
|
||||
------------
|
||||
|
||||
DPI providers have gaps. They happen because DPI rules are writtten for
|
||||
ordinary user programs, omitting all possible cases that are permissible by standards.
|
||||
This is done for simplicity and speed. It makes no sense to catch 0.01% hackers,
|
||||
because these blockings are quite simple and easily bypassed even by ordinary users.
|
||||
|
||||
Some DPIs cannot recognize the http request if it is divided into TCP segments.
|
||||
For example, a request of the form "GET / HTTP / 1.1 \ r \ nHost: kinozal.tv ......"
|
||||
we send in 2 parts: first go "GET", then "/ HTTP / 1.1 \ r \ nHost: kinozal.tv .....".
|
||||
Other DPIs stumble when the "Host:" header is written in another case: for example, "host:".
|
||||
Sometimes work adding extra space after the method: "GET /" => "GET /"
|
||||
or adding a dot at the end of the host name: "Host: kinozal.tv."
|
||||
|
||||
|
||||
How to put this into practice in the linux system
|
||||
-------------------------------------------------
|
||||
|
||||
How to make the system break the request into parts? You can pipe the entire TCP session
|
||||
through transparent proxy, or you can replace the tcp window size field on the first incoming TCP packet with a SYN, ACK.
|
||||
Then the client will think that the server has set a small window size for it and the first data segment
|
||||
will send no more than the specified length. In subsequent packages, we will not change anything.
|
||||
The further behavior of the system depends on the implemented algorithm in the OS.
|
||||
Experience shows that linux always sends first packet no more than the specified
|
||||
in window size length, the rest of the packets until some time sends no more than max (36, specified_size).
|
||||
After a number of packets, the window scaling mechanism is triggered and starts taking
|
||||
the scaling factor into account. The packet size becomes no more than max (36, specified_ramer << scale_factor).
|
||||
The behavior is not very elegant, but since we do not affect the size of the incoming packets,
|
||||
and the amount of data received in http is usually much higher than the amount sent, then visually
|
||||
there will be only small delays.
|
||||
Windows behaves in a similar case much more predictably. First segment
|
||||
the specified length goes away, then the window size changes depending on the value,
|
||||
sent in new tcp packets. That is, the speed is almost immediately restored to the possible maximum.
|
||||
|
||||
Its easy to intercept a packet with SYN, ACK using iptables.
|
||||
However, the options for editing packets in iptables are severely limited.
|
||||
It’s not possible to change window size with standard modules.
|
||||
For this, we will use the NFQUEUE. This tool allows transfer packets to the processes running in user mode.
|
||||
The process, accepting a packet, can change it, which is what we need.
|
||||
|
||||
iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
It will queue the packets we need to the process that listens on the queue with the number 200.
|
||||
Process will replace the window size. PREROUTING will catch packets addressed to the host itself and routed packets.
|
||||
That is, the solution works the same way as on the client, so on the router. On a PC-based or OpenWRT router.
|
||||
In principle, this is enough.
|
||||
However, with such an impact on TCP there will be a slight delay.
|
||||
In order not to touch the hosts that are not blocked by the provider, you can make such a move.
|
||||
Create a list of blocked domains, resolve them to IP addresses and save to ipset named "zapret".
|
||||
Add to rule:
|
||||
|
||||
iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
Thus, the impact will be made only on ip addresses related to blocked sites.
|
||||
The list can be updated in scheduled task every few days.
|
||||
|
||||
If DPI cant be bypassed with splitting a request into segments, then sometimes helps changing case
|
||||
of the "Host:" http header. We may not need a window size replacement, so the do not need PREROUTING chain.
|
||||
Instead, we hang on outgoing packets in the POSTROUTING chain:
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
In this case, additional points are also possible. DPI can catch only the first http request, ignoring
|
||||
subsequent requests in the keep-alive session. Then we can reduce the cpu load abandoning the processing of unnecessary packages.
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
It happens that the provider monitors the entire HTTP session with keep-alive requests. In this case
|
||||
it is not enough to restrict the TCP window when establishing a connection. Each http request must be splitted
|
||||
to multiple TCP segments. This task is solved through the full proxying of traffic using
|
||||
transparent proxy (TPROXY or DNAT). TPROXY does not work with connections originating from the local system
|
||||
so this solution is applicable only on the router. DNAT works with local connections,
|
||||
but there is a danger of entering into endless recursion, so the daemon is launched as a separate user,
|
||||
and for this user, DNAT is disabled via "-m owner". Full proxying requires more resources than outbound packet
|
||||
manipulation without reconstructing a TCP connection.
|
||||
|
||||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188
|
||||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188
|
||||
|
||||
NOTE: DNAT on localhost works in the OUTPUT chain, but does not work in the PREROUTING chain without enabling the route_localnet parameter:
|
||||
|
||||
sysctl -w net.ipv4.conf.<incoming_interface_name>.route_localnet=1
|
||||
|
||||
You can use "-j REDIRECT --to-port 1188" instead of DNAT, but in this case the transpareny proxy process
|
||||
should listen on the ip address of the incoming interface or on all addresses. Listen all - not good
|
||||
in terms of security. Listening one (local) is possible, but in the case of automated
|
||||
script will have to recognize it, then dynamically enter it into the command. In any case, additional efforts are required.
|
||||
|
||||
ip6tables
|
||||
---------
|
||||
|
||||
ip6tables work almost exactly the same way as ipv4, but there are a number of important nuances.
|
||||
In DNAT, you should take the address --to in square brackets. For example :
|
||||
|
||||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:1188
|
||||
|
||||
The route_localnet parameter does not exist for ipv6.
|
||||
DNAT to localhost (:: 1) is possible only in the OUTPUT chain.
|
||||
In the PREROUTING DNAT chain, it is possible to any global address or to the link local address of the same interface
|
||||
the packet came from.
|
||||
NFQUEUE works without changes.
|
||||
|
||||
When it will not work
|
||||
----------------------
|
||||
|
||||
* If DNS server returns false responses. ISP can return false IP addresses or not return anything
|
||||
when blocked domains are queried. If this is the case change DNS to public ones, such as 8.8.8.8 or 1.1.1.1.
|
||||
Sometimes ISP hijacks queries to any DNS server. Dnscrypt or dns-over-tls help.
|
||||
* If blocking is done by IP.
|
||||
* If a connection passes through a filter capable of reconstructing a TCP connection, and which
|
||||
follows all standards. For example, we are routed to squid. Connection goes through the full OS tcpip stack,
|
||||
fragmentation disappears immediately as a means of circumvention. Squid is correct, it will find everything
|
||||
as it should, it is useless to deceive him.
|
||||
BUT. Only small providers can afford using squid, since it is very resource intensive.
|
||||
Large companies usually use DPI, which is designed for much greater bandwidth.
|
||||
|
||||
nfqws
|
||||
-----
|
||||
|
||||
This program is a packet modifier and a NFQUEUE queue handler.
|
||||
It takes the following parameters:
|
||||
|
||||
--debug=0|1 ; 1=print debug info
|
||||
--qnum=<nfqueue_number>
|
||||
--wsize=<window_size> ; set window size. 0 = do not modify
|
||||
--hostcase ; change Host: => host:
|
||||
--hostspell=HoSt ; exact spelling of the "Host" header. must be 4 chars. default is "host"
|
||||
--hostnospace ; remove space after Host: and add it to User-Agent: to preserve packet size
|
||||
--daemon ; daemonize
|
||||
--pidfile=<filename> ; write pid to file
|
||||
--user=<username> ; drop root privs
|
||||
--uid=uid[:gid] ; drop root privs
|
||||
--dpi-desync[=fake|rst|rstack|disorder] ; try to desync dpi state
|
||||
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000
|
||||
--dpi-desync-ttl=<int> ; set ttl for desync packet
|
||||
--dpi-desync-fooling=none|md5sig|badsum
|
||||
--dpi-desync-retrans=0|1 ; (fake,rst,rstack only) 0(default)=reinject original data packet after fake 1=drop original data packet to force its retransmission
|
||||
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not apply desync to requests without hostname in the SNI
|
||||
--dpi-desync-split-pos=<1..1500> ; (for disorder only) split TCP packet at specified position
|
||||
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply)
|
||||
|
||||
The manipulation parameters can be combined in any way.
|
||||
|
||||
COMMENT. As described earlier, Linux behaves strangely when the window size is changed, unlike Windows.
|
||||
Following segments do not restore their full length. Connection can go for a long time in batches of small packets.
|
||||
Package modification parameters (--hostcase, ...) may not work, because nfqws does not work with the connection,
|
||||
but only with separate packets in which the search may not be found, because scattered across multiple packets.
|
||||
If the source of the packages is Windows, there is no such problem.
|
||||
|
||||
DPI DESYNC ATTACK
|
||||
After completion of the tcp 3-way handshake, the first data packet from the client goes.
|
||||
It usually has "GET / ..." or TLS ClientHello. We drop this packet, replacing with something else.
|
||||
It can be a fake version with another harmless but valid http or https request (fake), tcp reset packet (rst,rstack),
|
||||
split into 2 segments original packet with fake segment in the middle (disorder).
|
||||
In articles these attack have names "TCB desynchronization" and "TCB teardown".
|
||||
Fake packet must reach DPI, but do not reach the destination server.
|
||||
The following means are available: set a low TTL, send a packet with bad checksum,
|
||||
add tcp option "MD5 signature". All of them have their own disadvantages :
|
||||
|
||||
* md5sig does not work on all servers
|
||||
* badsum doesn't work if your device is behind NAT which does not pass invalid packets.
|
||||
Linux NAT by default does not pass them without special setting "sysctl -w net.netfilter.nf_conntrack_checksum=0"
|
||||
Openwrt sets it from the box, other routers in most cases dont, and its not always possible to change it.
|
||||
If nfqws is on the router, its not neccessary to switch of "net.netfilter.nf_conntrack_checksum".
|
||||
Fake packet doesn't go through FORWARD chain, it goes through OUTPUT. But if your router is behind another NAT, for example ISP NAT,
|
||||
and that NAT does not pass invalid packets, you cant do anything.
|
||||
* TTL looks like the best option, but it requires special tuning for earch ISP. If DPI is further than local ISP websites
|
||||
you can cut access to them. Manual IP exclude list is required. Its possible to use md5sig with ttl.
|
||||
This way you cant hurt anything, but good chances it will help to open local ISP websites.
|
||||
If automatic solution cannot be found then use zapret-hosts-user-exclude.txt.
|
||||
|
||||
For fake,rst,rstack modes original packet can be sent after the fake one or just dropped.
|
||||
If its dropped OS will perform first retransmission after 0.2 sec, then the delay increases exponentially.
|
||||
Delay can help to make sure fake and original packets are properly ordered and processed on DPI.
|
||||
|
||||
Disorder mode splits original packet and sends packets in the following order :
|
||||
1. 2nd segment
|
||||
2. fake 1st segment, data filled with zeroes
|
||||
3. 1st segment
|
||||
4. fake 1st segment, data filled with zeroes (2nd copy)
|
||||
Original packet is always dropped. --dpi-desync-split-pos sets split position (default 3).
|
||||
If position is higher than packet length, pos=1 is used.
|
||||
This sequence is designed to make reconstruction of critical message as difficult as possible.
|
||||
Fake segments may not be required to bypass some DPIs, but can potentially help if more sophisticated reconstruction
|
||||
algorithms are used.
|
||||
|
||||
Hostlist is applicable only to desync attack. It does not work for other options.
|
||||
Hosts are extracted from plain http request Host: header and SNI of ClientHelllo TLS message.
|
||||
Subdomains are applied automatically. gzip lists are supported.
|
||||
|
||||
iptables for performing the attack :
|
||||
|
||||
iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||||
|
||||
connbytes will only queue the first data packet. mark is needed to keep away generated packets from NFQUEUE.
|
||||
nfqws sets fwmark when it sends generated packets.
|
||||
|
||||
tpws
|
||||
-----
|
||||
|
||||
tpws is transparent proxy.
|
||||
|
||||
--debug=0|1|2 ; 0(default)=silent 1=verbose 2=debug
|
||||
--bind-addr=<ipv4_addr>|<ipv6_addr>
|
||||
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
|
||||
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
|
||||
--bind-linklocal=prefer|force ; prefer or force ipv6 link local
|
||||
--bind-wait-ifup=<sec> ; wait for interface to appear and up
|
||||
--bind-wait-ip=<sec> ; after ifup wait for ip address to appear up to N seconds
|
||||
--bind-wait-ip-linklocal=<sec> ; accept only link locals first N seconds then any
|
||||
--port=<port> ; port number to listen on
|
||||
--socks ; implement socks4/5 proxy instead of transparent proxy
|
||||
--local-rcvbuf=<bytes> ; SO_RCVBUF for local legs
|
||||
--local-sndbuf=<bytes> ; SO_SNDBUF for local legs
|
||||
--remote-rcvbuf=<bytes> ; SO_RCVBUF for remote legs
|
||||
--remote-sndbuf=<bytes> ; SO_SNDBUF for remote legs
|
||||
--skip-nodelay ; do not set TCP_NODELAY for outgoing connections. incompatible with split.
|
||||
--no-resolve ; disable socks5 remote dns
|
||||
--maxconn=<max_connections> ; max number of local legs
|
||||
--maxfiles=<max_open_files> ; max file descriptors (setrlimit). min requirement is (X*connections+16), where X=6 in tcp proxy mode, X=4 in tampering mode.
|
||||
; its worth to make a reserve with 1.5 multiplier. by default maxfiles is (X*connections)*1.5+16
|
||||
--max-orphan-time=<sec> ; if local leg sends something and closes and remote leg is still connecting then cancel connection attempt after N seconds
|
||||
|
||||
--hostlist=<filename> ; only act on host in the list (one host per line, subdomains auto apply)
|
||||
--split-http-req=method|host ; split http request at specified logical position
|
||||
--split-pos=<numeric_offset> ; split at specified pos. invalidates split-http-req.
|
||||
--hostcase ; change Host: => host:
|
||||
--hostspell ; exact spelling of "Host" header. must be 4 chars. default is "host"
|
||||
--hostdot ; add "." after Host: name
|
||||
--hosttab ; add tab after Host: name
|
||||
--hostnospace ; remove space after Host:
|
||||
--hostpad=<bytes> ; add dummy padding headers before Host:
|
||||
--methodspace ; add extra space after method
|
||||
--methodeol ; add end-of-line before method
|
||||
--unixeol ; replace 0D0A to 0A
|
||||
--daemon ; daemonize
|
||||
--pidfile=<filename> ; write pid to file
|
||||
--user=<username> ; drop root privs
|
||||
--uid=uid[:gid] ; drop root privs
|
||||
|
||||
The manipulation parameters can be combined in any way.
|
||||
There are exceptions: split-pos replaces split-http-req. hostdot and hosttab are mutually exclusive.
|
||||
Only split-pos option works for non-HTTP traffic.
|
||||
|
||||
tpws can bind only to one ip or to all at once.
|
||||
To bind to all ipv4, specify "0.0.0.0", to all ipv6 - "::". Without parameters, tpws bind to all ipv4 and ipv6.
|
||||
The --bind-wait * parameters can help in situations where you need to get IP from the interface, but it is not there yet, it is not raised
|
||||
or not configured.
|
||||
In different systems, ifup events are caught in different ways and do not guarantee that the interface has already received an IP address of a certain type.
|
||||
In the general case, there is no single mechanism to hang oneself on an event of the type "link local address appeared on the X interface."
|
||||
|
||||
in socks proxy mode no additional system privileges are required
|
||||
connection to local IPs of the system where tpws runs are prohibited
|
||||
tpws supports remote dns resolving (curl : --socks5-hostname firefox : socks_remote_dns=true) , but does it in blocking mode.
|
||||
tpws uses async sockets for all activity but resolving can break this model.
|
||||
if tpws serves many clients it can cause trouble. also DoS attack is possible against tpws.
|
||||
if remote resolving causes trouble configure clients to use local name resolution and use
|
||||
--no-resolve option on tpws side.
|
||||
|
||||
Ways to get a list of blocked IP
|
||||
--------------------------------
|
||||
|
||||
1) Enter the blocked domains to ipset/zapret-hosts-user.txt and run ipset/get_user.sh
|
||||
At the output, you get ipset/zapret-ip-user.txt with IP addresses.
|
||||
|
||||
2) ipset/get_reestr_*.sh. Russian specific
|
||||
|
||||
3) ipset/get_antifilter_*.sh. Russian specific
|
||||
|
||||
4) ipset/get_config.sh. This script calls what is written into the GETLIST variable from the config file.
|
||||
If the variable is not defined, then only lists for ipsets nozapret/nozapret6 are resolved.
|
||||
|
||||
So, if you're not russian, the only way for you is to manually add blocked domains.
|
||||
Or write your own ipset/get_iran_blocklist.sh , if you know where to download this one.
|
||||
|
||||
On routers, it is not recommended to call these scripts more than once in 2 days to minimize flash memory writes.
|
||||
|
||||
ipset/create_ipset.sh executes forced ipset update.
|
||||
The regulator list has already reached an impressive size of hundreds of thousands of IP addresses. Therefore, to optimize ipset
|
||||
ip2net utility is used. It takes a list of individual IP addresses and tries to find in it subnets of the maximum size (from / 22 to / 30),
|
||||
in which more than 3/4 addresses are blocked. ip2net is written in C because the operation is resource intensive.
|
||||
If ip2net is compiled or a binary is copied to the ip2net directory, the create_ipset.sh script uses an ipset of the hash:net type,
|
||||
piping the list through ip2net. Otherwise, ipset of hash:ip type is used, the list is loaded as is.
|
||||
Accordingly, if you don’t like ip2net, just remove the binary from the ip2net directory.
|
||||
create_ipset.sh supports loading ip lists from gzip files. First it looks for the filename with the ".gz" extension,
|
||||
such as "zapret-ip.txt.gz", if not found it falls back to the original name "zapret-ip.txt".
|
||||
So your own get_iran_blockslist.sh can use "zz" function to produce gz. Study how other russian get_XXX.sh work.
|
||||
Gzipping helps saving a lot of precious flash space on embedded systems.
|
||||
User lists are not gzipped because they are not expected to be very large.
|
||||
|
||||
You can add a list of domains to ipset/zapret-hosts-user-ipban.txt. Their ip addresses will be placed
|
||||
in a separate ipset "ipban". It can be used to route connections to transparent proxy "redsocks" or VPN.
|
||||
|
||||
IPV6: if ipv6 is enabled, then additional txt's are created with the same name, but with a "6" at the end before the extension.
|
||||
zapret-ip.txt => zapret-ip6.txt
|
||||
The ipsets zapret6 and ipban6 are created.
|
||||
|
||||
IP EXCLUSION SYSTEM. All scripts resolve zapret-hosts-user-exclude.txt file, creating zapret-ip-exclude.txt and zapret-ip-exclude6.txt.
|
||||
They are the source for ipsets nozapret/nozapret6. All rules created by init scripts are created with these ipsets in mind.
|
||||
The IPs placed in them are not involved in the process.
|
||||
zapret-hosts-user-exclude.txt can contain domains, ipv4 and ipv6 addresses or subnets.
|
||||
|
||||
Domain name filtering
|
||||
---------------------
|
||||
|
||||
An alternative to ipset is to use tpws with a list of domains.
|
||||
tpws can only read one hostlist.
|
||||
|
||||
Enter the blocked domains to ipset/zapret-hosts-users.txt. Remove ipset/zapret-hosts.txt.gz.
|
||||
Then the init script will run tpws with the zapret-hosts-users.txt list.
|
||||
|
||||
Other option ( Roskomnadzor list - get_hostlist.sh ) is russian specific.
|
||||
You can write your own replacement for get_hostlist.sh.
|
||||
|
||||
When filtering by domain name, tpws should run without filtering by ipset.
|
||||
All http traffic goes through tpws, and it decides whether to use manipulation depending on the Host: field in the http request.
|
||||
This creates an increased load on the system.
|
||||
The domain search itself works very quickly, the load is connected with pumping the amount of data through the process.
|
||||
When using large regulator lists estimate the amount of RAM on the router!
|
||||
|
||||
Choosing parameters
|
||||
-------------------
|
||||
|
||||
The file /opt/zapret/config is used by various components of the system and contains basic settings.
|
||||
It needs to be viewed and edited if necessary.
|
||||
Select MODE:
|
||||
|
||||
nfqws_ipset - use nfqws for http. targets are filtered by ipset "zapret"
|
||||
nfqws_ipset_https - use nfqws for http and https. targets are filtered by ipset "zapret"
|
||||
nfqws_all - use nfqws for all http
|
||||
nfqws_all_https - use nfqws for all http and https
|
||||
nfqws_all_desync - use nfqws for DPI desync attack on http и https for all http and https
|
||||
nfqws_ipset_desync - use nfqws for DPI desync attack on http и https for all http and https. targets are filtered by ipset "zapret"
|
||||
nfqws_hostlist_desync - use nfqws for DPI desync attack on http и https , only to hosts from hostlist
|
||||
|
||||
tpws_ipset - use tpws for http. targets are filtered by ipset "zapret"
|
||||
tpws_ipset_https - use tpws for http and https. targets are filtered by ipset "zapret"
|
||||
tpws_all - use tpws for all http
|
||||
tpws_all_https - use tpws for all http and https
|
||||
tpws_hostlist - same as tpws_all but touch only domains from the hostlist
|
||||
|
||||
ipset - only fill ipset. futher actions depend on your own code
|
||||
|
||||
Its possible to change manipulation options used by the daemons :
|
||||
|
||||
NFQWS_OPT="--wsize=3 --hostspell=HOST"
|
||||
TPWS_OPT_HTTP="--hostspell=HOST --split-http-req=method"
|
||||
TPWS_OPT_HTTPS="--split-pos=3"
|
||||
|
||||
Options for DPI desync attack are configured separately:
|
||||
|
||||
DESYNC_MARK=0x40000000
|
||||
NFQWS_OPT_DESYNC="--dpi-desync --dpi-desync-ttl=0 --dpi-desync-fooling=badsum --dpi-desync-fwmark=$DESYNC_MARK"
|
||||
|
||||
|
||||
The GETLIST parameter tells the install_easy.sh installer which script to call
|
||||
to update the list of blocked ip or hosts.
|
||||
Its called via get_config.sh from scheduled tasks (crontab or systemd timer).
|
||||
Put here the name of the script that you will use to update the lists.
|
||||
If not, then the parameter should be commented out.
|
||||
|
||||
You can individually disable ipv4 or ipv6. If the parameter is commented out or not equal to "1",
|
||||
use of the protocol is permitted.
|
||||
#DISABLE_IPV4=1
|
||||
DISABLE_IPV6=1
|
||||
|
||||
The number of threads for mdig multithreaded DNS resolver (1..100).
|
||||
The more of them, the faster, but will your DNS server be offended by hammering ?
|
||||
MDIG_THREADS=30
|
||||
|
||||
The following settings are not relevant for openwrt :
|
||||
|
||||
If your system works as a router, then you need to enter the names of the internal and external interfaces:
|
||||
IFACE_LAN = eth0
|
||||
IFACE_WAN = eth1
|
||||
IMPORTANT: configuring routing, masquerade, etc. not a zapret task.
|
||||
Only modes that intercept transit traffic are enabled.
|
||||
|
||||
The INIT_APPLY_FW=1 parameter enables the init script to independently apply iptables rules.
|
||||
With other values or if the parameter is commented out, the rules will not be applied.
|
||||
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
|
||||
|
||||
Screwing to the firewall control system or your launch system
|
||||
-------------------------------------------------------------
|
||||
|
||||
If you use some kind of firewall management system, then it may conflict with an existing startup script.
|
||||
When re-applying the rules, it could break the iptables settings from the zapret.
|
||||
In this case, the rules for iptables should be screwed to your firewall separately from running tpws or nfqws.
|
||||
|
||||
The following calls allow you to apply or remove iptables rules separately:
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret start-fw
|
||||
/opt/zapret/init.d/sysv/zapret stop-fw
|
||||
|
||||
And you can start or stop the demons separately from the firewall:
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret start-daemons
|
||||
/opt/zapret/init.d/sysv/zapret stop-daemons
|
||||
|
||||
|
||||
Simple install to desktop linux system
|
||||
--------------------------------------
|
||||
|
||||
Simple install works on most modern linux distributions with systemd.
|
||||
Run install_easy.sh and answer its questions.
|
||||
|
||||
Simple install to openwrt
|
||||
-------------------------
|
||||
|
||||
install_easy.sh also works on openwrt but there're additional challenges.
|
||||
They are mainly about possibly low flash free space.
|
||||
Simple install will not work if it has no space to install itself and required packages from the repo.
|
||||
|
||||
Another challenge would be to bring zapret to the router. You can download zip from github and use it.
|
||||
Do not repack zip contents in the Windows, because this way you break chmod and links.
|
||||
Install openssh-sftp-server and unzip to openwrt and use sftp to transfer the file.
|
||||
|
||||
The best way to start is to put zapret dir to /tmp and run /tmp/zapret/install_easy.sh from there.
|
||||
After installation remove /tmp/zapret to free RAM.
|
||||
|
||||
The absolute minimum for openwrt is 64/8 system, 64/16 is comfortable, 128/extroot is recommended.
|
||||
|
||||
|
||||
Android
|
||||
-------
|
||||
|
||||
Its not possible to use nfqws and tpws in transparent proxy mode without root privileges.
|
||||
Without root tpws can run in --socks mode.
|
||||
|
||||
I have no NFQUEUE presence statistics in stock android kernels, but its present on my MTK device.
|
||||
If NFQUEUE is present nfqws works.
|
||||
|
||||
There's no ipset support unless you run custom kernel. In common case task of bringing up ipset
|
||||
on android is ranging from "not easy" to "almost impossible", unless you find working kernel
|
||||
image for your device.
|
||||
|
||||
Android does not use /etc/passwd, tpws --user won't work. There's replacement.
|
||||
Use numeric uids in --uid option.
|
||||
Its recommended to use gid 3003 (AID_INET), otherwise tpws will not have inet access.
|
||||
Example : --uid 1:3003
|
||||
In iptables use : "! --uid-owner 1" instead of "! --uid-owner tpws".
|
||||
|
||||
Write your own shell script with iptables and tpws, run it using your root manager.
|
||||
Autorun scripts are here :
|
||||
magisk : /data/adb/service.d
|
||||
supersu : /system/su.d
|
||||
|
||||
I haven't checked whether android can kill iptable rules at its own will during wifi connection/disconnection,
|
||||
mobile data on/off, ...
|
||||
|
||||
|
||||
Https blocking bypass
|
||||
----------------------
|
||||
|
||||
As a rule, DPI tricks do not help to bypass https blocking.
|
||||
You have to redirect traffic through a third-party host.
|
||||
It is proposed to use transparent redirect through socks5 using iptables + redsocks, or iptables + iproute + vpn.
|
||||
Redsocks variant is described in https.txt.
|
||||
iproute + wireguard - in wireguard_iproute_openwrt.txt.
|
||||
(they are russian)
|
||||
|
||||
SOMETIMES (but not often) a tls handshake split trick works.
|
||||
Try MODE=..._https
|
||||
May be you're lucky.
|
||||
|
||||
MORE OFTEN DPI desync attack work, but it may require some manual tuning.
|
1132
docs/readme.txt
Normal file
1132
docs/readme.txt
Normal file
File diff suppressed because it is too large
Load Diff
133
docs/wireguard/010-wg-mod.patch
Normal file
133
docs/wireguard/010-wg-mod.patch
Normal file
@@ -0,0 +1,133 @@
|
||||
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
|
||||
+ get_random_bytes_wait(>rash, 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 */
|
244
docs/wireguard/wireguard-mod.txt
Normal file
244
docs/wireguard/wireguard-mod.txt
Normal file
@@ -0,0 +1,244 @@
|
||||
Посвящено возможной блокировке в РФ VPN протоколов через DPI.
|
||||
Предпосылками являются последние законодательные акты и во всю сочащиеся "секретные" записки.
|
||||
В РФ разрабатываются и готовятся к применению более продвинутые решения по блокировке трафика.
|
||||
Вполне вероятно будут резать стандартные VPN протоколы. Нам надо быть к этому готовыми.
|
||||
|
||||
Один из возможных и перспективных путей решения данного вопроса - кустомная модификация
|
||||
исходников VPN с целью незначительного изменения протокола, ломающего стандартные модули обнаружения в DPI.
|
||||
Это относительно сложно, доступно только для гиков.
|
||||
Никто не будет разрабатывать специальные модули обнаружения в DPI, если только кто-то не сделает простое и
|
||||
удобное решение для всех, и его станут широко применять. Но это маловероятно, и даже если и так,
|
||||
то всегда можно модифицировать протокол чуток по другому. Делать моды для DPI несравненно дольше
|
||||
и дороже, чем клепать на коленке изменения протокола для wireguard.
|
||||
|
||||
|
||||
ЗАМЕЧЕНИЕ : альтернативой модификации конечного софта для VPN является использование "навесных"
|
||||
обфускаторов. см : https://github.com/bol-van/ipobfs
|
||||
|
||||
|
||||
Рассмотрю что нам надо пропатчить в 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
|
||||
get_random_bytes_wait(>rash, 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/compile
|
||||
|
||||
Сборка будет довольно долгой. Ведь придется подтащить ядро, собрать его, собрать зависимости.
|
||||
"-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
|
||||
При последующей очистке и пересборке он будет автоматом применяться.
|
||||
|
||||
|
||||
АЛЬТЕРНАТИВА : можно не возиться с quilt.
|
||||
сделайте
|
||||
# make package/wireguard/clean
|
||||
# make package/wireguard/prepare
|
||||
и напрямую модифицируйте или копируйте файлы в
|
||||
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
|
||||
затем
|
||||
# make package/wireguard/compile
|
||||
|
||||
Если нужно поменять версию wireguard, то идите в
|
||||
openwrt-sdk-18.06.2-ar71xx-generic_gcc-7.3.0_musl.Linux-x86_64/feeds/base/package/network/services/wireguard/Makefile
|
||||
поменяйте там версию в PKG_VERSION на последнюю из : https://git.zx2c4.com/WireGuard
|
||||
скачайте tar.xz с этой версией , вычислите его sha256sum, впишите в PKG_HASH
|
||||
|
||||
1 раз где-нибудь пропатчите файлы последней версии wireguard в текстовом редакторе, скопируйте в build_dir,
|
||||
сделайте версию для openwrt. эти же файлы скопируйте на ваш сервер с десктопным linux, сделайте там make / make install
|
||||
|
||||
Но имейте в виду, что build_dir - локация для временных файлов.
|
||||
make clean оттуда все снесет, включая ваши модификации. Модифицированные файлы лучше сохранить отдельно,
|
||||
чтобы потом было легко скопировать обратно.
|
||||
|
||||
Полученные ipk копируем на роутер в /tmp, устанавливаем через
|
||||
# cd /tmp
|
||||
# rm -r /tmp/opkg-lists
|
||||
# opkg install *.ipk
|
||||
Если требует зависимостей, то
|
||||
# opkg update
|
||||
# opkg install .... <зависимости>
|
||||
# rm -r /tmp/opkg-lists
|
||||
# opkg install *.ipk
|
||||
|
||||
В /tmp/opkg-lists opkg хранит кэш списка пакетов. Если попытаться установить файл ipk, и такой же пакет
|
||||
найдется в репозитории, opkg будет устанавливать из репозитория. А нам это не надо.
|
||||
|
||||
# rmmod wireguard
|
||||
# kmodloader
|
||||
# dmesg | tail
|
||||
должны увидеть что-то вроде :
|
||||
[8985.415490] wireguard: WireGuard 0.0.20190123 loaded. See www.wireguard.com for information.
|
||||
[8985.424178] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
значит модуль загрузился
|
||||
|
||||
Могут понадобиться ключи opkg --force-reinstall, --force-depends.
|
||||
--force-depends поможет при несоответствии hash версии ядра. То есть версия x.x.x та же самая, но hash конфигурации разный.
|
||||
При несоответствии x.x.x вы что-то делаете не так, работать это не будет.
|
||||
Например : 4.14.56-1-b1186491495127cc6ff81d29c00a91fc, 4.14.56-1-3f8a21a63974cfb7ee67e41f2d4b805d
|
||||
Это свидетельствует о несоответствии .config ядра при сборке прошивки и в SDK.
|
||||
Если несоответствие легкое, то может все прокатить, но при более серьезной разнице в .config модуль может не загрузиться
|
||||
или вызвать стабильные или хаотические падения ядра и перезагрузки (включая вариант беcконечной перезагрузки - bootloop).
|
||||
Так что перед --force-depends убедитесь, что знаете как лечится такая ситуация, и не стоит это делать при отсутствии физического
|
||||
доступа к девайсу.
|
||||
|
||||
Когда поднимите линк, и вдруг ничего не будет работать, то посмотрите в wireshark udp пакеты
|
||||
на порт endpoint. Они не должны начинаться с 0,1,2,3,4. В первых 4 байтах должен быть рандом,
|
||||
в следующих 4 байтах - значения из измененного enum message_type. Если пакет все еще начинается с 0..4,
|
||||
значит модуль wireguard оригинальный, что-то не собралось, не скопировалось, не перезапустилось.
|
||||
В противном случае должен подняться линк, пинги ходить. Значит вы победили, поздравляю.
|
||||
Регулятору будет намного сложнее поймать ваш VPN.
|
519
docs/wireguard/wireguard_iproute_openwrt.txt
Normal file
519
docs/wireguard/wireguard_iproute_openwrt.txt
Normal file
@@ -0,0 +1,519 @@
|
||||
Есть возможность поднять свой 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----------------------------
|
||||
. /opt/zapret/init.d/openwrt/functions
|
||||
|
||||
create_ipset no-update
|
||||
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt OUTPUT -t mangle -o $DEVICE -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
|
||||
ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800
|
||||
done
|
||||
|
||||
network_get_device DEVICE lan
|
||||
ipt PREROUTING -t mangle -i $DEVICE -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
|
||||
ipt PREROUTING -t mangle -i $DEVICE -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'
|
||||
------------------------------------------------
|
||||
|
||||
Существуют еще два неочевидных нюанса.
|
||||
|
||||
Первый из них касается пакетов с самого роутера (цепочка OUTPUT).
|
||||
Адрес источника выбирается по особому алгоритму, если программа явно его не задала, еще до этапа iptables.
|
||||
Он берется с интерфейса, куда бы пошел пакет при нормальном раскладе.
|
||||
Обратная маршрутизация с VPN станет невозможной, да и wireguard такие пакеты порежет, поскольку они не вписываются в AllowedIPs.
|
||||
Никаким мистическим образом автоматом source address не поменяется.
|
||||
В прошлом варианте настройки проблема решалось через маскарад. Сейчас же маскарада нет.
|
||||
Потому все же придется его делать в случае, когда пакет изначально направился бы через wan,
|
||||
а мы его завертываем на VPN. Помечаем такие пакеты марком 0x1000.
|
||||
Если вам не актуальны исходящие с самого роутера, то можно ничего не менять.
|
||||
|
||||
Другой нюанс связан с обработкой проброшенных на vps портов, соединения по которым приходят как входящие с интерфейса wgvps.
|
||||
Представьте себе, что вы пробросили порт 2222. Кто-то подключается с адреса 1.2.3.4. Вам приходит пакет SYN 1.2.3.4:51723=>192.168.2.2:2222.
|
||||
По правилам маршрутизации он пойдет в локалку. 192.168.2.2 его обработает, ответит пакетом ACK 192.168.2.2:2222=>1.2.3.4:51723.
|
||||
Этот пакет придет на роутер. И куда он дальше пойдет ? Если он не занесен в ipban, то согласно правилам машрутизации
|
||||
он пойдет по WAN интерфейсу, а не по исходному wgvps.
|
||||
Чтобы решить эту проблему, необходимо воспользоваться CONNMARK. Существуют 2 отдельных марка : fwmark и connmark.
|
||||
connmark относится к соединению, fwmark - к пакету. Трэкингом соединений занимается conntrack.
|
||||
Посмотреть его таблицу можно командой "conntrack -L". Там же найдете connmark : mark=xxxx.
|
||||
Как только видим приходящий с wgvps пакет с новым соединением, отмечаем его connmark как 0x800/0x800.
|
||||
При этом fwmark не меняется, иначе бы пакет тут же бы завернулся обратно на wgvps согласно ip rule.
|
||||
Если к нам приходит пакет с какого-то другого интерфейса, то восстанавливаем его connmark в fwmark по маске 0x800.
|
||||
И теперь он подпадает под правило ip rule, заворачиваясь на wgvps, что и требовалось.
|
||||
|
||||
--/etc/firewall.user----------------------------
|
||||
. /opt/zapret/init.d/openwrt/functions
|
||||
|
||||
create_ipset no-update
|
||||
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt OUTPUT -t mangle -o $DEVICE -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
|
||||
ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800
|
||||
ipt OUTPUT -t mangle -o $DEVICE -j MARK --set-mark 0x1000/0x1000
|
||||
done
|
||||
|
||||
network_get_device DEVICE lan
|
||||
ipt PREROUTING -t mangle -i $DEVICE -p tcp --dport 443 -m set --match-set zapret dst -j MARK --set-mark 0x800/0x800
|
||||
ipt PREROUTING -t mangle -i $DEVICE -m set --match-set ipban dst -j MARK --set-mark 0x800/0x800
|
||||
|
||||
# do masquerade for OUTPUT to ensure correct outgoing address
|
||||
ipt postrouting_tunvps_rule -t nat -m mark --mark 0x1000/0x1000 -j MASQUERADE
|
||||
|
||||
# incoming from wgvps
|
||||
network_get_device DEVICE wgvps
|
||||
ipt PREROUTING -t mangle ! -i $DEVICE -j CONNMARK --restore-mark --nfmask 0x800 --ctmask 0x800
|
||||
ipt PREROUTING -t mangle -i $DEVICE -m conntrack --ctstate NEW -j CONNMARK --set-xmark 0x800/0x800
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
# 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 -A OUTPUT -t mangle -p tcp --sport 23444 -j DSCP --set-dscp 1
|
||||
iptables -A OUTPUT -t mangle -p udp --sport 23444 -j DSCP --set-dscp 1
|
||||
------------------------------------------------
|
||||
|
||||
можно привязываться к pid процесса, но тогда нужно перенастраивать iptables при каждом перезапуске
|
||||
торент клиента, это требует рута, и все становится очень неудобно.
|
||||
|
||||
|
||||
--- Автоматизация проброса портов через miniupnd ---
|
||||
|
||||
Да, его тоже можно использовать на vps. Только как всегда есть нюансы.
|
||||
|
||||
miniupnpd поддерживает 3 протокола IGD : upnp,nat-pmp и pcp.
|
||||
upnp и pcp работают через мультикаст, который не пройдет через wgvps.
|
||||
nat-pmp работает через посылку специальных сообщений на udp:5351 на default gateway.
|
||||
Обычно их обслуживает miniupnpd на роутере. При создании lease miniupnpd добавляет
|
||||
правила для проброса портов в цепочку iptables MINIUPNPD, при потери lease - убирает.
|
||||
|
||||
udp:5351 можно перенаправить на vpn сервер через DNAT, чтобы их обрабатывал miniupnpd там.
|
||||
Но вы должны иметь однозначный критерий перенаправления.
|
||||
Если вы решили завернуть на vpn все, то проблем нет. Пробрасываем udp:5351 безусловно.
|
||||
Если у вас идет перенаправление только с торрент, то необходимо к условию перенаправления
|
||||
добавить условия, выделяющие torrent трафик из прочего. Или по dscp, или по sport.
|
||||
Чтобы запросы от остальных программ обрабатывались miniupnpd на роутере.
|
||||
Если какая-то программа создаст lease не там, где нужно, то входящий трафик до нее не дойдет.
|
||||
|
||||
На роутере стоит запретить протокол upnp, чтобы торрент клиент не удовлетворился запросом,
|
||||
обслуженным по upnp на роутере, и пытался использовать nat-pmp.
|
||||
|
||||
--/etc/config/upnp--------------------------
|
||||
config upnpd 'config'
|
||||
.....
|
||||
option enable_upnp '0'
|
||||
------------------------------------------------
|
||||
|
||||
/etc/init.d/miniupnpd restart
|
||||
|
||||
Делаем проброс порта на роутере.
|
||||
Для простоты изложения будем считать, что на vpn у нас завернут весь трафик.
|
||||
Если это не так, то следует добавить фильтр в "config redirect".
|
||||
Заодно выделяем диапазон портов для торрент клиентов.
|
||||
Порт в торент клиенте следует прописать какой-то из этого диапазона.
|
||||
|
||||
------------------------------------------------
|
||||
config redirect
|
||||
option enabled '1'
|
||||
option target 'DNAT'
|
||||
option src 'lan'
|
||||
option dest 'tunvps'
|
||||
option proto 'udp'
|
||||
option src_dport '5351'
|
||||
option dest_ip '192.168.254.1'
|
||||
option dest_port '5351'
|
||||
option name 'NAT-PMP'
|
||||
option reflection '0'
|
||||
config rule
|
||||
option enabled '1'
|
||||
option target 'ACCEPT'
|
||||
option src 'tunvps'
|
||||
option dest 'lan'
|
||||
option name 'tunvps-torrent'
|
||||
option dest_port '28000-28009'
|
||||
------------------------------------------------
|
||||
|
||||
fw3 reload
|
||||
|
||||
|
||||
На сервере :
|
||||
|
||||
apt install miniupnpd
|
||||
|
||||
--- /etc/miniupnpd/miniupnpd.conf --------
|
||||
enable_natpmp=yes
|
||||
enable_upnp=no
|
||||
lease_file=/var/log/upnp.leases
|
||||
system_uptime=yes
|
||||
clean_ruleset_threshold=10
|
||||
clean_ruleset_interval=600
|
||||
force_igd_desc_v1=no
|
||||
listening_ip=192.168.254.1/16
|
||||
ext_ifname=eth0
|
||||
------------------------------------------
|
||||
|
||||
systemctl restart miniupnpd
|
||||
|
||||
listening_ip прописан именно таким образом, чтобы обозначить диапазон разрешенных IP.
|
||||
С других IP он не будет обрабатывать запросы на редирект.
|
||||
В ext_ifname впишите название inet интерфейса на сервере.
|
||||
|
||||
Запускаем торрент клиент. Попутно смотрим в tcpdump весь путь udp:5351 до сервера и обратно.
|
||||
Смотрим syslog сервера на ругань от miniupnpd.
|
||||
Если все ок, то можем проверить редиректы : iptables -t nat -nL MINIUPNPD
|
||||
С какого-нибудь другого хоста (не vpn сервер, не ваше подключение) можно попробовать telnet-нуться на проброшенный порт.
|
||||
Должно установиться соединение. Или качайте торент и смотрите в пирах флаг "I" (incoming).
|
||||
Если "I" есть и по ним идет закачка, значит все в порядке.
|
||||
|
||||
ОСОБЕННОСТЬ НОВЫХ DEBIAN : по умолчанию используются iptables-nft. miniupnpd работает с iptables-legacy.
|
||||
ЛЕЧЕНИЕ : update-alternatives --set iptables /usr/sbin/iptables-legacy
|
||||
|
||||
|
||||
--- А если не заработало ? ---
|
||||
|
||||
Мануал пишется не как копипастная инструкция, а как помощь уже соображающему.
|
||||
В руки вам ifconfig, ip, iptables, tcpdump, ping. В умелых руках творят чудеса.
|
Reference in New Issue
Block a user