From b15ca040df6ecc6902c67654112cedd657631b74 Mon Sep 17 00:00:00 2001 From: conc3rned Date: Tue, 17 Sep 2024 16:16:35 +0300 Subject: [PATCH] .txt -> .md, existing Markdown fixes --- binaries/win64/readme.md | 11 + binaries/win64/readme.txt | 9 - docs/bsd.eng.md | 405 ++-- docs/{bsd.txt => bsd.md} | 528 +++-- docs/{bsdfw.txt => bsdfw.md} | 43 +- docs/changes.md | 315 +++ docs/changes.txt | 310 --- docs/compile/build_howto_openwrt.md | 70 + docs/compile/build_howto_openwrt.txt | 42 - docs/{iptables.txt => iptables.md} | 36 +- docs/manual_setup.md | 420 ++++ docs/manual_setup.txt | 282 --- docs/{nftables.txt => nftables.md} | 26 +- docs/nftables_notes.md | 142 ++ docs/nftables_notes.txt | 120 -- docs/quick_start.md | 134 ++ docs/quick_start.txt | 137 -- docs/quick_start_windows.md | 117 ++ docs/quick_start_windows.txt | 117 -- docs/readme.eng.md | 197 +- docs/readme.md | 1924 ++++++++++++++++++ docs/readme.txt | 1848 ----------------- docs/redsocks.md | 228 +++ docs/redsocks.txt | 196 -- docs/windows.eng.md | 100 +- docs/windows.md | 229 +++ docs/windows.txt | 222 -- docs/wireguard/wireguard-mod.md | 296 +++ docs/wireguard/wireguard-mod.txt | 250 --- docs/wireguard/wireguard_iproute_openwrt.md | 730 +++++++ docs/wireguard/wireguard_iproute_openwrt.txt | 645 ------ 31 files changed, 5348 insertions(+), 4781 deletions(-) create mode 100644 binaries/win64/readme.md delete mode 100644 binaries/win64/readme.txt rename docs/{bsd.txt => bsd.md} (50%) rename docs/{bsdfw.txt => bsdfw.md} (89%) create mode 100644 docs/changes.md delete mode 100644 docs/changes.txt create mode 100644 docs/compile/build_howto_openwrt.md delete mode 100644 docs/compile/build_howto_openwrt.txt rename docs/{iptables.txt => iptables.md} (89%) create mode 100644 docs/manual_setup.md delete mode 100644 docs/manual_setup.txt rename docs/{nftables.txt => nftables.md} (72%) create mode 100644 docs/nftables_notes.md delete mode 100644 docs/nftables_notes.txt create mode 100644 docs/quick_start.md delete mode 100644 docs/quick_start.txt create mode 100644 docs/quick_start_windows.md delete mode 100644 docs/quick_start_windows.txt create mode 100644 docs/readme.md delete mode 100644 docs/readme.txt create mode 100644 docs/redsocks.md delete mode 100644 docs/redsocks.txt create mode 100644 docs/windows.md delete mode 100644 docs/windows.txt create mode 100644 docs/wireguard/wireguard-mod.md delete mode 100644 docs/wireguard/wireguard-mod.txt create mode 100644 docs/wireguard/wireguard_iproute_openwrt.md delete mode 100644 docs/wireguard/wireguard_iproute_openwrt.txt diff --git a/binaries/win64/readme.md b/binaries/win64/readme.md new file mode 100644 index 0000000..994b180 --- /dev/null +++ b/binaries/win64/readme.md @@ -0,0 +1,11 @@ +Standalone version in `zapret-winws` folder !! +From this folder `winws` can be started only from `cygwin` shell. + +`cygwin` refuses to start winws if a copy of `cygwin1.dll` is present ! + +How to get Windows 7 and `winws` compatible version of `cygwin`: + +```powershell +curl -O https://www.cygwin.com/setup-x86_64.exe +setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 +``` diff --git a/binaries/win64/readme.txt b/binaries/win64/readme.txt deleted file mode 100644 index 3923bc6..0000000 --- a/binaries/win64/readme.txt +++ /dev/null @@ -1,9 +0,0 @@ -Standalone version in zapret-winws folder !! -From this folder winws can be started only from cygwin shell. - -Cygwin refuses to start winws if a copy of cygwin1.dll is present ! - -How to get win7 and winws compatible version of cygwin : - -curl -O https://www.cygwin.com/setup-x86_64.exe -setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 diff --git a/docs/bsd.eng.md b/docs/bsd.eng.md index 3c3bffb..28a2233 100644 --- a/docs/bsd.eng.md +++ b/docs/bsd.eng.md @@ -1,6 +1,3 @@ -## Table of contents - -- [Table of contents](#table-of-contents) - [Supported versions](#supported-versions) - [BSD features](#bsd-features) - [FreeBSD](#freebsd) @@ -8,24 +5,23 @@ - [PF in FreeBSD](#pf-in-freebsd) - [`pfsense`](#pfsense) - [OpenBSD](#openbsd) -- [MacOS](#macos) - - [MacOS easy install](#macos-easy-install) +- [macOS](#macos) + - [Easy install](#easy-install) ## Supported versions -FreeBSD 11.x+ , OpenBSD 6.x+, partially MacOS Sierra+ +FreeBSD 11.x+, OpenBSD 6.x+, partially macOS Sierra+ Older versions may work or not. ## BSD features -BSD does not have NFQUEUE. Similar mechanism - divert sockets. In BSD compiling -the source from nfq directory result in `dvtws` binary instead of `nfqws`. -`dvtws` shares most of the code with `nfqws` and offers almost identical -parameters. +BSD does not have NFQUEUE. Similar mechanism - divert sockets. +In BSD compiling the source from nfq directory result in `dvtws` binary instead of `nfqws`. +`dvtws` shares most of the code with `nfqws` and offers almost identical parameters. -FreeBSD has 3 firewalls: IPFilter, ipfw and Packet Filter (PF). OpenBSD has -only PF. +FreeBSD has 3 firewalls: IPFilter, `ipfw` and Packet Filter (PF). +OpenBSD has only PF. To compile sources: @@ -34,42 +30,39 @@ To compile sources: - MacOS: `make mac` Compile all programs: -``` + +```sh make -C /opt/zapret ``` -Divert sockets are internal type sockets in the BSD kernel. They have no -relation to network addresses or network packet exchange. They are identified -by a port number `1..65535`. Its like queue number in NFQUEUE. Traffic can be -diverted to a divert socket using firewall rule. If nobody listens on the -specified divert port packets are dropped. Its similar to NFQUEUE without -`--queue-bypass`. +Divert sockets are internal type sockets in the BSD kernel. +They have no relation to network addresses or network packet exchange. +They are identified by a port number `1..65535`. It's like queue number in NFQUEUE. +Traffic can be diverted to a divert socket using firewall rule. +If nobody listens on the specified divert port packets are dropped. +It's similar to NFQUEUE without `--queue-bypass`. -`ipset/*.sh` scripts work with ipfw lookup tables if ipfw is present. +`ipset/*.sh` scripts work with `ipfw` lookup tables if `ipfw` is present. -ipfw table is analog to linux `ipset`. Unlike ipsets ipfw tables share v4 an v6 -addresses and subnets. +`ipfw` table is analog to Linux `ipset`. Unlike IP sets `ipfw` tables share v4 an v6 addresses and subnets. -- If ipfw is absent scripts check LISTS_RELOAD config variable. -- If its present then scripts execute a command from LISTS_RELOAD. -- If LISTS_RELOAD=- scripts do not load tables even if ipfw exists. +- If `ipfw` is absent scripts check `LISTS_RELOAD` config variable. +- If it's present then scripts execute a command from `LISTS_RELOAD`. +- If `LISTS_RELOAD=-`, scripts do not load tables even if `ipfw` exists. -PF can load ip tables from a file. To use this feature with `ipset/*.sh` scripts disable gzip file creation -using `GZIP_LISTS=0` directive in the `/opt/zapret/config` file. +PF can load ip tables from a file. To use this feature with `ipset/*.sh` scripts disable gzip file creation using `GZIP_LISTS=0` directive in the `/opt/zapret/config` file. -BSD kernel doesn't implement splice syscall. tpws uses regular recv/send -operations with data copying to user space. Its slower but not critical. +BSD kernel doesn't implement splice syscall. `tpws` uses regular recv/send operations with data copying to user space. +It's slower but not critical. -`tpws` uses nonblocking sockets with linux specific epoll feature. In BSD systems -epoll is emulated by epoll-shim library on top of kqueue. +`tpws` uses nonblocking sockets with Linux specific epoll feature. +In BSD systems epoll is emulated by epoll-shim library on top of kqueue. -`dvtws` uses some programming HACKs, assumptions and knowledge of discovered -bugs and limitations. BSD systems have many limitations, version specific -features and bugs in low level networking, especially for ipv6. Many years have -passed but BSD code still has 15-20 year artificial limiters in the code. `dvtws` -uses additinal divert socket(s) for layer 3 packet injection if raw sockets do -not allow it. It works for the moment but who knows. Such a usage is not very -documented. +`dvtws` uses some programming HACKs, assumptions and knowledge of discovered bugs and limitations. +BSD systems have many limitations, version specific features and bugs in low level networking, especially for IPv6. +Many years have passed but BSD code still has 15-20 year artificial limiters in the code. +`dvtws` uses additional divert socket(s) for layer 3 packet injection if raw sockets do not allow it. +It works for the moment but who knows. Such a usage is not very documented. `mdig` and `ip2net` are fully compatible with BSD. @@ -80,25 +73,29 @@ Divert sockets require special kernel module `ipdivert`. Write the following to config files: `/boot/loader.conf` (create if absent): -``` + +```conf ipdivert_load="YES" net.inet.ip.fw.default_to_accept=1 ``` `/etc/rc.conf`: -``` + +```conf firewall_enable="YES" firewall_script="/etc/rc.firewall.my" ``` `/etc/rc.firewall.my`: -``` + +```sh ipfw -q -f flush ``` -Later you will add ipfw commands to `/etc/rc.firewall.my` to be reapplied after reboot. -You can also run zapret daemons from there. Start them with `--daemon` options, for example -``` +Later you will add `ipfw` commands to `/etc/rc.firewall.my` to be reapplied after reboot. +You can also run zapret daemons from there. Start them with `--daemon` options, for example: + +```sh pkill ^dvtws$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2 ``` @@ -110,7 +107,8 @@ Assume `LAN="em1"`, `WAN="em0"`. `tpws` transparent mode quick start. For all traffic: -``` + +```sh ipfw delete 100 ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon @@ -119,8 +117,9 @@ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 ``` -Process only table zapret with the exception of table nozapret: -``` +Process only table `zapret` with the exception of table `nozapret`: + +```sh ipfw delete 100 ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon @@ -131,28 +130,30 @@ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 ``` -Tables zapret, nozapret, ipban are created by `ipset/*.sh` scripts the same way as in Linux. -Its a good idea to update tables periodically: -``` - crontab -e +Tables `zapret`, `nozapret`, `ipban` are created by `ipset/*.sh` scripts the same way as in Linux. +It's a good idea to update tables periodically: + +```sh +crontab -e ``` Write the line: -``` + +```sh 0 12 */2 * * /opt/zapret/ipset/get_config.sh ``` -When using `ipfw`, `tpws` does not require special permissions for transparent -mode. However without root its not possible to bind to ports less than 1024 and -change UID/GID. Without changing UID tpws will run into recursive loop, and -that's why its necessary to write ipfw rules with the right UID. Redirecting to -ports greater than or equal to 1024 is dangerous. If tpws is not running any -unprivileged process can listen to that port and intercept traffic. +When using `ipfw`, `tpws` does not require special permissions for transparent mode. +However without root it's not possible to bind to ports less than 1024 and change UID/GID. +Without changing UID tpws will run into recursive loop, and that's why it's necessary to write ipfw rules with the right UID. +Redirecting to ports greater than or equal to 1024 is dangerous. +If tpws is not running any unprivileged process can listen to that port and intercept traffic. ### `dvtws` quick start For all traffic: -``` + +```sh ipfw delete 100 ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg xmit em0 # required for autottl mode only @@ -160,8 +161,9 @@ ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diver /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 ``` -Process only table zapret with the exception of table nozapret: -``` +Process only table `zapret` with the exception of table `nozapret`: + +```sh ipfw delete 100 ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0 @@ -170,21 +172,19 @@ ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 ``` -Reinjection loop avoidance. FreeBSD artificially ignores sockarg for ipv6 in -the kernel. This limitation is coming from the ipv6 early age. Code is still in -"testing" state. 10-20 years. Everybody forgot about it. `dvtws` sends ipv6 -forged frames using another divert socket (HACK). they can be filtered out -using 'diverted'. ipv4 frames are filtered using 'sockarg'. +Reinjection loop avoidance. FreeBSD artificially ignores sockarg for IPv6 in the kernel. +This limitation is coming from the IPv6 early age. Code is still in "testing" state. 10-20 years. +Everybody forgot about it. `dvtws` sends IPv6 forged frames using another divert socket (HACK). +They can be filtered out using 'diverted'. IPv4 frames are filtered using `sockarg`. ### PF in FreeBSD The setup is similar to OpenBSD, but there are important nuances. 1. PF support is disabled by default in FreeBSD. Use parameter `--enable-pf`. -2. It's not possible to redirect to `::1`. Need to redirect to the link-local - address of the incoming interface. Look for fe80:... address in ifconfig and - use it for redirection target. -3. pf.conf syntax is a bit different from OpenBSD. -4. How to set maximum table size : sysctl net.pf.request_maxcount=2000000 +2. It's not possible to redirect to `::1`. Need to redirect to the link-local address of the incoming interface. + Look for `fe80:...` address in `ifconfig` and use it for redirection target. +3. `pf.conf` syntax is a bit different from OpenBSD. +4. How to set maximum table size: `sysctl net.pf.request_maxcount=2000000` 5. `divert-to` is broken. Loop avoidance scheme does not work. This makes `dvtws` unusable with pf. Someone posted kernel patch but 14-RELEASE is still broken. @@ -196,43 +196,37 @@ rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 ``` Then: -``` + +```sh /opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force ``` -Its not clear how to do rdr-to outgoing traffic. I could not make route-to -scheme work. - +It's not clear how to do rdr-to outgoing traffic. I could not make route-to scheme work. ### `pfsense` -`pfsense` is based on FreeBSD. Binaries from `binaries/freebsd-x64` are -compiled in FreeBSD 11 and should work. Use `install_bin.sh`. pfsense uses pf -firewall which does not support divert. Fortunately ipfw and ipdivert modules -are present and can be kldload-ed. In older versions it's also necessary to -change firewall order using sysctl commands. In newer versions those sysctl -parameters are absent but the system behaves as required without them. -Sometimes pf may limit `dvtws` abilities. It scrubs ip fragments disabling `dvtws` -ipfrag2 desync mode. +`pfsense` is based on FreeBSD. Binaries from `binaries/freebsd-x64` are compiled in FreeBSD 11 and should work. +Use `install_bin.sh`. pfsense uses pf firewall which does not support divert. +Fortunately ipfw and ipdivert modules are present and can be kldload-ed. +In older versions it's also necessary to change firewall order using `sysctl` commands. +In newer versions those `sysctl` parameters are absent but the system behaves as required without them. +Sometimes pf may limit `dvtws` abilities. It scrubs ip fragments disabling `dvtws` `ipfrag2` desync mode. -There's autostart script example in `init.d/pfsense`. It should be placed to -`/usr/local/etc/rc.d` and edited. Write your ipfw rules and daemon start -commands. Because git is absent the most convinient way to copy files is ssh. -curl is present by default. +There's autostart script example in `init.d/pfsense`. It should be placed to `/usr/local/etc/rc.d` and edited. +Write your `ipfw` rules and daemon start commands. Because `git` is absent the most convenient way to copy files is `ssh`. +`curl` is present by default. -Copy zip with zapret files to `/opt` and unpack there as it's done in other -systems. In this case run `dvtws` as `/opt/zapret/nfq/dvtws`. Or just copy -`dvtws` to `/usr/local/sbin`. As you wish. `ipset` scripts are working, cron is -present. It's possible to renew lists. +Copy zip with zapret files to `/opt` and unpack there as it's done in other systems. +In this case run `dvtws` as `/opt/zapret/nfq/dvtws`. Or just copy `dvtws` to `/usr/local/sbin`. +As you wish. `ipset` scripts are working, `cron` is present. It's possible to renew lists. -If you dont like poverty of default repos its possible to enable FreeBSD repo. +If you don't like poverty of default repos it's possible to enable FreeBSD repo. Change `no` to `yes` in `/usr/local/etc/pkg/repos/FreeBSD.conf` and `/usr/local/etc/pkg/repos/pfSense.conf`. -Then it becomes possible to install all the required software including git to download -zapret from github directly. +Then it becomes possible to install all the required software including `git` to download `zapret` from GitHub directly. +`/usr/local/etc/rc.d/zapret.sh` (`chmod 755`): -`/usr/local/etc/rc.d/zapret.sh` (chmod 755) -``` +```sh #!/bin/sh kldload ipfw @@ -253,10 +247,9 @@ dvtws --daemon --port 989 --dpi-desync=split2 pfctl -d ; pfctl -e ``` -I could not make tpws work from ipfw. Looks like there's some conflict between -two firewalls. Only PF redirection works. PF does not allow to freely add and -delete rules. Only anchors can be reloaded. To make an anchor work it must be -referred from the main ruleset. But its managed by pfsense scripts. +I could not make `tpws` work from `ipfw`. Looks like there's some conflict between two firewalls. +Only PF redirection works. PF does not allow to freely add and delete rules. Only anchors can be reloaded. +To make an anchor work it must be referred from the main ruleset. But it's managed by pfsense scripts. One possible solution would be to modify `/etc/inc/filter.inc` as follows: ``` @@ -275,11 +268,12 @@ Write the anchor code to `/etc/zapret.anchor`: rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988 ``` -Replace `fe80::20c:29ff:5ae3:4821` with your link local address of the LAN -interface or remove the line if ipv6 is not needed. + +Replace `fe80::20c:29ff:5ae3:4821` with your link local address of the LAN interface or remove the line if IPv6 is not needed. Autostart `/usr/local/etc/rc.d/zapret.sh`: -``` + +```sh pfctl -a zapret -f /etc/zapret.anchor pkill ^tpws$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2 @@ -308,11 +302,9 @@ This way avoids modification of pfsense code. ## OpenBSD -In OpenBSD default `tpws` bind is ipv6 only. To bind to ipv4 specify -`--bind-addr=0.0.0.0`. +In OpenBSD default `tpws` bind is IPv6 only. To bind to IPv4 specify `--bind-addr=0.0.0.0`. -Use `--bind-addr=0.0.0.0 --bind-addr=::` to achieve the same default bind as in -others OSes. +Use `--bind-addr=0.0.0.0 --bind-addr=::` to achieve the same default bind as in others OSes. `tpws` for forwarded traffic only : @@ -323,14 +315,14 @@ pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 ``` Then: -``` + +```sh pfctl -f /etc/pf.conf tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 ``` -Its not clear how to do rdr-to outgoing traffic. I could not make route-to -scheme work. rdr-to support is done using /dev/pf, that's why transparent mode -requires root. +It's not clear how to do rdr-to outgoing traffic. I could not make route-to scheme work. +rdr-to support is done using `/dev/pf`, that's why transparent mode requires root. `dvtws` for all traffic: @@ -342,7 +334,8 @@ pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 ``` Then: -``` + +```sh pfctl -f /etc/pf.conf ./dvtws --port=989 --dpi-desync=split2 ``` @@ -375,47 +368,49 @@ pass out quick on em0 inet6 proto tcp to port {80,443} divert-p ``` Then: -``` + +```sh pfctl -f /etc/pf.conf ./dvtws --port=989 --dpi-desync=split2 ``` -divert-packet automatically adds the reverse rule. By default also incoming -traffic will be passwed to `dvtws`. This is highly undesired because it is waste -of cpu resources and speed limiter. The trick with "no state" and "in" rules -allows to bypass auto reverse rule. +divert-packet automatically adds the reverse rule. By default also incoming traffic will be passed to `dvtws`. +This is highly undesired because it is waste of CPU resources and speed limiter. +The trick with "no state" and "in" rules allows to bypass auto reverse rule. -`dvtws` in OpenBSD sends all fakes through a divert socket because raw sockets -have critical artificial limitations. Looks like pf automatically prevent -reinsertion of diverted frames. Loop problem does not exist. +`dvtws` in OpenBSD sends all fakes through a divert socket because raw sockets have critical artificial limitations. +Looks like pf automatically prevent reinsertion of diverted frames. Loop problem does not exist. -OpenBSD forcibly recomputes tcp checksum after divert. Thats why most likely -dpi-desync-fooling=badsum will not work. `dvtws` will warn if you specify this -parameter. +OpenBSD forcibly recomputes TCP checksum after divert. Thats why most likely `dpi-desync-fooling=badsum` will not work. +`dvtws` will warn if you specify this parameter. -`ipset` scripts do not reload PF by default. To enable reload specify command in -`/opt/zapret/config`: -``` +`ipset` scripts do not reload PF by default. To enable reload specify command in `/opt/zapret/config`: + +```sh LISTS_RELOAD="pfctl -f /etc/pf.conf" ``` Newer `pfctl` versions can reload tables only: -``` + +```sh pfctl -Tl -f /etc/pf.conf ``` -But OpenBSD 6.8 `pfctl` is old enough and does not support that. Newer FreeBSD do. +But OpenBSD 6.8 `pfctl` is old enough and does not support that. +Newer FreeBSD do. Don't forget to disable gzip compression: -``` + +```sh GZIP_LISTS=0 ``` -If some list files do not exist and have references in pf.conf it leads to -error. You need to exclude those tables from pf.conf and referencing them -rules. After configuration is done you can put `ipset` script: -``` - crontab -e +If some list files do not exist and have references in `pf.conf` it leads to error. +You need to exclude those tables from `pf.conf` and referencing them rules. +After configuration is done you can put `ipset` script: + +```sh +crontab -e ``` Then write the line: @@ -425,65 +420,45 @@ Then write the line: ## MacOS -Initially, the kernel of this OS was based on BSD. That's why it is still BSD -but a lot was modified by Apple. As usual a mass commercial project priorities -differ from their free counterparts. Apple guys do what they want. +Initially, the kernel of this OS was based on BSD. That's why it is still BSD but a lot was modified by Apple. +As usual a mass commercial project priorities differ from their free counterparts. Apple guys do what they want. -MacOS used to have ipfw but it was removed later and replaced by PF. It looks -like divert sockets are internally replaced with raw. Its possible to request a -divert socket but it behaves exactly as raw socket with all its BSD inherited + -apple specific bugs and feature. The fact is that divert-packet in -`/etc/pf.conf` does not work. pfctl binary does not contain the word `divert`. +macOS used to have `ipfw` but it was removed later and replaced by PF. +It looks like divert sockets are internally replaced with raw. +It's possible to request a divert socket but it behaves exactly as raw socket with all its BSD inherited + Apple specific bugs and feature. +The fact is that divert-packet in `/etc/pf.conf` does not work. `pfctl` binary does not contain the word `divert`. `dvtws` does compile but is useless. -After some efforts `tpws` works. Apple has removed some important stuff from -their newer SDKs (DIOCNATLOOK) making them undocumented and unsupported. +After some efforts `tpws` works. +Apple has removed some important stuff from their newer SDKs (DIOCNATLOOK) making them undocumented and unsupported. -With important definitions copied from an older SDK it was possible to make -transparent mode working again. But this is not guaranteed to work in the -future versions. +With important definitions copied from an older SDK it was possible to make transparent mode working again. +But this is not guaranteed to work in the future versions. -Another MacOS unique feature is root requirement while polling `/dev/pf`. +Another macOS unique feature is root requirement while polling `/dev/pf`. +By default `tpws` drops root. It's necessary to specify `--user=root` to stay with root. +In other aspects PF behaves very similar to FreeBSD and shares the same `pf.conf` syntax. -By default tpws drops root. Its necessary to specify `--user=root` to stay with -root. - -In other aspects PF behaves very similar to FreeBSD and shares the same pf.conf -syntax. - -In MacOS redirection works both for passthrough and outgoing traffic. Outgoing -redirection requires route-to rule. Because tpws is forced to run as root to -avoid loop its necessary to exempt root from the redirection. That's why DPI -bypass will not work for local requests from root. - -If you do ipv6 routing you have to get rid of "secured" ipv6 address -assignment. - -"secured" addresses are designed to be permanent and not related to the MAC -address. +In macOS redirection works both for passthrough and outgoing traffic. Outgoing redirection requires route-to rule. +Because `tpws` is forced to run as root to avoid loop it's necessary to exempt root from the redirection. +That's why DPI bypass will not work for local requests from root. +If you do IPv6 routing you have to get rid of "secured" IPv6 address assignment. +"secured" addresses are designed to be permanent and not related to the MAC address. And they really are. Except for link-locals. - -If you just reboot the system link-locals will not change. But next day they -will change. +If you just reboot the system link-locals will not change. But next day they will change. Not necessary to wait so long. Just change the system time to tomorrow and reboot. -Link-locals will change (at least they change in vmware guest). Looks like its a kernel bug. -Link locals should not change. Its useless and can be harmful. Cant use LL as a gateway. +Link-locals will change (at least they change in VMware guest). Looks like it's a kernel bug. +Link locals should not change. It's useless and can be harmful. Can't use LL as a gateway. The easiest solution is to disable "secured" addresses. - -Outgoing connections prefer randomly generated temporary addressesas like in other systems. - -Put the string `net.inet6.send.opmode=0` to `/etc/sysctl.conf`. If not present -- create it. - +Outgoing connections prefer randomly generated temporary addresses like in other systems. +Put the string `net.inet6.send.opmode=0` to `/etc/sysctl.conf`. If not present - create it. Then reboot the system. -If you dont like this solution you can assign an additional static ipv6 address -from `fc00::/7` range with `/128` prefix to your LAN interface and use it as -the gateway address. +If you don't like this solution you can assign an additional static IPv6 address from `fc00::/7` range with `/128` prefix to your LAN interface and use it as the gateway address. `tpws` transparent mode only for outgoing connections. @@ -496,12 +471,13 @@ pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} us ``` Then: -``` + +```sh pfctl -ef /etc/pf.conf /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force ``` -`tpws` transparent mode for both passthrough and outgoing connections. en1 - LAN. +`tpws` transparent mode for both passthrough and outgoing connections (`en1` - LAN): ``` ifconfig en1 | grep fe80 @@ -519,7 +495,8 @@ pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} us ``` Then: -``` + +```sh pfctl -ef /etc/pf.conf /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force ``` @@ -528,68 +505,69 @@ Build from source : `make -C /opt/zapret mac` `ipset/*.sh` scripts work. +### Easy install -### MacOS easy install +`install_easy.sh` supports macOS. -`install_easy.sh` supports MacOS +Shipped precompiled binaries are built for 64-bit macOS with `-mmacosx-version-min=10.8` option. +They should run on all supported macOS versions. If no - it's easy to build your own. +Running `make` automatically installs developer tools. -Shipped precompiled binaries are built for 64-bit MacOS with -`-mmacosx-version-min=10.8` option. They should run on all supported MacOS -versions. If no - its easy to build your own. Running `make` automatically -installs developer tools. +**WARNING: Internet sharing is not supported!** -**WARNING**: -**Internet sharing is not supported!** - -Routing is supported but only manually configured through PF. If you enable -internet sharing tpws stops functioning. When you disable internet sharing you -may lose web site access. +Routing is supported but only manually configured through PF. +If you enable internet sharing tpws stops functioning. +When you disable internet sharing you may lose web site access. To fix: -``` + +```sh pfctl -f /etc/pf.conf ``` -If you need internet sharing use `tpws` socks mode. +If you need internet sharing, use `tpws` SOCKS mode. `launchd` is used for autostart (`/Library/LaunchDaemons/zapret.plist`) Control script: `/opt/zapret/init.d/macos/zapret` -The following commands fork with both tpws and firewall (if `INIT_APPLY_FW=1` in config) -``` +The following commands fork with both tpws and firewall (if `INIT_APPLY_FW=1` in `config`) + +```sh /opt/zapret/init.d/macos/zapret start /opt/zapret/init.d/macos/zapret stop /opt/zapret/init.d/macos/zapret restart ``` Work with `tpws` only: -``` + +```sh /opt/zapret/init.d/macos/zapret start-daemons /opt/zapret/init.d/macos/zapret stop-daemons /opt/zapret/init.d/macos/zapret restart-daemons ``` Work with PF only: -``` + +```sh /opt/zapret/init.d/macos/zapret start-fw /opt/zapret/init.d/macos/zapret stop-fw /opt/zapret/init.d/macos/zapret restart-fw ``` Reloading PF tables: -``` + +```sh /opt/zapret/init.d/macos/zapret reload-fw-tables ``` -Installer configures `LISTS_RELOAD` in the config so `ipset *.sh` scripts -automatically reload PF tables. Installer creates cron job for `ipset -/get_config.sh`, as in OpenWRT. +Installer configures `LISTS_RELOAD` in the config so `ipset *.sh` scripts automatically reload PF tables. +Installer creates cron job for `ipset /get_config.sh`, as in OpenWrt. -start-fw script automatically patches `/etc/pf.conf` inserting there `zapret` -anchors. Auto patching requires pf.conf with apple anchors preserved. If your -`pf.conf` is highly customized and patching fails you will see the warning. Do -not ignore it. +`start-fw` script automatically patches `/etc/pf.conf` inserting there `zapret` anchors. +Auto patching requires `pf.conf` with Apple anchors preserved. +If your `pf.conf` is highly customized and patching fails you will see the warning. +Do not ignore it. In that case you need to manually insert "zapret" anchors to your `pf.conf` (keeping the right rule type ordering): @@ -598,14 +576,15 @@ rdr-anchor "zapret" anchor "zapret" unistall_easy.sh unpatches pf.conf ``` -start-fw creates 3 anchor files in `/etc/pf.anchors` : -zapret,zapret-v4,zapret-v6. + +`start-fw` creates 3 anchor files in `/etc/pf.anchors`: +`zapret`, `zapret-v4`, `zapret-v6`. - Last 2 are referenced by anchor `zapret`. -- Tables `nozapret`,`nozapret6` belong to anchor `zapret`. -- Tables `zapret`,`zapret-user` belong to anchor `zapret-v4`. -- Tables `zapret6`,`apret6-user` belong to anchor `zapret-v6`. +- Tables `nozapret`, `nozapret6` belong to anchor `zapret`. +- Tables `zapret`, `zapret-user` belong to anchor `zapret-v4`. +- Tables `zapret6`, `zapret6-user` belong to anchor `zapret-v6`. -If an ip version is disabled then corresponding anchor is empty and is not +If an IP version is disabled then corresponding anchor is empty and is not referenced from the anchor `zapret`. Tables are only created for existing list files in the `ipset` directory. diff --git a/docs/bsd.txt b/docs/bsd.md similarity index 50% rename from docs/bsd.txt rename to docs/bsd.md index 829dc5c..7ea23b8 100644 --- a/docs/bsd.txt +++ b/docs/bsd.md @@ -1,93 +1,111 @@ -Поддерживаемые версии ---------------------- +- [Поддерживаемые версии](#поддерживаемые-версии) +- [Особенности BSD систем](#особенности-bsd-систем) +- [FreeBSD](#freebsd) + - [Краткая инструкция по запуску `tpws` в прозрачном режиме](#краткая-инструкция-по-запуску-tpws-в-прозрачном-режиме) +- [pfsense](#pfsense) +- [OpenBSD](#openbsd) +- [macOS](#macos) + - [Простая установка](#простая-установка) + - [Вариант custom](#вариант-custom) -FreeBSD 11.x+ , OpenBSD 6.x+, частично MacOS Sierra+ +# Поддерживаемые версии + +FreeBSD 11.x+, OpenBSD 6.x+, частично macOS Sierra+ На более старых может собираться, может не собираться, может работать или не работать. -На FreeBSD 10 собирается и работает dvtws. С tpws есть проблемы из-за слишком старой версии компилятора clang. +На FreeBSD 10 собирается и работает `dvtws`. С `tpws` есть проблемы из-за слишком старой версии компилятора `clang`. Вероятно, будет работать, если обновить компилятор. -Возможна прикрутка к последним версиям pfsense без веб интерфейса в ручном режиме через консоль. +Возможна прикрутка к последним версиям `pfsense` без веб-интерфейса в ручном режиме через консоль. - -Особенности BSD систем ----------------------- +# Особенности BSD систем В BSD нет nfqueue. Похожий механизм - divert sockets. -Из каталога "nfq" под BSD собирается dvtws вместо nfqws. -Он разделяет с nfqws большую часть кода и почти совпадает по параметрам командной строки. +Из каталога `nfq/` под BSD собирается `dvtws` вместо `nfqws`. +Он разделяет с `nfqws` большую часть кода и почти совпадает по параметрам командной строки. -FreeBSD содержит 3 фаервола : IPFilter, ipfw и Packet Filter (PF). OpenBSD содержит только PF. +FreeBSD содержит 3 фаервола: IPFilter, `ipfw` и Packet Filter (PF). OpenBSD содержит только PF. -Под FreeBSD tpws и dvtws собираются через "make", под OpenBSD - "make bsd", под MacOS - "make mac". -FreeBSD make распознает BSDmakefile , OpenBSD и MacOS - нет. Поэтому там используется отдельный target в Makefile. -Сборка всех исходников : make -C /opt/zapret +Под FreeBSD `tpws` и `dvtws` собираются через `make`, под OpenBSD - `make bsd`, под macOS - `make mac`. +FreeBSD `make` распознает `BSDmakefile`, OpenBSD и macOS - нет. Поэтому там используется отдельный `target` в `Makefile`. +Сборка всех исходников: `make -C /opt/zapret` divert сокет - внутренний тип сокета ядра BSD. Он не привязывается ни к какому сетевому адресу, не участвует -в обмене данными через сеть и идентифицируется по номеру порта 1..65535. Аналогия с номером очереди NFQUEUE. -На divert сокеты заворачивается трафик посредством правил ipfw или PF. +в обмене данными через сеть и идентифицируется по номеру порта `1...65535`. Аналогия с номером очереди NFQUEUE. +На divert сокеты заворачивается трафик посредством правил `ipfw` или PF. Если в фаерволе есть правило divert, но на divert порту никто не слушает, то пакеты дропаются. -Это поведение аналогично правилам NFQUEUE без параметра --queue-bypass. -На FreeBSD divert сокеты могут быть только ipv4, хотя на них принимаются и ipv4, и ipv6 фреймы. -На OpenBSD divert сокеты создаются отдельно для ipv4 и ipv6 и работают только с одной версией ip каждый. -На MacOS похоже, что divert сокеты из ядра вырезаны. См подробнее раздел про MacOS. -Отсылка в divert сокет работает аналогично отсылке через raw socket на linux. Передается полностью IP фрейм, начиная -с ip загловка . Эти особенности учитываются в dvtws. +Это поведение аналогично правилам NFQUEUE без параметра `--queue-bypass`. +На FreeBSD divert сокеты могут быть только IPv4, хотя на них принимаются и IPv4, и IPv6 фреймы. +На OpenBSD divert сокеты создаются отдельно для IPv4 и IPv6 и работают только с одной версией IP каждый. +На macOS похоже, что divert сокеты из ядра вырезаны. См. подробнее раздел про [macOS](#macos). +Отсылка в divert сокет работает аналогично отсылке через raw socket на Linux. Передается полностью IP фрейм, начиная с IP заголовка. Эти особенности учитываются в `dvtws`. -Скрипты ipset/*.sh при наличии ipfw работают с ipfw lookup tables. -Это прямой аналог ipset. lookup tables не разделены на v4 и v6. Они могут содержать v4 и v6 адреса и подсети одновременно. -Если ipfw отсутствует, то действие зависит от переменной LISTS_RELOAD в config. -Если она задана, то выполняется команда из LISTS_RELOAD. В противном случае не делается ничего. -Если LISTS_RELOAD=-, то заполнение таблиц отключается даже при наличии ipfw. +Скрипты `ipset/*.sh` при наличии `ipfw` работают с ipfw lookup tables. +Это прямой аналог `ipset`. lookup tables не разделены на v4 и v6. Они могут содержать v4 и v6 адреса и подсети одновременно. +Если `ipfw` отсутствует, то действие зависит от переменной `LISTS_RELOAD` в `config`. +Если она задана, то выполняется команда из `LISTS_RELOAD`. В противном случае не делается ничего. +Если `LISTS_RELOAD=-`, то заполнение таблиц отключается даже при наличии `ipfw`. -PF может загружать ip таблицы из файла. Чтобы использовать эту возможность следует отключить сжатие gzip для листов -через параметр файла config "GZIP_LISTS=0". +PF может загружать IP таблицы из файла. Чтобы использовать эту возможность следует отключить сжатие gzip для листов +через параметр файла `config` `GZIP_LISTS=0`. -BSD не содержит системного вызова splice. tpws работает через переброску данных в user mode в оба конца. +BSD не содержит системного вызова `splice`. `tpws` работает через переброску данных в user mode в оба конца. Это медленнее, но не критически. -Управление асинхронными сокетами в tpws основано на linux-specific механизме epoll. +Управление асинхронными сокетами в `tpws` основано на Linux-specific механизме epoll. В BSD для его эмуляции используется epoll-shim - прослойка для эмуляции epoll на базе kqueue. -mdig и ip2net полностью работоспособны в BSD. В них нет ничего системо-зависимого. +`mdig` и `ip2net` полностью работоспособны в BSD. В них нет ничего системозависимого. -FreeBSD -------- +# FreeBSD -divert сокеты требуют специального модуля ядра ipdivert. -Поместите следующие строки в /boot/loader.conf (создать, если отсутствует) : ------------ +divert сокеты требуют специального модуля ядра `ipdivert`. +Поместите следующие строки в `/boot/loader.conf` (создать, если отсутствует): + +```conf ipdivert_load="YES" net.inet.ip.fw.default_to_accept=1 ------------ -В /etc/rc.conf : ------------ +``` + +В `/etc/rc.conf`: + +```conf firewall_enable="YES" firewall_script="/etc/rc.firewall.my" ------------ -/etc/rc.firewall.my : ------------ +``` + +`/etc/rc.firewall.my`: + +```sh ipfw -q -f flush ------------ -В /etc/rc.firewall.my можно дописывать правила ipfw, чтобы они восстанавливались после перезагрузки. -Оттуда же можно запускать и демоны zapret, добавив в параметры "--daemon". Например так : ------------ +``` + +В `/etc/rc.firewall.my` можно дописывать правила `ipfw`, чтобы они восстанавливались после перезагрузки. +Оттуда же можно запускать и демоны `zapret`, добавив в параметры `--daemon`. Например, так: + +```sh pkill ^dvtws$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2 ------------ -Для перезапуска фаервола и демонов достаточно будет сделать : /etc/rc.d/ipfw restart +``` +Для перезапуска фаервола и демонов достаточно будет сделать: `/etc/rc.d/ipfw restart` -Краткая инструкция по запуску tpws в прозрачном режиме. -Предполагается, что интерфейс LAN называется em1, WAN - em0. +## Краткая инструкция по запуску `tpws` в прозрачном режиме -Для всего трафика : +Предполагается, что интерфейс LAN называется `em1`, WAN - `em0`. + +Для всего трафика: + +```sh ipfw delete 100 ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 +``` -Для трафика только на таблицу zapret, за исключением таблицы nozapret : +Для трафика только на таблицу `zapret`, за исключением таблицы `nozapret`: + +```sh ipfw delete 100 ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon @@ -96,25 +114,28 @@ ipfw add 100 allow tcp from any to table\(nozapret\) 80,443 recv em1 ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 +``` -Таблицы zapret, nozapret, ipban создаются скриптами из ipset по аналогии с Linux. -Обновление скриптов можно забить в cron под root : - crontab -e - Создать строчку "0 12 */2 * * /opt/zapret/ipset/get_config.sh" +Таблицы `zapret`, `nozapret`, `ipban` создаются скриптами из `ipset` по аналогии с Linux. +Обновление скриптов можно забить в cron под root: `crontab -e`. +Создать для крона строчку `0 12 */2 * * /opt/zapret/ipset/get_config.sh` -При использовании ipfw tpws не требует повышенных привилегий для реализации прозрачного режима. +При использовании `ipfw` `tpws` не требует повышенных привилегий для реализации прозрачного режима. Однако, без рута невозможен бинд на порты <1024 и смена UID/GID. Без смены UID будет рекурсия, -поэтому правила ipfw нужно создавать с учетом UID, под которым работает tpws. +поэтому правила `ipfw` нужно создавать с учетом UID, под которым работает `tpws`. Переадресация на порты >=1024 может создать угрозу перехвата трафика непривилегированным -процессом, если вдруг tpws не запущен. +процессом, если вдруг `tpws` не запущен. +Краткая инструкция по запуску `dvtws`. -Краткая инструкция по запуску dvtws. +Для всего трафика: -Для всего трафика : +```sh ipfw delete 100 ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 + # required for autottl mode only + ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0 /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 @@ -122,66 +143,73 @@ ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diver ipfw delete 100 ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0 + # required for autottl mode only + ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0 /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 - +``` PF в FreeBSD: Настройка аналогична OpenBSD, но есть важные нюансы. -1) В FreeBSD поддержка PF в tpws отключена по умолчанию. Чтобы ее включить, нужно использовать параметр --enable-pf. -2) Нельзя сделать ipv6 rdr на ::1. Нужно делать на link-local адрес входящего интерфейса. -Смотрите через ifconfig адрес fe80:... и добавляете в правило -3) Синтаксис pf.conf немного отличается. Более новая версия PF. -4) Лимит на количество элементов таблиц задается так : sysctl net.pf.request_maxcount=2000000 + +1) В FreeBSD поддержка PF в `tpws` отключена по умолчанию. Чтобы ее включить, нужно использовать параметр `--enable-pf`. +2) Нельзя сделать IPv6 rdr на `::1`. Нужно делать на link-local адрес входящего интерфейса. +Смотрите через `ifconfig` адрес `fe80:...` и добавляете в правило. +3) Синтаксис `pf.conf` немного отличается. Более новая версия PF. +4) Лимит на количество элементов таблиц задается так: `sysctl net.pf.request_maxcount=2000000` 5) divert-to сломан. Он работает, но не работает механизм предотвращения зацикливаний. Кто-то уже написал патч, но в 14-RELEASE проблема все еще есть. -Следовательно, на данный момент работа dvtws через pf невозможна. +Следовательно, на данный момент работа `dvtws` через `pf` невозможна. -/etc/pf.conf ------------ +`/etc/pf.conf`: + +``` rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::31c:29ff:dee2:1c4d port 988 rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 ------------ +``` + +```sh /opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force +``` В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал. - -pfsense -------- +# pfsense pfsense основано на FreeBSD. -pfsense использует фаервол pf, а он имеет проблемы с divert. -К счастью, модули ipfw и ipdivert присутствуют в поставке последних версий pfsense. -Их можно подгрузить через kldload. -В некоторых более старых версиях pfsense требуется изменить порядок фаерволов через sysctl, сделав ipfw первым. -В более новых эти параметры sysctl отсутствуют, но система работает как надо и без них. -В некоторых случаях фаервол pf может ограничивать возможности dvtws, в частности в области фрагментации ip. +pfsense использует фаервол `pf`, а он имеет проблемы с divert. +К счастью, модули `ipfw` и `ipdivert` присутствуют в поставке последних версий pfsense. +Их можно подгрузить через `kldload`. +В некоторых более старых версиях pfsense требуется изменить порядок фаерволов через `sysctl`, сделав `ipfw` первым. +В более новых эти параметры `sysctl` отсутствуют, но система работает как надо и без них. +В некоторых случаях фаервол `pf` может ограничивать возможности `dvtws`, в частности в области фрагментации IP. Присутствуют по умолчанию правила scrub для реассемблинга фрагментов. -Бинарики из binaries/freebsd-x64 собраны под FreeBSD 11. Они должны работать и на последующих версиях FreeBSD, -включая pfsense. Можно пользоваться install_bin.sh. +Бинарники из `binaries/freebsd-x64` собраны под FreeBSD 11. Они должны работать и на последующих версиях FreeBSD, +включая pfsense. Можно пользоваться `install_bin.sh`. -Пример скрипта автозапуска лежит в init.d/pfsense. Его следует поместить в /usr/local/etc/rc.d и отредактировать -на предмет правил ipfw и запуска демонов. Есть встроенный редактор edit как более приемлемая альтернатива vi. -Поскольку git отсутствует, копировать файлы удобнее всего через ssh. curl присутствует по умолчанию. -Можно скопировать zip с файлами zapret и распаковать в /opt, как это делается на других системах. -Тогда dvtws нужно запускать как /opt/zapret/nfq/dvtws. Либо скопировать только dvtws в /usr/local/sbin. +Пример скрипта автозапуска лежит в `init.d/pfsense`. Его следует поместить в `/usr/local/etc/rc.d` и отредактировать +на предмет правил `ipfw` и запуска демонов. Есть встроенный редактор `edit` как более приемлемая альтернатива `vi`. +Поскольку `git` отсутствует, копировать файлы удобнее всего через `ssh`. `curl` присутствует по умолчанию. +Можно скопировать zip с файлами `zapret` и распаковать в `/opt`, как это делается на других системах. +Тогда `dvtws` нужно запускать как `/opt/zapret/nfq/dvtws`. Либо скопировать только `dvtws` в `/usr/local/sbin`. Как вам больше нравится. -ipset скрипты работают, крон есть. Можно сделать автообновление листов. +`ipset` скрипты работают, крон есть. Можно сделать автообновление листов. Если вас напрягает бедность имеющегося репозитория, можно включить репозиторий от FreeBSD, который по умолчанию выключен. -Поменяйте no на yes в /usr/local/etc/pkg/repos/FreeBSD.conf -Можно установить весь привычный soft, включая git, чтобы напрямую скачивать zapret с github. +Поменяйте `no` на `yes` в `/usr/local/etc/pkg/repos/FreeBSD.conf` +Можно установить весь привычный soft, включая `git`, чтобы напрямую скачивать zapret с GitHub. -/usr/local/etc/rc.d/zapret.sh (chmod 755) ------------ -#!/bin/sh +`/usr/local/etc/rc.d/zapret.sh` (`chmod 755`): + +```sh +# !/bin/sh kldload ipfw kldload ipdivert # for older pfsense versions. newer do not have these sysctls + sysctl net.inet.ip.pfil.outbound=ipfw,pf sysctl net.inet.ip.pfil.inbound=ipfw,pf sysctl net.inet6.ip6.pfil.outbound=ipfw,pf @@ -193,42 +221,48 @@ pkill ^dvtws$ dvtws --daemon --port 989 --dpi-desync=split2 # required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state -pfctl -d ; pfctl -e ------------ -Что касается tpws, то видимо имеется некоторый конфликт двух фаерволов, и правила fwd в ipfw не работают. -Работает перенаправление средствами pf как описано в разделе по FreeBSD. -В pf можно изменять правила только целыми блоками - якорями (anchors). Нельзя просто так добавить или удалить что-то. +pfctl -d ; pfctl -e +``` + +Что касается `tpws`, то видимо имеется некоторый конфликт двух фаерволов, и правила fwd в `ipfw` не работают. +Работает перенаправление средствами `pf` как описано в разделе по FreeBSD. +В `pf` можно изменять правила только целыми блоками - якорями (anchors). Нельзя просто так добавить или удалить что-то. Но чтобы какой-то anchor был обработан, на него должна быть ссылка из основного набора правил. Его трогать нельзя, иначе порушится весь фаервол. -Поэтому придется править код скриптов pfsense. Поправьте /etc/inc/filter.inc следующим образом : ------------ - ................. - /* MOD */ - $natrules .= "# ZAPRET redirection\n"; - $natrules .= "rdr-anchor \"zapret\"\n"; +Поэтому придется править код скриптов pfsense. Поправьте `/etc/inc/filter.inc` следующим образом: - $natrules .= "# TFTP proxy\n"; - $natrules .= "rdr-anchor \"tftp-proxy/*\"\n"; - ................. ------------ +``` + ................. + /*MOD*/ + $natrules .= "# ZAPRET redirection\n"; + $natrules .= "rdr-anchor \"zapret\"\n"; -Напишите файл с содержимым anchor-а (например, /etc/zapret.anchor): ------------ +$natrules .= "# TFTP proxy\n"; + $natrules .= "rdr-anchor \"tftp-proxy/*\"\n"; + ................. +``` + +Напишите файл с содержимым anchor-а (например, `/etc/zapret.anchor`): + +``` rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988 ------------ -fe80::20c:29ff:5ae3:4821 замените на ваш link local адрес LAN интерфейса, либо уберите строчку, если ipv6 не нужен. +``` -Добавьте в автозапуск /usr/local/etc/rc.d/zapret.sh : ------------ +`fe80::20c:29ff:5ae3:4821` замените на ваш link local адрес LAN интерфейса, либо уберите строчку, если IPv6 не нужен. + +Добавьте в автозапуск, `/usr/local/etc/rc.d/zapret.sh`: + +```sh pfctl -a zapret -f /etc/zapret.anchor pkill ^tpws$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2 ------------ +``` -После перезагрузки проверьте, что правила создались : ------------ +После перезагрузки проверьте, что правила создались: + +``` [root@pfSense /]# pfctl -s nat no nat proto carp all nat-anchor "natearly/*" all @@ -243,47 +277,54 @@ rdr pass on em1 inet proto tcp from any to any port = http -> 127.0.0.1 port 988 rdr pass on em1 inet proto tcp from any to any port = https -> 127.0.0.1 port 988 rdr pass on em1 inet6 proto tcp from any to any port = http -> fe80::20c:29ff:5ae3:4821 port 988 rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5ae3:4821 port 988 ------------ +``` -Так же есть более элегантный способ запуска tpws через @reboot в cron и правило перенаправления в UI. +Так же есть более элегантный способ запуска `tpws` через @reboot в `cron` и правило перенаправления в UI. Это позволит не редактировать код pfsense. +# OpenBSD -OpenBSD -------- - -В tpws бинд по умолчанию только на ipv6. для бинда на ipv4 указать "--bind-addr=0.0.0.0" -Используйте --bind-addr=0.0.0.0 --bind-addr=:: для достижения того же результата, как в других ОС по умолчанию. +В `tpws` бинд по умолчанию только на IPv6. для бинда на IPv4 указать `--bind-addr=0.0.0.0`. +Используйте `--bind-addr=0.0.0.0 --bind-addr=::` для достижения того же результата, как в других ОС по умолчанию. (лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы) -tpws для проходящего трафика : +`tpws` для проходящего трафика: -/etc/pf.conf ------------- -pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 -pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 ------------- +`/etc/pf.conf`: + +``` +pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 +pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 +``` + +```sh pfctl -f /etc/pf.conf tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 +``` В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал. -Поддержка rdr-to реализована через /dev/pf, поэтому прозрачный режим требует root. +Поддержка rdr-to реализована через `/dev/pf`, поэтому прозрачный режим требует root. -dvtws для всего трафика : +`dvtws` для всего трафика: -/etc/pf.conf ------------- +`/etc/pf.conf`: + +``` pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state pass in quick on em0 proto tcp from port {80,443} no state pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state ------------- +``` + +```sh pfctl -f /etc/pf.conf ./dvtws --port=989 --dpi-desync=split2 +``` -dvtws для трафика только на таблицу zapret, за исключением таблицы nozapret : +`dvtws` для трафика только на таблицу `zapret`, за исключением таблицы `nozapret`: -/etc/pf.conf ------------- +`/etc/pf.conf`: + +``` set limit table-entries 2000000 table file "/opt/zapret/ipset/zapret-ip.txt" table file "/opt/zapret/ipset/zapret-ip-user.txt" @@ -305,172 +346,209 @@ pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet pass in quick on em0 inet6 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state pass in quick on em0 inet6 proto tcp from port {80,443} no state pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet port 989 no state ------------- +``` + +```sh pfctl -f /etc/pf.conf ./dvtws --port=989 --dpi-desync=split2 +``` divert-packet автоматически вносит обратное правило для перенаправления. -Трюк с no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать массивный трафик через dvtws. +Трюк с no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать массивный трафик через `dvtws`. -В OpenBSD dvtws все фейки отсылает через divert socket, поскольку эта возможность через raw sockets заблокирована. -Видимо pf автоматически предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания нет. +В OpenBSD `dvtws` все фейки отсылает через divert socket, поскольку эта возможность через raw sockets заблокирована. +Видимо, `pf` автоматически предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания нет. -OpenBSD принудительно пересчитывает tcp checksum после divert, поэтому скорее всего -dpi-desync-fooling=badsum у вас не заработает. При использовании этого параметра -dvtws предупредит о возможной проблеме. +OpenBSD принудительно пересчитывает TCP checksum после divert, поэтому, скорее всего, +`--dpi-desync-fooling=badsum` у вас не заработает. При использовании этого параметра +`dvtws` предупредит о возможной проблеме. -Скрипты из ipset не перезагружают таблицы в PF по умолчанию. -Чтобы они это делали, добавьте параметр в /opt/zapret/config : +Скрипты из `ipset` не перезагружают таблицы в PF по умолчанию. +Чтобы они это делали, добавьте параметр в `/opt/zapret/config`: + +```sh LISTS_RELOAD="pfctl -f /etc/pf.conf" -Более новые версии pfctl понимают команду перезагрузить только таблицы : pfctl -Tl -f /etc/pf.conf +``` + +Более новые версии `pfctl` понимают команду перезагрузить только таблицы: `pfctl -Tl -f /etc/pf.conf`. Но это не относится к OpenBSD 6.8. В новых FreeBSD есть. -Не забудьте выключить сжатие gzip : +Не забудьте выключить сжатие gzip: + +```sh GZIP_LISTS=0 +``` + Если в вашей конфигурации какого-то файла листа нет, то его необходимо исключить из правил PF. -Если вдруг листа нет, и он задан в pf.conf, будет ошибка перезагрузки фаервола. -После настройки обновление листов можно поместить в cron : - crontab -e - дописать строчку : 0 12 */2 * * /opt/zapret/ipset/get_config.sh +Если вдруг листа нет, и он задан в `pf.conf`, будет ошибка перезагрузки фаервола. +После настройки обновление листов можно поместить в cron: +```sh +crontab -e +``` -MacOS ------ +дописать строчку: `0 12 */2 * * /opt/zapret/ipset/get_config.sh` + +# macOS Иначально ядро этой ОС "darwin" основывалось на BSD, потому в ней много похожего на другие версии BSD. Однако, как и в других массовых коммерческих проектах, приоритеты смещаются в сторону от оригинала. Яблочники что хотят, то и творят. -Раньше был ipfw, потом его убрали, заменили на PF. +Раньше был `ipfw`, потом его убрали, заменили на PF. Есть сомнения, что divert сокеты в ядре остались. Попытка создать divert socket не выдает ошибок, но полученный сокет ведет себя точно так же, как raw, со всеми его унаследованными косяками + еще яблочно специфическими. -В PF divert-packet не работает. Простой grep бинарика pfctl показывает, что там нет слова "divert", -а в других версиях BSD оно есть. dvtws собирается, но совершенно бесполезен. +В PF divert-packet не работает. Простой grep бинарника pfctl показывает, что там нет слова "divert", +а в других версиях BSD оно есть. `dvtws` собирается, но совершенно бесполезен. -tpws удалось адаптировать, он работоспособен. Получение адреса назначения для прозрачного прокси в PF (DIOCNATLOOK) -убрали из заголовков в новых SDK, сделав фактически недокументированным. -В tpws перенесены некоторые определения из более старых версий яблочных SDK. С ними удалось завести прозрачный режим. +`tpws` удалось адаптировать, он работоспособен. Получение адреса назначения для прозрачного прокси в PF (DIOCNATLOOK) +убрали из заголовков в новых SDK, сделав фактически недокументированным. +В `tpws` перенесены некоторые определения из более старых версий яблочных SDK. С ними удалось завести прозрачный режим. Однако, что будет в следующих версиях угадать сложно. Гарантий нет. -Еще одной особенностью PF в MacOS является проверка на рута в момент обращения к /dev/pf, чего нет в остальных BSD. -tpws по умолчанию сбрасывает рутовые привилегии. Необходимо явно указать параметр --user=root. -В остальном PF себя ведет похоже на FreeBSD. Синтаксис pf.conf тот же. +Еще одной особенностью PF в macOS является проверка на рута в момент обращения к `/dev/pf`, чего нет в остальных BSD. +`tpws` по умолчанию сбрасывает рутовые привилегии. Необходимо явно указать параметр `--user=root`. +В остальном PF себя ведет похоже на FreeBSD. Синтаксис `pf.conf` тот же. -На MacOS работает редирект как с проходящего трафика, так и с локальной системы через route-to. -Поскольку tpws вынужден работать под root, для исключения рекурсии приходится пускать исходящий от root трафик напрямую. -Отсюда имеем недостаток : обход DPI для рута работать не будет. +На macOS работает редирект как с проходящего трафика, так и с локальной системы через route-to. +Поскольку `tpws` вынужден работать под root, для исключения рекурсии приходится пускать исходящий от root трафик напрямую. +Отсюда имеем недостаток: обход DPI для рута работать не будет. Если вы пользуетесь MaсOS в качестве ipv6 роутера, то нужно будет решить вопрос с регулярно изменяемым link-local адресом. С некоторых версий MacOS использует по умолчанию постоянные "secured" ipv6 адреса вместо генерируемых на базе MAC адреса. Все замечательно, но есть одна проблема. Постоянными остаются только global scope адреса. Link locals периодически меняются. Смена завязана на системное время. Перезагрузки адрес не меняют, -Но если перевести время на день вперед и перезагрузиться - link local станет другим. (по крайней мере в vmware это так) +Но если перевести время на день вперед и перезагрузиться - link local станет другим. (по крайней мере в VMware это так) Информации по вопросу крайне мало, но тянет на баг. Не должен меняться link local. Скрывать link local не имеет смысла, а динамический link local нельзя использовать в качестве адреса шлюза. Проще всего отказаться от "secured" адресов. -Поместите строчку "net.inet6.send.opmode=0" в /etc/sysctl.conf. Затем перезагрузите систему. +Поместите строчку `net.inet6.send.opmode=0` в `/etc/sysctl.conf`. Затем перезагрузите систему. Все равно для исходящих соединений будут использоваться temporary адреса, как и в других системах. -Или вам идея не по вкусу, можно прописать дополнительный статический ipv6 из диапазона fc00::/7 - +Или вам идея не по вкусу, можно прописать дополнительный статический IPv6 из диапазона `fc00::/7` - выберите любой с длиной префикса 128. Это можно сделать в системных настройках, создав дополнительный адаптер на базе -того же сетевого интерфейса, отключить в нем ipv4 и вписать статический ipv6. Он добавится к автоматически настраеваемым. +того же сетевого интерфейса, отключить в нем IPv4 и вписать статический IPv6. Он добавится к автоматически настраиваемым. -Настройка tpws на macos в прозрачном режиме только для исходящих запросов : +Настройка `tpws` на macOS в прозрачном режиме только для исходящих запросов: -/etc/pf.conf ------------- +`/etc/pf.conf`: + +``` rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } ------------- +``` + +```sh pfctl -ef /etc/pf.conf /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force +``` +Настройка `tpws` на macOS роутере в прозрачном режиме, где `en1` - LAN. -Настройка tpws на macos роутере в прозрачном режиме, где en1 - LAN. - +``` ifconfig en1 | grep fe80 - inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8 -/etc/pf.conf ------------- + inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8 +``` + +`/etc/pf.conf`: + +``` rdr pass on en1 inet proto tcp from any to any port {80,443} -> 127.0.0.1 port 988 rdr pass on en1 inet6 proto tcp from any to any port {80,443} -> fe80::bbbb:bbbb:bbbb:bbbb port 988 rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } ------------- +``` + +```sh pfctl -ef /etc/pf.conf /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force +``` +Сборка: `make -C /opt/zapret mac` -Сборка : make -C /opt/zapret mac +Скрипты получения листов `ipset/*.sh` работают. +Если будете пользоваться `ipset/get_combined.sh`, нужно установить gnu `grep` через brew. +Имеющийся очень старый и безумно медленный с опцией `-f`. -Скрипты получения листов ipset/*.sh работают. -Если будете пользоваться ipset/get_combined.sh, нужно установить gnu grep через brew. -Имеющийся очень старый и безумно медленный с оцией -f. +## Простая установка +В macOS поддерживается `install_easy.sh` -MacOS простая установка ------------------------ +В комплекте идут бинарники, собранные под 64-bit с опцией `-mmacosx-version-min=10.8`. +Они должны работать на всех поддерживаемых версиях macOS. +Если вдруг не работают - можно собрать свои. Developer tools ставятся автоматом при запуске `make`. -В MacOS поддерживается install_easy.sh - -В комплекте идут бинарики, собраные под 64-bit с опцией -mmacosx-version-min=10.8. -Они должны работать на всех поддерживаемых версиях macos. -Если вдруг не работают - можно собрать свои. Developer tools ставятся автоматом при запуске make. - -!! Internet sharing средствами системы НЕ ПОДДЕРЖИВАЕТСЯ !! +**Internet sharing средствами системы НЕ ПОДДЕРЖИВАЕТСЯ** Поддерживается только роутер, настроенный своими силами через PF. Если вы вдруг включили шаринг, а потом выключили, то доступ к сайтам может пропасть совсем. -Лечение : pfctl -f /etc/pf.conf -Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и использовать socks. +Лечение: `pfctl -f /etc/pf.conf`. +Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и использовать SOCKS. -Для автостарта используется launchd (/Library/LaunchDaemons/zapret.plist) -Управляющий скрипт : /opt/zapret/init.d/macos/zapret -Следующие команды работают с tpws и фаерволом одновременно (если INIT_APPLY_FW=1 в config) +Для автостарта используется `launchd` (`/Library/LaunchDaemons/zapret.plist`). +Управляющий скрипт: `/opt/zapret/init.d/macos/zapret`. +Следующие команды работают с `tpws` и фаерволом одновременно (если `INIT_APPLY_FW=1` в `config`): + +```sh /opt/zapret/init.d/macos/zapret start /opt/zapret/init.d/macos/zapret stop /opt/zapret/init.d/macos/zapret restart -Работа только с tpws : +``` + +Работа только с `tpws`: + +```sh /opt/zapret/init.d/macos/zapret start-daemons /opt/zapret/init.d/macos/zapret stop-daemons /opt/zapret/init.d/macos/zapret restart-daemons -Работа только с PF : +``` + +Работа только с PF: + +```sh /opt/zapret/init.d/macos/zapret start-fw /opt/zapret/init.d/macos/zapret stop-fw /opt/zapret/init.d/macos/zapret restart-fw -Перезагрузка всех IP таблиц из файлов : +``` + +Перезагрузка всех IP таблиц из файлов: + +```sh /opt/zapret/init.d/macos/zapret reload-fw-tables +``` -Инсталятор настраивает LISTS_RELOAD в config, так что скрипты ipset/*.sh автоматически перезагружают IP таблицы в PF. -Автоматически создается cron job на ipset/get_config.sh, по аналогии с openwrt. +Инсталлятор настраивает `LISTS_RELOAD` в `config`, так что скрипты `ipset/*.sh` автоматически перезагружают IP таблицы в PF. +Автоматически создается cron job на `ipset/get_config.sh`, по аналогии с OpenWrt. -При start-fw скрипт автоматически модицифирует /etc/pf.conf, вставляя туда anchors "zapret". -Модификация расчитана на pf.conf, в котором сохранены дефолтные anchors от apple. -Если у вас измененный pf.conf и модификация не удалась, об этом будет предупреждение. Не игнорируйте его. -В этом случае вам нужно вставить в свой pf.conf (в соответствии с порядком типов правил) : +При `start-fw` скрипт автоматически модифицирует `/etc/pf.conf`, вставляя туда anchors "zapret". +Модификация рассчитана на `pf.conf`, в котором сохранены дефолтные anchors от Apple. +Если у вас измененный `pf.conf` и модификация не удалась, об этом будет предупреждение. Не игнорируйте его. +В этом случае вам нужно вставить в свой `pf.conf` (в соответствии с порядком типов правил): + +``` rdr-anchor "zapret" anchor "zapret" -При деинсталяции через uninstall_easy.sh модификации pf.conf убираются. +``` -start-fw создает 3 файла anchors в /etc/pf.anchors : zapret,zapret-v4,zapret-v6. +При деинсталляции через `uninstall_easy.sh` модификации `pf.conf` убираются. + +`start-fw` создает 3 файла anchors в `/etc/pf.anchors`: `zapret`, `zapret-v4`, `zapret-v6`. Последние 2 подключаются из anchor "zapret". -Таблицы nozapret,nozapret6 принадлежат anchor "zapret". -Таблицы zapret,zapret-user - в anchor "zapret-v4". -Таблицы zapret6,zapret6-user - в anchor "zapret-v6". +Таблицы `nozapret`, `nozapret6` принадлежат anchor "zapret". +Таблицы `zapret`, `zapret-user` - в anchor "zapret-v4". +Таблицы `zapret6`, `zapret6-user` - в anchor "zapret-v6". Если какая-то версия протокола отключена - соответствующий anchor пустой и не упоминается в anchor "zapret". Таблицы и правила создаются только на те листы, которые фактически есть в директории ipset. +## Вариант custom -MacOS вариант custom --------------------- +Так же как и в других системах, поддерживаемых в простом инсталляторе, можно создавать свои custom скрипты. +Расположение: `/opt/zapret/init.d/macos/custom` -Так же как и в других системах, поддерживаемых в простом инсталяторе, можно создавать свои custom скрипты. -Расположение : /opt/zapret/init.d/macos/custom - -zapret_custom_daemons() получает в $1 "0" или "1". "0" - stop, "1" - start -custom firewall отличается от linux варианта. -Вместо заполнения iptables вам нужно сгенерировать правила для zapret-v4 и zapret-v6 anchors и выдать их в stdout. -Это делается в функциях zapret_custom_firewall_v4() и zapret_custom_firewall_v6(). +`zapret_custom_daemons()` получает в `$1` "0" или "1". "0" - stop, "1" - start +custom firewall отличается от Linux варианта. +Вместо заполнения `iptables` вам нужно сгенерировать правила для `zapret-v4` и`zapret-v6` anchors и выдать их в stdout. +Это делается в функциях `zapret_custom_firewall_v4()` и `zapret_custom_firewall_v6()`. Определения таблиц заполняются основным скриптом - вам это делать не нужно. -Можно ссылаться на таблицы zapret и zapret-user в v4, zapret6 и zapret6-user. +Можно ссылаться на таблицы `zapret` и `zapret-user` в v4, `zapret6` и `zapret6-user`. -Cм. пример в файле custom-tpws +Cм. пример в файле `custom-tpws`. diff --git a/docs/bsdfw.txt b/docs/bsdfw.md similarity index 89% rename from docs/bsdfw.txt rename to docs/bsdfw.md index 2575c69..3223187 100644 --- a/docs/bsdfw.txt +++ b/docs/bsdfw.md @@ -1,7 +1,8 @@ -WAN=em0 LAN=em1 +`WAN=em0`, `LAN=em1` -FreeBSD IPFW : +FreeBSD IPFW: +```sh ipfw delete 100 ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon @@ -18,12 +19,11 @@ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 - ipfw delete 100 ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 -; required for autottl mode +# required for autottl mode ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0 -; udp +# udp ipfw add 100 divert 989 udp from any to any 443 out not diverted xmit em0 ipfw delete 100 @@ -31,10 +31,11 @@ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted xmit em0 /opt/zapret/nfq/dvtws --port=989 --debug --dpi-desync=split +``` +sample `ipfw` NAT setup: -sample ipfw NAT setup : - +```sh WAN=em0 LAN=em1 ipfw -q flush @@ -46,25 +47,28 @@ ipfw -q add 301 check-state ipfw -q add 350 skipto 390 tcp from any to any out xmit $WAN setup keep-state ipfw -q add 350 skipto 390 udp from any to any out xmit $WAN keep-state ipfw -q add 360 allow all from any to me in recv $WAN -ipfw -q add 390 nat 1 ip4 from any to any out xmit $WAN +ipfw -q add 390 nat 1 ip4 from any to any out xmit $WAN ipfw -q add 10000 allow ip from any to any +``` -Forwarding : +Forwarding: + +```sh sysctl net.inet.ip.forwarding=1 sysctl net.inet6.ip6.forwarding=1 +``` +OpenBSD PF: -OpenBSD PF : - -; dont know how to rdr-to from local system. doesn't seem to work. only works for routed traffic. - -/etc/pf.conf -pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 -pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 +```sh +# don't know how to rdr-to from local system. doesn't seem to work. only works for routed traffic. +# /etc/pf.conf +pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 +pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 pfctl -f /etc/pf.conf /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 -; dvtws works both for routed and local +# dvtws works both for routed and local pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state pass in quick on em0 proto tcp from port {80,443} no state @@ -72,8 +76,8 @@ pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no sta pfctl -f /etc/pf.conf ./dvtws --port=989 --dpi-desync=split2 -; dvtws with table limitations : to zapret,zapret6 but not to nozapret,nozapret6 -; reload tables : pfctl -f /etc/pf.conf +# dvtws with table limitations: to zapret,zapret6 but not to nozapret,nozapret6 +# reload tables: pfctl -f /etc/pf.conf set limit table-entries 2000000 table file "/opt/zapret/ipset/zapret-ip.txt" table file "/opt/zapret/ipset/zapret-ip-user.txt" @@ -95,3 +99,4 @@ pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet pass in quick on em0 inet6 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state pass in quick on em0 inet6 proto tcp from port {80,443} no state pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet port 989 no state +``` diff --git a/docs/changes.md b/docs/changes.md new file mode 100644 index 0000000..4234672 --- /dev/null +++ b/docs/changes.md @@ -0,0 +1,315 @@ +# 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 choice 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 how-to + +# 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 https://antifilter.network support + +# v29 + +* `nfqws`: DPI desync attack +* ip exclude system + +# v30 + +* `nfqws`: DPI desync attack modes: `fake`, `rst` + +# v31 + +* `nfqws`: DPI desync attack modes: `disorder`, `disorder2`, `split`, `split2`. +* `nfqws`: DPI desync fooling mode: `badseq`. multiple modes supported + +# v32 + +* `tpws`: multiple binds +* init scripts: run only one instance of `tpws` in any case + +# v33 + +* OpenWrt: flow offloading support +* `config`: `MODE` refactoring + +# v34 + +* `nfqws`: `dpi-desync` 2 mode combos +* `nfqws`: `dpi-desync` without parameter no more supported. previously it meant `fake` +* `nfqws`: custom fake HTTP request and TLS ClientHello + +# v35 + +* limited FreeBSD and OpenBSD support + +# v36 + +* full FreeBSD and OpenBSD support + +# v37 + +* limited macOS support + +# v38 + +* macOS easy install + +# v39 + +* `nfqws`: `conntrack`, `wssize` + +# v40 + +* init scripts: `IFACE_LAN`, `IFACE_WAN` now accept multiple interfaces +* init scripts: OpenWrt uses now `OPENWRT_LAN` parameter to override incoming interfaces for `tpws` + +# v41 + +* `install_easy`: openrc support + +# v42 + +* `blockcheck.sh` + +# v43 + +* `nfqws`: UDP desync with conntrack support (any-protocol only for now) + +# v44 + +* `nfqws`: `ipfrag` + +# v45 + +* `nfqws`: `hop-by-hop` - IPv6 desync and fooling + +# v46 + +* big startup script refactoring to support `nftables` and new OpenWrt snapshot builds with `firewall4` + +# v47 + +* `nfqws`: QUIC initial decryption +* `nfqws`: `udplen`, `fakeknown` dpi desync modes + +# v48 + +* `nfqws`, `tpws`: multiple `--hostlist` and `--hostlist-exclude` support +* launch system, `ipset`: no more list merging. all lists are passed separately to `nfqws` and `tpws` +* `nfqws`: `udplen` fooling supports packet shrinking (negative increment value) + +# v49 + +* QUIC support integrated to the main system and setup + +# v50 + +* DHT protocol support. +* DPI desync mode `tamper` for DHT. +* HEX string support in addition to binary files. + +# v51 + +* `tpws`: `--tlsrec` attack. + +# v52 + +* `autohostlist` mode + +# v53 + +* `nfqws`: TCP session reassemble for TLS ClientHello + +# v54 + +* `tpws`: out of band send when splitting (`--oob`) +* `nfqws`: `autottl` +* `nfqws`: `datanoack` fooling +* nftables: use POSTNAT path for TCP redirections to allow NAT-breaking strategies. use additional mark bit DESYNC_MARK_POSTNAT. + +# v55 + +* `tpws`: + * incompatible `oob` parameter change. it doesn't take oob byte anymore. instead it takes optional protocol filter - HTTP or TLS. + * the same is done with `disorder`. oob byte can be specified in parameter `--oob-data`. +* `blockcheck`: quick mode, strategy order optimizations, QUIC protocol support +* `nfqws`: `syndata` desync mode + +# v56 + +* `tpws`: `mss` fooling +* `tpws`: multi thread resolver. eliminates blocks related to hostname resolve. + +# v57 + +* `tpws`: `--nosplice` option +* `nfqws`: postnat fixes +* `nfqws`: `--dpi-desync-start` option +* `nfqws`: packet delay for kyber TLS and QUIC +* `nfqws`: `--dpi-desync-retrans` obsolete +* `nfqws`: `--qnum` is mandatory, no more default queue 0 + +# v58 + +* `winws` + +# v59 + +* `tpws`: `--split-tls` +* `tpws`: `--tlsrec=sniext` +* `nfqws`: `--dpi-desync-split-http-req`, `--dpi-desync-split-tls`. multi segment TLS support for split. +* `blockcheck`: `mdig` DNS cache + +# v60 + +* `blockcheck`: port block test, partial ip block test +* `nfqws`: `seqovl` `split`/`disorder` modes + +# v61 + +* C code cleanups +* `dvtws`: do not use raw sockets. use divert. +* `nfqws`,`tpws`: detect TLS 1.2 ClientHello from very old libraries with SSL 3.0 version in record layer +* `nfqws`,``tpws``: debug log to file and syslog +* ``tpws``: `--connect-bind-addr` option +* ``tpws``: log local endpoint (including source port number) for remote leg diff --git a/docs/changes.txt b/docs/changes.txt deleted file mode 100644 index 797ed92..0000000 --- a/docs/changes.txt +++ /dev/null @@ -1,310 +0,0 @@ -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 - -v31 - -nfqws : DPI desync attack modes : disorder,disorder2,split,split2. -nfqws : DPI desync fooling mode : badseq. multiple modes supported - -v32 - -tpws : multiple binds -init scripts : run only one instance of tpws in any case - -v33 - -openwrt : flow offloading support -config : MODE refactoring - -v34 - -nfqws : dpi-desync 2 mode combos -nfqws : dpi-desync without parameter no more supported. previously it meant "fake" -nfqws : custom fake http request and tls client hello - -v35 - -limited FreeBSD and OpenBSD support - -v36 - -full FreeBSD and OpenBSD support - -v37 - -limited MacOS support - -v38 - -MacOS easy install - -v39 - -nfqws: conntrack, wssize - -v40 - -init scripts : IFACE_LAN, IFACE_WAN now accept multiple interfaces -init scripts : openwrt uses now OPENWRT_LAN parameter to override incoming interfaces for tpws - -v41 - -install_easy : openrc support - -v42 - -blockcheck.sh - -v43 - -nfqws: UDP desync with conntrack support (any-protocol only for now) - -v44 - -nfqws: ipfrag - -v45 - -nfqws: hop-by-hop ipv6 desync and fooling - -v46 - -big startup script refactoring to support nftables and new openwrt snapshot builds with firewall4 - -v47 - -nfqws: QUIC initial decryption -nfqws: udplen, fakeknown dpi desync modes - -v48 - -nfqws, tpws : multiple --hostlist and --hostlist-exclude support -launch system, ipset : no more list merging. all lists are passed separately to nfqws and tpws -nfqws : udplen fooling supports packet shrinking (negative increment value) - -v49 - -QUIC support integrated to the main system and setup - -v50 - -DHT protocol support. -DPI desync mode 'tamper' for DHT. -HEX string support in addition to binary files. - -v51 - -tpws --tlsrec attack. - -v52 - -autohostlist mode - -v53 - -nfqws: tcp session reassemble for TLS ClientHello - -v54 - -tpws: out of band send when splitting (--oob) -nfqws: autottl -nfqws: datanoack fooling -nftables: use POSTNAT path for tcp redirections to allow NAT-breaking strategies. use additional mark bit DESYNC_MARK_POSTNAT. - -v55 - -tpws: incompatible oob parameter change. it doesn't take oob byte anymore. instead it takes optional protocol filter - http or tls. - the same is done with disorder. oob byte can be specified in parameter --oob-data. -blockcheck: quick mode, strategy order optimizations, QUIC protocol support -nfqws: syndata desync mode - -v56 - -tpws: mss fooling -tpws: multi thread resolver. eliminates blocks related to hostname resolve. - -v57 - -tpws: --nosplice option -nfqws: postnat fixes -nfqws: --dpi-desync-start option -nfqws: packet delay for kyber TLS and QUIC -nfqws: --dpi-desync-retrans obsolete -nfqws: --qnum is mandatory, no more default queue 0 - -v58 - -winws - -v59 - -tpws: --split-tls -tpws: --tlsrec=sniext -nfqws: --dpi-desync-split-http-req, --dpi-desync-split-tls. multi segment TLS support for split. -blockcheck: mdig dns cache - -v60 - -blockcheck: port block test, partial ip block test -nfqws: seqovl split/disorder modes - -v61 - -C code cleanups -dvtws: do not use raw sockets. use divert. -nfqws,tpws: detect TLS 1.2 ClientHello from very old libraries with SSL 3.0 version in record layer -nfqws,tpws: debug log to file and syslog -tpws: --connect-bind-addr option -tpws: log local endpoint (including source port number) for remote leg diff --git a/docs/compile/build_howto_openwrt.md b/docs/compile/build_howto_openwrt.md new file mode 100644 index 0000000..20edadc --- /dev/null +++ b/docs/compile/build_howto_openwrt.md @@ -0,0 +1,70 @@ +How to compile native programs for use in OpenWrt +------------------------------------------------- + +1) Fetch correct version of OpenWrt + +```sh +cd ~ +``` + +* the latest: + +```sh +git clone git://git.openwrt.org/openwrt.git +``` + +* exact version for older devices, e.g., 15.05: + +```sh +git clone git://git.openwrt.org/15.05/openwrt.git +``` + +```sh +cd openwrt +``` + +2) Feed Initialization and Installation + +```sh +./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` folder to `~/openwrt/package/zapret/tpws` +* Copy source code of `nfq`: copy `nfq` folder to `~/openwrt/package/zapret/nfq` +* Copy source code of `ip2net`: copy `ip2net` folder to `~/openwrt/package/zapret/ip2net` + +4) Make a menuconfig + +```sh +make menuconfig +``` + +* Select your target architecture +* Select packages `Network/Zapret/*` as "M" + +5) Compile a toolchain + +```sh +make toolchain/compile +``` + +6) Compile packages + +```sh +make package/tpws/compile +make package/nfqws/compile +make package/ip2net/compile +make package/mdig/compile +``` + +7) Get resulting packages + +Take your `tpws*.ipk`, `nfqws*.ipk`, `ip2net*.ipk`, `mdig*.ipk` from there, e.g.: + +```sh +find bin -name tpws*.ipk +``` diff --git a/docs/compile/build_howto_openwrt.txt b/docs/compile/build_howto_openwrt.txt deleted file mode 100644 index 46a65d8..0000000 --- a/docs/compile/build_howto_openwrt.txt +++ /dev/null @@ -1,42 +0,0 @@ -How to compile native programs for use in openwrt -------------------------------------------------- - -1) - - cd ~ - - - git clone git://git.openwrt.org/15.05/openwrt.git - - git clone git://git.openwrt.org/14.07/openwrt.git - - 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 diff --git a/docs/iptables.txt b/docs/iptables.md similarity index 89% rename from docs/iptables.txt rename to docs/iptables.md index 4e319e0..12baa52 100644 --- a/docs/iptables.txt +++ b/docs/iptables.md @@ -1,45 +1,56 @@ -For window size changing : +For window size changing: +```sh 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 dpi desync attack : +For `dpi-desync` attack: +```sh iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass iptables -t mangle -I POSTROUTING -p tcp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass iptables -t mangle -I POSTROUTING -p udp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass -# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI -sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 +# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by Russian DPI + +sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:12 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass iptables -t mangle -I PREROUTING -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass +``` +For `TPROXY`: -For TPROXY : - +```sh 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 988 -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 988 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 988 +``` -For DNAT : +For DNAT: + +```sh +# run tpws as user "tpws". its required to avoid loops -# 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.127:988 iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988 +``` +Reset all `iptables` rules: -Reset all iptable rules : - +```sh iptables -F iptables -X iptables -t nat -F @@ -48,9 +59,11 @@ iptables -t mangle -F iptables -t mangle -X iptables -t raw -F iptables -t raw -X +``` -Reset iptable policies : +Reset `iptables` policies: +```sh iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT @@ -61,3 +74,4 @@ iptables -t mangle -P FORWARD ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -t raw -P PREROUTING ACCEPT iptables -t raw -P OUTPUT ACCEPT +``` diff --git a/docs/manual_setup.md b/docs/manual_setup.md new file mode 100644 index 0000000..57162ee --- /dev/null +++ b/docs/manual_setup.md @@ -0,0 +1,420 @@ +- [Пример ручной установки на Debian-подобную систему](#пример-ручной-установки-на-debian-подобную-систему) +- [CentOS 7+, Fedora](#centos-7-fedora) +- [openSUSE](#opensuse) +- [Arch Linux](#arch-linux) +- [Gentoo](#gentoo) +- [Ручная установка на OpenWrt/LEDE 15.xx-21.xx](#ручная-установка-на-openwrtlede-15xx-21xx) + +Пример ручной установки на Debian-подобную систему +-------------------------------------------------- + +На Debian основано большое количество дистрибутивов Linux, включая Ubuntu. +Здесь рассматриваются прежде всего Debian 8+ и Ubuntu 16+. +Но с большой вероятностью может сработать и на производных от них. +Главное условие - наличие `systemd`, `apt` и нескольких стандартных пакетов в репозитории. + +Установить пакеты: + +```sh +apt-get update +apt-get install ipset curl dnsutils git +``` + +Если хотите использовать `nftables`, то нужен пакет `nftables`, а `ipset` не обязателен. + +Скопировать директорию `zapret` в `/opt` или скачать через `git`: + +```sh +cd /opt +git clone --depth 1 https://github.com/bol-van/zapret +``` + +Запустить автоинсталлятор бинарников. Он сам определит рабочую архитектуру и настроит все бинарники. + +```sh +/opt/zapret/install_bin.sh +``` + +**АЛЬТЕРНАТИВА:** `make -C /opt/zapret`. Получите динамические бинарники под вашу ось. +Для сборки требуются dev пакеты: `zlib1g-dev`, `libcap-dev`, `libnetfilter-queue-dev`. + +Создать конфиг по умолчанию: + +```sh +cp /opt/zapret/config.default /opt/zapret/config +``` + +Настроить параметры согласно разделу "Выбор параметров". + +Создать user листы по умолчанию: + +```sh +cp /opt/zapret/ipset/zapret-hosts-user-exclude.txt.default /opt/zapret/ipset/zapret-hosts-user-exclude.txt +echo nonexistent.domain > /opt/zapret/ipset/zapret-hosts-user.txt +touch /opt/zapret/ipset/zapret-hosts-user-ipban.txt +``` + +Создать ссылку на service unit в `systemd`: + +```sh +ln -fs /opt/zapret/init.d/systemd/zapret.service /lib/systemd/system +``` + +Удалить старые листы, если они были созданы ранее: + +```sh +/opt/zapret/ipset/clear_lists.sh +``` + +По желанию прописать в `/opt/zapret/ipset/zapret-hosts-user.txt` свои домены. + +Выполнить скрипт обновления листа: + +```sh +/opt/zapret/ipset/get_config.sh +``` + +Настроить таймер `systemd` для обновления листа: + +```sh +ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /lib/systemd/system +ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /lib/systemd/system +``` + +Принять изменения в `systemd`: `systemctl daemon-reload` + +Включить автозапуск службы: `systemctl enable zapret` + +Включить таймер обновления листа: `systemctl enable zapret-list-update.timer` + +Запустить службу: `systemctl start zapret` + +Шпаргалка по управлению службой и таймером : + +- enable auto start: `systemctl enable zapret` +- disable auto start: `systemctl disable zapret` +- start: `systemctl start zapret` +- stop: `systemctl stop zapret` +- status, output messages: `systemctl status zapret` +- timer info: `systemctl list-timer` +- delete service: `systemctl disable zapret; rm /lib/systemd/system/zapret.service` +- delete timer: `systemctl disable zapret-list-update.timer; rm /lib/systemd/system/zapret-list-update.*` + +CentOS 7+, Fedora +----------------- + +CentOS с 7 версии и более-менее новые федоры построены на `systemd`. +В качестве пакетного менеджера используется `yum`. + +Установить пакеты: + +```sh +yum install -y curl ipset dnsutils git +``` + +Далее все аналогично Debian. + +openSUSE +-------- + +Новые openSUSE основаны на `systemd` и менеджере пакетов `zypper`. + +Установить пакеты: + +```sh +zypper --non-interactive install curl ipset +``` + +Далее все аналогично Debian, кроме расположения `systemd`. +В openSUSE он находится не в `/lib/systemd`, а в `/usr/lib/systemd`. +Правильные команды будут: + +```sh +ln -fs /opt/zapret/init.d/systemd/zapret.service /usr/lib/systemd/system +ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /usr/lib/systemd/system +ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /usr/lib/systemd/system +``` + +Arch Linux +---------- + +Построен на базе `systemd`. + +Установить пакеты: + +```sh +pacman -Syy +pacman --noconfirm -S ipset curl +``` + +Далее все аналогично Debian. + +Gentoo +------ + +Эта система использует OpenRC - улучшенную версию sysvinit. +Установка пакетов производится командой: `emerge ` +Пакеты собираются из исходников. + +Требуются все те же `ipset`, `curl`, `git` для скачивания с GitHub. +`git` и `curl` по умолчанию могут присутствовать, `ipset` отсутствует. + +```sh +emerge ipset +``` + +Настроить параметры согласно разделу "Выбор параметров". + +Запустить автоинсталлятор бинарников. Он сам определит рабочую архитектуру и настроит все бинарники: + +```sh +/opt/zapret/install_bin.sh +``` + +**АЛЬТЕРНАТИВА:** `make -C /opt/zapret`. Получите динамические бинарники под вашу ось. + +Удалить старые листы, если они были созданы ранее: + +```sh +/opt/zapret/ipset/clear_lists.sh +``` + +По желанию прописать в `/opt/zapret/ipset/zapret-hosts-user.txt` свои домены. + +Выполнить скрипт обновления листа: + +```sh +/opt/zapret/ipset/get_config.sh +``` + +Зашедулить обновление листа: + +```sh +crontab -e +``` + +Создать для крона строчку `0 12 */2* * /opt/zapret/ipset/get_config.sh` + +Подключить init скрипт: + +```sh +ln -fs /opt/zapret/init.d/openrc/zapret /etc/init.d +rc-update add zapret +``` + +Запустить службу: + +```sh +rc-service zapret start +``` + +Шпаргалка по управлению службой: + +- enable auto start: `rc-update add zapret` +- disable auto start: `rc-update del zapret` +- start: `rc-service zapret start` +- stop: `rc-service zapret stop` + +Ручная установка на OpenWrt/LEDE 15.xx-21.xx +-------------------------------------------- + +**ВАЖНО:** Данная инструкция написана для систем, основанных на `iptables`+`firewall3`. +В новых версиях OpenWrt переходит на `nftables`+`firewall4`, инструкция неприменима. Пользуйтесь `install_easy.sh` + +Установить дополнительные пакеты: + +```sh +opkg update +opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ipset curl +# (IPv6) opkg install ip6tables-mod-nat +# (опционально) opkg install gzip +# (опционально) opkg install coreutils-sort +``` + +**ЭКОНОМИЯ МЕСТА:** + +`gzip` от `busybox` в разы медленней полноценного варианта. `gzip` используется скриптами получения листов. +`sort` от `busybox` медленней полноценного варианта и жрет намного больше памяти. `sort` используется скриптами получения листов. +`iptables-mod-nfqueue` можно выкинуть, если не будем пользоваться `nfqws`. +`curl` можно выкинуть, если для получения IP листа будет использоваться только `get_user.sh` + +Самая главная трудность - скомпилировать программы на C. Это можно сделать на Linux x64 при помощи SDK, который можно скачать с официального сайта OpenWrt или LEDE. Но процесс кросс-компиляции - это всегда сложности. +Недостаточно запустить `make` как на традиционной Linux системе. +Поэтому в `binaries/` имеются готовые статические бинарники для всех самых распространенных архитектур. +Статическая сборка означает, что бинарник не зависит от типа `libc` (`glibc`, `uclibc` или `musl`) и наличия установленных `*.so`. +Его можно использовать сразу. Лишь бы подходил тип CPU. У ARM и MIPS есть несколько версий. +Скорее всего найдется рабочий вариант. Если нет - вам придется собирать самостоятельно. +Для всех поддерживаемых архитектур бинарники запакованы `upx`. На текущий момент все, кроме `mips64`. + +Скопировать директорию `zapret` в `/opt` на роутер. + +Если места достаточно, самый простой способ: + +```sh +opkg update +opkg install git-http +mkdir /opt +cd /opt +git clone --depth 1 https://github.com/bol-van/zapret +``` + +Если места немного: + +```sh +opkg update +opkg install openssh-sftp-server unzip +ifconfig br-lan +``` + +Скачать на комп с GitHub zip архив кнопкой "Clone or download" -> Download ZIP +Скопировать средствами `sftp` zip архив на роутер в `/tmp`. + +```sh +mkdir /opt +cd /opt +unzip /tmp/zapret-master.zip +mv zapret-master zapret +rm /tmp/zapret-master.zip +``` + +Если места совсем мало: +На Linux системе скачать и распаковать zapret. Оставить необходимый минимум файлов. +Запаковать в архив `zapret.tar.gz`. + +```sh +nc -l -p 1111 < zapret.tar.gz +``` + +На роутере: + +```sh +cd /tmp +nc 1111 >zapret.tar.gz +``` + +Не стоит работать с распакованной версией `zapret` на Windows. Потеряются ссылки и `chmod`. + +Запустить автоинсталлятор бинарников. Он сам определит рабочую архитектуру и настроит все бинарники: + +```sh +/opt/zapret/install_bin.sh +``` + +Создать ссылку на скрипт запуска: + +```sh +ln -fs /opt/zapret/init.d/openwrt/zapret /etc/init.d +``` + +Создать ссылку на скрипт события поднятия интерфейса: + +```sh +ln -fs /opt/zapret/init.d/openwrt/90-zapret /etc/hotplug.d/iface +``` + +Создать конфиг по умолчанию: + +```sh +cp /opt/zapret/config.default /opt/zapret/config +``` + +Настроить параметры согласно разделу "Выбор параметров". + +Создать user листы по умолчанию: + +```sh +cp /opt/zapret/ipset/zapret-hosts-user-exclude.txt.default /opt/zapret/ipset/zapret-hosts-user-exclude.txt +echo nonexistent.domain > /opt/zapret/ipset/zapret-hosts-user.txt +touch /opt/zapret/ipset/zapret-hosts-user-ipban.txt +``` + +Удалить старые листы, если они были созданы ранее: + +```sh +/opt/zapret/ipset/clear_lists.sh +``` + +По желанию прописать в `/opt/zapret/ipset/zapret-hosts-user.txt` свои домены. +Выполнить скрипт обновления листа: + +```sh +/opt/zapret/ipset/get_config.sh +``` + +Зашедулить обновление листа: + +```sh +crontab -e +``` + +Создать для крона строчку `0 12 */2* * /opt/zapret/ipset/get_config.sh` + +Включить автозапуск службы и запустить ее: + +```sh +/etc/init.d/zapret enable +/etc/init.d/zapret start +``` + +**ПРИМЕЧАНИЕ:** на этапе старта системы интерфейсы еще не подняты. +В некоторых случаях невозможно правильно сформировать параметры запуска демонов, не зная имя физического интерфейса LAN. +Скрипт из /etc/hotplug.d/iface перезапустит демоны по событию поднятия LAN. + +Создать ссылку на firewall include: + +```sh +ln -fs /opt/zapret/init.d/openwrt/firewall.zapret /etc/firewall.zapret +``` + +Проверить была ли создана ранее запись о firewall include: + +```sh +uci show firewall | grep firewall.zapret +``` + +Если `firewall.zapret` нет, значит добавить: + +```sh +uci add firewall include +uci set firewall.@include[-1].path="/etc/firewall.zapret" +uci set firewall.@include[-1].reload="1" +uci commit firewall +``` + +Проверить, не включен ли flow offload: + +```sh +uci show firewall.@defaults[0] +``` + +Если `flow_offloading=1` или `flow_offloading_hw=1`: + +```sh +uci set firewall.@defaults[0].flow_offloading=0 +uci set firewall.@defaults[0].flow_offloading_hw=0 +uci commit firewall +``` + +Перезапустить фаервол: + +```sh +fw3 restart +``` + +Посмотреть через `iptables -nL`, `ip6tables -nL` или через `luci` вкладку "firewall", появились ли нужные правила. + +**ЭКОНОМИЯ МЕСТА:** если его мало, то можно оставить в директории `zapret` лишь подкаталоги `ipset/`, `common/`, файл `config/`, `init.d/openwrt/`. +Далее нужно создать подкаталоги с реально используемыми бинарниками (`ip2net`, `mdig`, `tpws`, `nfq`) и скопировать туда из `binaries/` рабочие executables. + +**ЕСЛИ ВСЕ ПЛОХО С МЕСТОМ:** откажитесь от работы со списком РКН. используйте только `get_user.sh`. + +**ЕСЛИ СОВСЕМ ВСЕ УЖАСНО С МЕСТОМ:** берете `tpws` и делаете все своими руками. поднятие `iptables`, автостарт бинарника. +С некоторых версий скрипты запуска zapret без `ipset` не работают (он требуется для IP exclude). + +**СОВЕТ:** Покупайте только роутеры с USB. +В USB можно воткнуть флэшку и вынести на нее корневую файловую систему или использовать ее в качестве оверлея. +Не надо мучить себя, запихивая незапихиваемое в 8 мб встроенной флэшки. +Для комфортной работы с zapret нужен роутер с 16 Mb встроенной памяти или USB разъемом и 128+ Mb RAM. +На 64 Mb без swap будут проблемы с листами РКН. Если у вас только 64 Mb, и вы хотите листы РКН, подключите swap. +32 Mb для современных версий OpenWrt - конфигурация на грани живучести. Возможны хаотические падения процессов в oom. +Работа с листами РКН невозможна в принципе. diff --git a/docs/manual_setup.txt b/docs/manual_setup.txt deleted file mode 100644 index 5dbdcc0..0000000 --- a/docs/manual_setup.txt +++ /dev/null @@ -1,282 +0,0 @@ -Пример ручной установки на debian-подобную систему --------------------------------------------------- - -На debian основано большое количество дистрибутивов linux, включая ubuntu. -Здесь рассматриваются прежде всего Debian 8+ и Ubuntu 16+. -Но с большой вероятностью может сработать и на производных от них. -Главное условие - наличие systemd, apt и нескольких стандартных пакетов в репозитории. - -Установить пакеты : - apt-get update - apt-get install ipset curl dnsutils git - -Если хотите использовать nftables, то нужен пакет nftables, а ipset не обязателен. - -Скопировать директорию zapret в /opt или скачать через git : - cd /opt - git clone --depth 1 https://github.com/bol-van/zapret - -Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики. - /opt/zapret/install_bin.sh -АЛЬТЕРНАТИВА : make -C /opt/zapret. Получите динамические бинарики под вашу ось. -Для сборки требуются dev пакеты : zlib1g-dev libcap-dev libnetfilter-queue-dev - -Создать конфиг по умолчанию : - cp /opt/zapret/config.default /opt/zapret/config - -Настроить параметры согласно разделу "Выбор параметров". - -Создать user листы по умолчанию : - cp /opt/zapret/ipset/zapret-hosts-user-exclude.txt.default /opt/zapret/ipset/zapret-hosts-user-exclude.txt - echo nonexistent.domain >/opt/zapret/ipset/zapret-hosts-user.txt - touch /opt/zapret/ipset/zapret-hosts-user-ipban.txt - -Создать ссылку на service unit в systemd : - ln -fs /opt/zapret/init.d/systemd/zapret.service /lib/systemd/system - -Удалить старые листы, если они были созданы ранее : - /opt/zapret/ipset/clear_lists.sh -По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены. -Выполнить скрипт обновления листа : - /opt/zapret/ipset/get_config.sh -Настроить таймер systemd для обновления листа : - ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /lib/systemd/system - ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /lib/systemd/system - -Принять изменения в systemd : - systemctl daemon-reload - -Включить автозапуск службы : - systemctl enable zapret - -Включить таймер обновления листа : - systemctl enable zapret-list-update.timer - -Запустить службу : - systemctl start zapret - -Шпаргалка по управлению службой и таймером : - -enable auto start : systemctl enable zapret -disable auto start : systemctl disable zapret -start : systemctl start zapret -stop : systemctl stop zapret -status, output messages : systemctl status zapret -timer info : systemctl list-timer -delete service : systemctl disable zapret ; rm /lib/systemd/system/zapret.service -delete timer : systemctl disable zapret-list-update.timer ; rm /lib/systemd/system/zapret-list-update.* - -Centos 7+, Fedora ------------------ - -Centos с 7 версии и более-менее новые федоры построены на systemd. -В качестве пакетного менеджера используется yum. - -Установить пакеты : - yum install -y curl ipset dnsutils git - -Далее все аналогично debian. - -OpenSUSE --------- - -Новые OpenSUSE основаны на systemd и менеджере пакетов zypper. - -Установить пакеты : - zypper --non-interactive install curl ipset - -Далее все аналогично debian, кроме расположения systemd. -В opensuse он находится не в /lib/systemd, а в /usr/lib/systemd. -Правильные команды будут : - - ln -fs /opt/zapret/init.d/systemd/zapret.service /usr/lib/systemd/system - ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /usr/lib/systemd/system - ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /usr/lib/systemd/system - -Arch linux ----------- - -Построен на базе systemd. - -Установить пакеты : - pacman -Syy - pacman --noconfirm -S ipset curl - -Далее все аналогично debian. - -Gentoo ------- - -Эта система использует OpenRC - улучшенную версию sysvinit. -Установка пакетов производится командой : emerge -Пакеты собираются из исходников. - -Требуются все те же ipset, curl, git для скачивания с github. -git и curl по умолчанию могут присутствовать, ipset отсутствует. - - emerge ipset - -Настроить параметры согласно разделу "Выбор параметров". - -Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики. - /opt/zapret/install_bin.sh -АЛЬТЕРНАТИВА : make -C /opt/zapret. Получите динамические бинарики под вашу ось. - -Удалить старые листы, если они были созданы ранее : - /opt/zapret/ipset/clear_lists.sh -По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены. -Выполнить скрипт обновления листа : - /opt/zapret/ipset/get_config.sh -Зашедулить обновление листа : - crontab -e - Создать строчку "0 12 */2 * * /opt/zapret/ipset/get_config.sh" - -Подключить init скрипт : - - ln -fs /opt/zapret/init.d/openrc/zapret /etc/init.d - rc-update add zapret - -Запустить службу : - - rc-service zapret start - -Шпаргалка по управлению службой : - -enable auto start : rc-update add zapret -disable auto start : rc-update del zapret -start : rc-service zapret start -stop : rc-service zapret stop - - - -Ручная установка на openwrt/LEDE 15.xx-21.xx --------------------------------------------- - -!!! Данная инструкция написана для систем, основанных на iptables+firewall3 -!!! В новых версиях openwrt переходит на nftables+firewall4, инструкция неприменима. Пользуйтесь install_easy.sh - -Установить дополнительные пакеты : -opkg update -opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ipset curl -(ipv6) opkg install ip6tables-mod-nat -(опционально) opkg install gzip -(опционально) opkg install coreutils-sort - -ЭКОНОМИЯ МЕСТА : - -gzip от busybox в разы медленней полноценного варианта. gzip используется скриптами получения листов. -sort от busybox медленней полноценного варианта и жрет намного больше памяти. sort используется скриптами получения листов. -iptables-mod-nfqueue можно выкинуть, если не будем пользоваться nfqws -curl можно выкинуть, если для получения ip листа будет использоваться только get_user.sh - -Самая главная трудность - скомпилировать программы на C. Это можно сделать на linux x64 при помощи SDK, который -можно скачать с официального сайта openwrt или LEDE. Но процесс кросс компиляции - это всегда сложности. -Недостаточно запустить make как на традиционной linux системе. -Поэтому в binaries имеются готовые статические бинарики для всех самых распространенных архитектур. -Статическая сборка означает, что бинарик не зависит от типа libc (glibc, uclibc или musl) и наличия установленных so. -Его можно использовать сразу. Лишь бы подходил тип CPU. У ARM и MIPS есть несколько версий. -Скорее всего найдется рабочий вариант. Если нет - вам придется собирать самостоятельно. -Для всех поддерживаемых архитектур бинарики запакованы upx. На текущий момент все, кроме mips64. - -Скопировать директорию "zapret" в /opt на роутер. - -Если места достаточно, самый простой способ : - opkg update - opkg install git-http - mkdir /opt - cd /opt - git clone --depth 1 https://github.com/bol-van/zapret - -Если места немного : - opkg update - opkg install openssh-sftp-server unzip - ifconfig br-lan -Скачать на комп с github zip архив кнопкой "Clone or download"->Download ZIP -Скопировать средствами sftp zip архив на роутер в /tmp. - mkdir /opt - cd /opt - unzip /tmp/zapret-master.zip - mv zapret-master zapret - rm /tmp/zapret-master.zip - -Если места совсем мало : -На linux системе скачать и распаковать zapret. Оставить необходимый минимум файлов. -Запаковать в архив zapret.tar.gz. - nc -l -p 1111 1111 >zapret.tar.gz - -Не стоит работать с распакованной версией zapret на windows. Потеряются ссылки и chmod. - -Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики. - /opt/zapret/install_bin.sh - -Создать ссылку на скрипт запуска : - ln -fs /opt/zapret/init.d/openwrt/zapret /etc/init.d -Создать ссылку на скрипт события поднятия интерфейса : - ln -fs /opt/zapret/init.d/openwrt/90-zapret /etc/hotplug.d/iface - -Создать конфиг по умолчанию : - cp /opt/zapret/config.default /opt/zapret/config - -Настроить параметры согласно разделу "Выбор параметров". - -Создать user листы по умолчанию : - cp /opt/zapret/ipset/zapret-hosts-user-exclude.txt.default /opt/zapret/ipset/zapret-hosts-user-exclude.txt - echo nonexistent.domain >/opt/zapret/ipset/zapret-hosts-user.txt - touch /opt/zapret/ipset/zapret-hosts-user-ipban.txt - -Удалить старые листы, если они были созданы ранее : - /opt/zapret/ipset/clear_lists.sh -По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены. -Выполнить скрипт обновления листа : - /opt/zapret/ipset/get_config.sh -Зашедулить обновление листа : - crontab -e - Создать строчку "0 12 */2 * * /opt/zapret/ipset/get_config.sh" - -Включить автозапуск службы и запустить ее : - /etc/init.d/zapret enable - /etc/init.d/zapret start -ПРИМЕЧАНИЕ : на этапе старта системы интерфейсы еще не подняты. в некоторых случаях невозможно правильно -сформировать параметры запуска демонов, не зная имя физического интерфейса LAN. -Cкрипт из /etc/hotplug.d/iface перезапустит демоны по событию поднятия LAN. - -Создать ссылку на firewall include : - ln -fs /opt/zapret/init.d/openwrt/firewall.zapret /etc/firewall.zapret -Проверить была ли создана ранее запись о firewall include : - uci show firewall | grep firewall.zapret -Если firewall.zapret нет, значит добавить : - uci add firewall include - uci set firewall.@include[-1].path="/etc/firewall.zapret" - uci set firewall.@include[-1].reload="1" - uci commit firewall -Проверить не включен ли flow offload : - uci show firewall.@defaults[0] -Если flow_offloading=1 или flow_offloading_hw=1 , - uci set firewall.@defaults[0].flow_offloading=0 - uci set firewall.@defaults[0].flow_offloading_hw=0 - uci commit firewall -Перезапустить фаервол : - fw3 restart - -Посмотреть через iptables -nL, ip6tables -nL или через luci вкладку "firewall" появились ли нужные правила. - -ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталоги -ipset, common, файл config, init.d/openwrt. -Далее нужно создать подкаталоги с реально используемыми бинариками (ip2net, mdig, tpws, nfq) -и скопировать туда из binaries рабочие executables. - -ЕСЛИ ВСЕ ПЛОХО С МЕСТОМ : откажитесь от работы со списком РКН. используйте только get_user.sh - -ЕСЛИ СОВСЕМ ВСЕ УЖАСНО С МЕСТОМ : берете tpws и делаете все своими руками. поднятие iptables, автостарт бинарика. -С некоторых версий скрипты запуска zapret без ipset не работают (он требуется для ip exclude) - -СОВЕТ : Покупайте только роутеры с USB. В USB можно воткнуть флэшку и вынести на нее корневую файловую систему -или использовать ее в качестве оверлея. Не надо мучать себя, запихивая незапихиваемое в 8 мб встроенной флэшки. -Для комфортной работы с zapret нужен роутер с 16 Mb встроенной памяти или USB разъемом и 128+ Mb RAM. -На 64 Mb без swap будут проблемы с листами РКН. Если у вас только 64 Mb, и вы хотите листы РКН, подключите swap. -32 Mb для современных версий openwrt - конфигурация на грани живучести. Возможны хаотические падения процессов в oom. -Работа с листами РКН невозможна в принципе. - diff --git a/docs/nftables.txt b/docs/nftables.md similarity index 72% rename from docs/nftables.txt rename to docs/nftables.md index 4acbb59..3b0ed43 100644 --- a/docs/nftables.txt +++ b/docs/nftables.md @@ -1,32 +1,32 @@ -nftables test cheat sheet -simplified rules to test nfqws and tpws +`nftables` test cheat sheet. Simplified rules to test `nfqws` and `tpws`. +For DNAT: -For DNAT : - -# run tpws as user "tpws". its required to avoid loops. - +```sh +# run tpws as user "tpws". its required to avoid loops nft delete table inet ztest nft create table inet ztest nft add chain inet ztest pre "{type nat hook prerouting priority dstnat;}" nft add rule inet ztest pre tcp dport "{80,443}" redirect to :988 nft add chain inet ztest out "{type nat hook output priority -100;}" nft add rule inet ztest out tcp dport "{80,443}" skuid != tpws redirect to :988 +``` +For `dpi-desync` attack: -For dpi desync attack : - +```sh nft delete table inet ztest nft create table inet ztest nft add chain inet ztest post "{type filter hook postrouting priority mangle;}" nft add rule inet ztest post tcp dport "{80,443}" ct original packets 1-12 queue num 200 bypass nft add rule inet ztest post udp dport 443 ct original packets 1-4 queue num 200 bypass -# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI -sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 +# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by Russian DPI + +sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 nft add chain inet ztest pre "{type filter hook prerouting priority filter;}" nft add rule inet ztest pre tcp sport "{80,443}" ct reply packets 1-4 queue num 200 bypass +``` - -show rules : nft list table inet ztest -delete table : nft delete table inet ztest +* show rules: `nft list table inet ztest`, +* delete table: `nft delete table inet ztest` diff --git a/docs/nftables_notes.md b/docs/nftables_notes.md new file mode 100644 index 0000000..bcf1c0a --- /dev/null +++ b/docs/nftables_notes.md @@ -0,0 +1,142 @@ +- [Вступление](#вступление) +- [Минусы](#минусы) + - [Главная боль №1](#главная-боль-1) + - [Боль №2](#боль-2) + - [Боль №3](#боль-3) + - [Боль №4](#боль-4) +- [Плюсы](#плюсы) + - [Плюс №1, главный](#плюс-1-главный) + - [Плюс №2](#плюс-2) + - [Плюс №3](#плюс-3) + - [Плюс №4](#плюс-4) + - [Плюс №5](#плюс-5) +- [Выводы](#выводы) + +# Вступление + +`nftables` - это технология, пришедшая на замену `iptables`. +В ней собрали все, что относилось к различным `iptables`. А их немало. `iptables`, `ip6tables`, `ebtables`, `arptables`, `ipset`. +Весь код из разрозненных, но похожих компонент, собрали в одно целое с единым синтаксисом. +Добавили различные конструкции языка, позволяющие писать правила более лаконично, не повторяя одни и те же команды с небольшими различиями. +На `nftables` можно сделать почти все, что можно было сделать на `iptables`. Есть то, что можно сделать на `nftables`, но нельзя на `iptables`. +Есть и наоборот. + +# Минусы + +К сожалению, не обошлось и без боли. + +## Главная боль №1 + +Очень серьезная, актуальная для OpenWrt, и решения не видно. + +ipset-ы позволяли загонять пересекающиеся интервалы IP адресов или подсетей. +nftables sets это не позволяют. Любое пересечение вызывает ошибку. +Есть auto-merge, но это работает только в user mode в процессе `nft`, при условии, что весь блок адресов загоняется одной командой +и нет пересечений с уже имеющимся контентом в set. +Это не было бы критической проблемой, поскольку скрипты `zapret` и так загоняют ipset целиком. +Проблема в катастрофическом расходе памяти при операции загона больших интервальных листов, то есть с подсетями и диапазонами. +Чтобы загнать 100000 IPv4 записей, едва хватает 300 Mb памяти устройства. +При успехе операции в ядре список столько не занимает, но суть дела это не меняет. +Для традиционных Linux систем это не проблема, но почти все роутеры загнутся. +Приемлемого решения не просматривается. +Сделать записи непересекающимися в листах - задача непростая. +Потребуется переписать алгоритм auto-merge из `nft`, но с пониженным расходом памяти. +Загонять записи по одному отдельными вызовами `nft`, игнорируя ошибки, займет вечность. +Загонять блоком отдельных команд, игнорируя ошибки, - `nft` такого не умеет. Похоже, при любой ошибке происходит откат всего скрипта. +К тому же при таком подходе будут неточности в итоговом результате. +Swap позволяет немного сгладить проблему, но лишь незначительно. +Скажем, если вдруг list загоняется без ошибок с 300 Mb памяти и с падением на 256 MB, то swap спасает. +Если памяти становится 200 MB, то swap уже не спасет. +Все равно вызывается OOM killer, заодно убивая и другие процессы, кроме `nft`, а это уже совсем плохо. Может быть убито что-то важное. + +## Боль №2 + +Не смертельная, но тоже не айс. + +Какие-то нерациональные алгоритмы разбора таблиц в `nft`. +Например, есть 1 большой set на 100000 элементов и 1 маленький на 2 элемента. +Чтобы просто пролистать мелкий set или добавить туда еще что-то `nft` будет мусолить несколько секунд. +Что он делает за это время? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь? +В какой-то мере удается это сгладить, объединяя несколько команд в единый скрипт. + +## Боль №3 + +Система `nftables` построена на виртуальной машине. Правила, которые вы пишите, переводятся в псевдокод VM. +Чтобы потом их показать, `nft` декомпилирует код и переводит в читаемый язык. +Это довольно сложно, и регулярно случаются баги, связанные с неверным отображением. + +Кроме этого, часто встречаются и баги парсера. +Например, все версии `nft` вплоть до 1.0.1 имеют баг, который не разрешает названия интерфейсов в кавычках в определении flowtable. +Без кавычек нельзя вставить интерфейсы, имя которых начинается с цифры. +OpenWrt решает эту проблему отдельным патчем в snapshot версии, но на традиционных системах и в OpenWrt 21.x- его нет. +Почему бы не наплевать на интерфейсы, начинающиеся с цифры? Потому что для OpenWrt 6to4-6to4, 6in4-he-net - обычное явление. +На текущий момент этой проблемы в OpenWrt уже нет, если использовать актуальную версию. + +Но тем не менее, хоть `nft` и давно перешел отметку 1.0, всякая мелочь, особенно на не совсем стандартных правилах, регулярно всплывает. +Потому чем новее у вас будет версия `nft`, тем больше там выловлено проблем. +Здесь обновления важны, чтобы потом не мучиться из-за давно исправленного велосипеда. + +## Боль №4 + +Невозможно, не копаясь в других таблицах и хуках, ничего не зная об их содержании, предотвратить DROP или REJECT. +Нельзя написать такое правило, которое что-то важное ACCEPT нет, игнорируя остальные хуки во всех таблицах. +Если у вас есть какой-то фаервол, и он что-то дропает, то как от этого отказаться, если надо временно что-то принять? +Это особенность `netfilter`, он так работает, но в `iptables` есть лишь стандартные таблицы с их хуками, куда можно вставить ACCEPT. +Здесь хуков может быть сколько угодно в каких угодно таблицах. +Эта проблема частично ломает кайф от независимого управления таблицами. + +# Плюсы + +## Плюс №1, главный + +`iptables` хороши, когда ими пользуется кто-то один. Иначе это проходной двор. +Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу +и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное. +Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в `iptables`, и это очень сильно портит жизнь. +У `iptables` есть предопределенный набор хуков `netfilter` с фиксированным приоритетом. +В `nftables` хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах. +Система управления фаерволом может работать в одной таблице (`fw4` в случае OpenWrt) и не трогать все остальное. +`zapret` может работать в другой таблице и не трогать систему управления фаерволом. Они друг другу не мешают. +Это снимает множество боли. +Но есть и исключение. `nfset`-ы - аналог `ipset`-ов - нельзя использовать из другой таблицы. +Потому если вам нужен `ipset`, создаваемый `zapret` скриптами, вам понадобится писать правила в той же таблице. +Но нет никакой необходимости влезать в цепочки `zapret`. +Создаете свои цепочки и хуки и делаете в них что угодно. + +## Плюс №2 + +Возможность выбора приоритета хука позволяет легко решить проблему хаотической и принудительной дефрагментацией L3 IPv6, без танцев с загрузкой модулей ядра со специальными параметрами или перекомпиляцией `nftables-nft`. +Это же позволяет перехватить трафик после SNAT/MASQUERADE, что на `iptables` невозможно. +Атаки на проходящий трафик, ломающие NAT, крайне затруднены на `iptables`. + +## Плюс №3 + +Наличие множеств (anonymous/named sets) позволяет не писать кучу однообразных правил там, где в `iptables` их пришлось бы написать. + +## Плюс №4 + +Если у вас есть `nftables`, то там наверняка есть уже все или почти все. +Нет кучи разных модулей ядра и .so плагинов для `iptables` user-mode процесса. +Отдельные модули ядра есть, но их меньше, чем в `iptables`, и OpenWrt их делит на меньшее число пакетов, большинство из которых +и так ставятся по умолчанию. user-mode процесс `nft` и вовсе неделим. EXE-шник + lib. + +## Плюс №5 + +Пишут, что `nftables` работают быстрее. Но это не точно и зависит от много чего. +В целом - чем меньше правил, тем выше скорость. Но в `nftables` правил можно писать меньше, значит скорость тоже может быть выше. +У разработчиков есть идея перевести backend `nftables` на BPF, а это наверняка будет существенно быстрее. + +# Выводы + +Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров. +А ipset-ы к `nftables` не прикрутить. +Зато есть возможность задействовать более продвинутые атаки, конфликтующие с NAT, которые на `iptables` могут быть невозможны. +Делать нечего. Openwrt отошел от `iptables`. С этим придется как-то жить. +Поэтому пришлось сделать для OpenWrt поддержку и `iptables`, и `nftables` (только с версии OpenWrt 21.xx, в более старых будут проблемы). +`iptables` можно задействовать на любой OpenWrt версии. +Если используется `fw3`, применяется старый механизм интеграции в `fw3`. +Если он не используется, то правилами `iptables` управляем как в традиционных Linux системах - то есть с возможностью +запуска и остановки, а скрипт запуска вносит в том числе и правила `iptables`. + +На новых OpenWrt возможно снести `nftables` и `firewall4` и установить `firewall3` и `iptables`. +Если вам никак без больших IP листов на слабой системе, это может быть единственным спасением. diff --git a/docs/nftables_notes.txt b/docs/nftables_notes.txt deleted file mode 100644 index 75fa845..0000000 --- a/docs/nftables_notes.txt +++ /dev/null @@ -1,120 +0,0 @@ -nftables - это технология, пришедшая на замену iptables. -В ней собрали все, что относилось к различным iptables. А их немало. iptables, ip6tables, ebtables, arptables, ipset. -Весь код из разрозненных, но похожих компонент, собрали в одно целое с единым синтаксисом. -Добавили различные конструкции языка, позволяющие писать правила более лаконично, не повторяя одни и те же команды с небольшими различиями. -На nftables можно сделать почти все, что можно было сделать на iptables. Есть то, что можно сделать на nftables, но нельзя на iptables. -Есть и наоборот. - -К сожалению, не обошлось и без боли. - -Главная боль N1. Очень серьезная, актуальная для openwrt, и решения не видно. - -ipset-ы позволяли загонять пересекающиеся интервалы ip адресов или подсетей. -nftables sets это не позволяют. Любое пересечение вызывает ошибку. -Есть auto-merge, но это работает только в user mode в процессе nft, при условии, что весь блок адресов загоняется одной командой -и нет пересечений с уже имеющимся контентом в set. -Это не было бы критической проблемой, поскольку скрипты zapret и так загоняют ipset целиком. -Проблема в катастрофическом расходе памяти при операции загона больших интервальных листов, то есть с подсетями и диапазонами. -Чтобы загнать 100000 ipv4 записей, едва хватает 300 Mb памяти устройства. -При успехе операции в ядре список столько не занимает, но суть дела это не меняет. -Для традиционных linux систем это не проблема, но почти все роутеры загнутся. -Приемлемого решения не просматривается. -Сделать записи непересекающимися в листах - задача непростая. Потребуется переписать алгоритм auto-merge из nft, -но с пониженным расходом памяти. -Загонять записи по одному отдельными вызовами nft, игнорируя ошибки, займет вечность. -Загонять блоком отдельных команд, игнорируя ошибки, - nft такого не умеет. Похоже, при любой ошибке происходит откат всего скрипта. -К тому же при таком подходе будут неточности в итоговом результате. -Swap позволяет немного сгладить проблему, но лишь незначительно. -Скажем, если вдруг list загоняется без ошибок с 300 Mb памяти и с падением на 256 Mb, то swap спасает. -Если памяти становится 200 Mb, то swap уже не спасет. Все равно вызывается OOM killer, заодно убивая и другие процессы, кроме nft, -а это уже совсем плохо. Может быть убито что-то важное. - -Боль N2, не смертельная, но тоже не айс. - -Какие-то нерациональные алгоритмы разбора таблиц в nft. -Например, есть 1 большой set на 100000 элементов и 1 маленький на 2 элемента. -Чтобы просто пролистать мелкий set или добавить туда еще что-то nft будет мусолить несколько секунд. -Что он делает за это время ? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь ? -В какой-то мере удается это сгладить, обьединяя несколько команд в единый скрипт. - -Боль N3 - -Система nftables построена на виртуальной машине. Правила, которые вы пишите, переводятся в псевдокод VM. -Чтобы потом их показать , nft декомпилирует код и переводит в читаемый язык. -Это довольно сложно, и регулярно случаются баги, связанные с неверным отображением. - -Кроме этого, часто встречаются и баги парсера. -Например, все версии nft вплоть до 1.0.1 имеют баг, который не разрешает названия интерфейсов в кавычках в -определении flowtable. Без кавычек нельзя вставить интерфейсы , имя которых начинается с цифры. -OpenWRT решает эту проблему отдельным патчем в snapshot версии, но на традиционных системах и в openwrt 21.x- его нет. -Почему бы не наплевать на интерфейсы, начинающиеся с цифры ? Потому что для openwrt 6to4-6to4, 6in4-he-net - обычное явление. -На текущий момент этой проблемы в openwrt уже нет, если использовать актуальную версию. - -Но тем не менее, хоть nft и давно перешел отметку 1.0, всякая мелочь, особенно на не совсем стандартных правилах, -регулярно всплывает. Потому чем новее у вас будет версия nft, тем больше там выловлено проблем. -Здесь обновления важны, чтобы потом не мучаться из-за давно исправленного велосипеда. - -Боль N4 - -Невозможно , не копаясь в других таблицах и хуках, ничего не зная об их содержании, предотвратить DROP или REJECT. -Нельзя написать такое правило, которое что-то важное ACCEPTнет, игнорируя остальные хуки во всех таблицах. -Если у вас есть какой-то фаервол, и он что-то дропает, то как от этого отказаться, если надо временно что-то принять ? -Это особенность netfilter, он так работает, но в iptables есть лишь стандартные таблицы с их хуками, куда можно -вставить ACCEPT. Здесь хуков может быть сколько угодно в каких угодно таблицах. -Эта проблема частично ломает кайф от независимого управления таблицами. - - -Плюс N1, главный - -iptables хороши, когда ими пользуется кто-то один. Иначе это проходной двор. -Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу -и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное. -Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в iptables, и это очень сильно портит жизнь. -У iptables есть предопределенный набор хуков netfilter с фиксированным приоритетом. -В nftables хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах. -Система управления фаерволом может работать в одной таблице (fw4 в случае openwrt) и не трогать все остальное. -zapret может работать в другой таблице и не трогать систему управления фаерволом. Они друг другу не мешают. -Это снимает множество боли. -Но есть и исключение. nfset-ы - аналог ipset-ов - нельзя использовать из другой таблицы. Потому если вам нужен ipset, -создаваемый zapret скриптами, вам понадобится писать правила в той же таблице. Но нет никакой необходимости влезать в цепочки zapret. -Создаете свои цепочки и хуки и делаете в них что угодно. - -Плюс N2 - -Возможность выбора приоритета хука позволяет легко решить проблему хаотической и принудительной дефрагментацией L3 ipv6, -без танцев с загрузкой модулей ядра со специальными параметрами или перекомпиляцией nftables-nft. -Это же позволяет перехватить трафик после SNAT/MASQUERADE, что на iptables невозможно. -Атаки на проходящий трафик, ломающие NAT, крайне затруднены на iptables. - -Плюс N3 - -Наличие множеств (anonymous/named sets) позволяет не писать кучу однообразных правил там, где в iptables их пришлось бы написать. - -Плюс N4 - -Если у вас есть nftables, то там наверняка есть уже все или почти все. -Нет кучи разных модулей ядра и .so плагинов для iptables user-mode процесса. -Отдельные модули ядра есть, но их меньше, чем в iptables, и openwrt их делит на меньшее число пакетов, большинство из которых -и так ставятся по умолчанию. user-mode процесс nft и вовсе неделим. EXE-шник + lib. - -Плюс N5 - -Пишут, что nftables работают быстрее. Но это не точно и зависит от много чего. -В целом - чем меньше правил, тем выше скорость. Но в nftables правил можно писать меньше, значит скрость тоже может быть выше. -У разработчиков есть идея перевести backend nftables на BPF, а это наверняка будет существенно быстрее. - - -Выводы - -Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров. -А ipset-ы к nftables не прикрутить. -Зато есть возможность задействовать более продвинутые атаки, конфликтующие с NAT, которые на iptables могут быть невозможны. -Делать нечего. Openwrt отошел от iptables. С этим придется как-то жить. -Поэтому пришлось сделать для openwrt поддержку и iptables, и nftables (только с версии openwrt 21.xx, в более старых будут проблемы). -iptables можно задействовать на любой openwrt версии. -Если используется fw3, применяется старый механизм интеграции в fw3. -Если он не используется, то правилами iptables управляем как в традиционных linux системах - то есть с возможностью -запуска и остановки, а скрипт запуска вносит в том числе и правила iptables. - -На новых openwrt возможно снести nftables и firewall4 и установить firewall3 и iptables. -Если вам никак без больших ip листов на слабой системе, это может быть единственным спасением. diff --git a/docs/quick_start.md b/docs/quick_start.md new file mode 100644 index 0000000..498ba03 --- /dev/null +++ b/docs/quick_start.md @@ -0,0 +1,134 @@ +Специально для тех, кто хочет побыстрее начать, но не хочет слишком углубляться в простыню `readme.md`. + +Предупреждение: не пишите в Issue вопросы типа: "как скопировать файл", "как скачать", "как запустить", ... +То есть все, что касается базовых навыков обращения с ОС Linux. Эти вопросы буду закрывать сразу. +Если у вас подобные вопросы возникают, рекомендую не использовать данный софт или искать помощь где-то в другом месте. +То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы все заработало, и совсем не хочет читать и изучать. +Увы, такое не подвезли и не подвезут. Ищите другие более простые методы обхода. Этот метод не для рядового пользователя. + +Обход DPI является хакерской методикой. +Под этим словом понимается метод, которому сопротивляется окружающая среда, которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах, требуется настройка под специфические условия у вашего провайдера. +Условия могут меняться со временем, и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации. +Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать. +Могут и сломаться отдельные незаблокированные ресурсы. +Поэтому очень желательно иметь знания в области сетей, чтобы иметь возможность проанализировать техническую ситуацию. +Не будет лишним иметь обходные каналы проксирования трафика на случай, если обход DPI не помогает. + +Будем считать, что у вас есть система на базе традиционного Linux или OpenWrt. +Если у вас традиционный Linux - задача обойти блокировки только на этой системе, если OpenWrt - обойти блокировки для подключенных устройств. +Это наиболее распространенный случай. + +1) Чтобы процедура установки сработала в штатном режиме на OpenWrt, нужно рассчитывать на свободное место около 1-2 Mb +для установки самого `zapret` и необходимых дополнительных пакетов. +Если места мало и нет возможности его увеличить за счет extroot, возможно, придется отказаться от варианта простой установки и прикручивать в ручном режиме без имеющихся скриптов запуска, +либо попробовать засунуть требуемые `zapret` дополнительные пакеты в сжатый образ squashfs с помощью image builder и перешить этим вариантом роутер. +См. `docs/manual_setup.md`, `docs/readme.md`. + +2) Скачайте `.zip` архив проекта с GitHub в `/tmp`, распакуйте его там, либо клонируйте проект: `git clone --depth 1 https://github.com/bol-van/zapret`. + +3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам `zapret`. +Гарантированно уберет `zapret` скрипт `uninstall_easy.sh`. + +4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. NAT не подходит. + +5) Выполните однократные действия по установке требуемых пакетов в ОС и настройке бинарников правильной архитектуры + +```sh +install_bin.sh +install_prereq.sh +``` + +Вас могут спросить о типе фаервола (`iptables`/`nftables`) и использовании IPv6. Это нужно для установки +правильных пакетов в ОС, чтобы не устанавливать лишнее. + +6) Запустите `blockcheck.sh`. + +`blockcheck.sh` в начале проверяет DNS. Если выводятся сообщения о подмене адресов, то первым делом нужно решить эту проблему, иначе ничего не будет работать. Решение проблемы DNS выходит за рамки проекта. +Обычно она решается либо заменой DNS серверов от провайдера на публичные (1.1.1.1, 8.8.8.8), либо в случае перехвата провайдером обращений к сторонним серверам - через специальные средства шифрования DNS запросов, такие как DNSCrypt, DoT, DoH. + +Еще один эффективный вариант - использовать ресолвер от Yandex 77.88.8.88 на нестандартном порту 1253. +Многие провайдеры не анализируют обращения к DNS на нестандартных портах. + +Проверить работает ли этот вариант можно так : + +```sh +dig -p 53 @77.88.8.88 rutracker.org +dig -p 1253 @77.88.8.88 rutracker.org +``` + +Если DNS действительно подменяется, и ответ на эти 2 команды разный, значит метод вероятно работает. + +В OpenWrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp` таким способом: + +``` +config dnsmasq + ............. + list server '77.88.8.88#1253' +``` + +Если настройки IP и DNS получаются автоматически от провайдера, в `/etc/config/network` +найдите секцию интерфейса `wan` и сделайте так: + +``` +config interface 'wan' + ............. + option peerdns '0' +``` + +```sh +/etc/init.d/network restart +/etc/init.d/dnsmasq restart +``` + +Если это не подходит, можно перенаправлять обращения на UDP и TCP порты 53 вашего DNS сервера на 77.88.8.88:1253 средствами `iptables`/`nftables`. В `/etc/resolv.conf` нельзя прописать DNS на нестандартном порту. + +7) `blockcheck` позволяет выявить рабочую стратегию обхода блокировок +По результатам `blockcheck` нужно понять какой вариант будете использовать: `nfqws` или `tpws`. +И запомнить найденные стратегии. + +Следует понимать, что `blockcheck` проверяет доступность только конкретного домена, который вы вводите в начале. +Вероятно, все остальные домены блокированы подобным образом, но не факт. +В большинстве случаев можно объединить несколько стратегий в одну универсальную, но для этого необходимо понимать +"что там за буковки". Если вы в сетях слабо разбираетесь, это не для вас. В противном случае читайте `readme.md`. +`zapret` не может пробить блокировку по IP адресу. Для проверки нескольких доменов вводите их через пробел. + +Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов с различной длиной по ХОПам, с DPI на разных хопах. +Приходится преодолевать целый зоопарк DPI, которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера). +`blockcheck` не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки. +В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях. +Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель +`--dpi-desync-fooling`, чтобы не сломать сайты на более коротких дистанциях. +`md5sig` наиболее совместим, но работает только на Linux серверах. +`badseq` может работать только на HTTPS и не работать на HTTP. +`badsum` и вовсе перестал работать на многих провайдерах с некоторых пор, видимо включили проверку чексумм на DPI. +Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL с каждым из этих ограничителей. + +При использовании `autottl` следует протестировать как можно больше разных доменов. +Эта техника может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах она стабильна, на третьих полный хаос, и проще отказаться. + +8) Запустите `install_easy.sh`. + +Выберите `nfqws` или `tpws`, затем согласитесь на редактирование параметров. +Откроется редактор, куда впишите найденные стратегии. +Для `nfqws` отдельно настраиваются стратегии на HTTP и HTTPS для IPv4 и IPv6. +То есть по максимуму 4 разных варианта. +`NFQWS_OPT_DESYNC` - это общая установка, которая применяется, если какой-либо уточняющий параметр не задан +`NFQWS_OPT_DESYNC_HTTP` и `NFQWS_OPT_DESYNC_HTTPS` заменяют стратегию для HTTP и HTTPS. +Если у вас включен IPv6, то они так же будут применены и к IPv6. Если для IPv6 нужна другая стратегия, то можно задать уточняющие параметры `NFQWS_OPT_DESYNC_HTTP6` и `NFQWS_OPT_DESYNC_HTTPS6`. +Если стратегии для IPv4 и IPv6 отличаются лишь TTL, то в целях экономии ресурсов роутера (меньше процессов `nfqws`) следует отказаться от использования специфических для IPv6 установок. Вместо них использовать параметры +`--dpi-desync-ttl` и `--dpi-desync-ttl6` в общих установках. Таким способом можно заставить один процесс `nfqws` обрабатывать трафик на IPv4 и на IPv6 с разным TTL. + +Важным вопросом является вопрос о поддержке HTTP keep alive. +Отвечайте `N`. Если вдруг на HTTP сайтах будут хаотические сбои типа то загружается, то заглушка или сброс, попробуйте включить поддержку keep alive. +Но просто "на всякий случай" не включайте - это увеличит нагрузку на роутер. + +Если это не помогает, или хаотичное поведение наблюдается и на HTTPS, то еще раз прогоните `blockcheck` с установленным числом попыток проверки не менее 5. +Возможно, ваш провайдер использует балансировку нагрузки, где на разных путях установлен разный DPI. + +9) На все остальные вопросы `install_easy.sh` отвечайте согласно выводимой аннотации. + +10) Если ломаются отдельные незаблокированные ресурсы, следует вносить их в исключения, либо пользоваться ограничивающим ipset или хост листом. Читайте основной талмуд `readme.md` ради подробностей. + +Это минимальная инструкция, чтобы сориентироваться с чего начать. Однако, это - не панацея. +В некоторых случаях вы не обойдетесь без знаний и основного "талмуда". +Подробности и полное техническое описание расписаны в `readme.md`. diff --git a/docs/quick_start.txt b/docs/quick_start.txt deleted file mode 100644 index 39dc2bd..0000000 --- a/docs/quick_start.txt +++ /dev/null @@ -1,137 +0,0 @@ -Специально для тех, кто хочет побыстрее начать, но не хочет слишком углубляться в простыню readme.txt. - -Предупреждение : не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как запустить", ... -То есть все , что касается базовых навыков обращения с ОС linux. Эти вопросы буду закрывать сразу. -Если у вас подобные вопросы возникают, рекомендую не использовать данный софт или искать помощь где-то в другом месте. -То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы все заработало, и совсем не хочет читать и изучать. -Увы, такое не подвезли и не подвезут. Ищите другие более простые методы обхода. Этот метод не для рядового пользователя. - -Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда, -которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах, -требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем, -и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации. -Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать. -Могут и сломаться отдельные незаблокированные ресурсы. -Поэтому очень желательно иметь знания в области сетей, чтобы иметь возможность проанализировать техническую ситуацию. -Не будет лишним иметь обходные каналы проксирования трафика на случай, если обход DPI не помогает. - -Будем считать, что у вас есть система на базе традиционного linux или openwrt. -Если у вас традиционный linux - задача обойти блокировки только на этой системе, если openwrt - обойти блокировки -для подключенных устройств. Это наиболее распространенный случай. - -1) Чтобы процедура установки сработала в штатном режиме на openwrt, нужно раcсчитывать на свободное место около 1-2 Mb -для установки самого zapret и необходимых дополнительных пакетов. -Если места мало и нет возможности его увеличить за счет extroot, возможно придется отказаться от варианта -простой установки и прикручивать в ручном режиме без имеющихся скриптов запуска, либо попробовать засунуть требуемые -zapret дополнительные пакеты в сжатый образ squashfs с помощью image builder и перешить этим вариантом роутер. -См docs/manual_setup.txt , docs/readme.txt . - -2) Скачайте zip архив проекта с github в /tmp, распакуйте его там, -либо клонируйте проект через : git clone --depth 1 https://github.com/bol-van/zapret - -3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret. -Гарантированно уберет zapret скрипт uninstall_easy.sh. - -4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит - -5) Выполните однократные действия по установке требуемых пакетов в ОС и настройке бинариков правильной архитектуры - -install_bin.sh -install_prereq.sh - -Вас могут спросить о типе фаервола (iptables/nftables) и использовании ipv6. Это нужно для установки -правильных пакетов в ОС, чтобы не устанавливать лишнее. - -6) Запустите blockcheck.sh. blockcheck.sh в начале проверяет DNS. Если выводятся сообщения о подмене адресов, то -первым делом нужно решить эту проблему, иначе ничего не будет работать. -Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов -от провайдера на публичные (1.1.1.1, 8.8.8.8), либо в случае перехвата провайдером обращений -к сторонним серверам - через специальные средства шифрования DNS запросов, такие как dnscrypt, DoT, DoH. - -Еще один эффективный вариант - использовать ресолвер от yandex 77.88.8.88 на нестандартном порту 1253. -Многие провайдеры не анализируют обращения к DNS на нестандартных портах. - -Проверить работает ли этот вариант можно так : - -dig -p 53 @77.88.8.88 rutracker.org -dig -p 1253 @77.88.8.88 rutracker.org - -Если DNS действительно подменяется, и ответ на эти 2 команды разный, значит метод вероятно работает. - -В openwrt DNS на нестандартном порту можно прописать в /etc/config/dhcp таким способом : - -config dnsmasq - ............. - list server '77.88.8.88#1253' - -Если настройки IP и DNS получаются автоматически от провайдера, в /etc/config/network -найдите секцию интерфейса 'wan' и сделайте так : - -config interface 'wan' - ............. - option peerdns '0' - -/etc/init.d/network restart -/etc/init.d/dnsmasq restart - -Если это не подходит, можно перенаправлять обращения на udp и tcp порты 53 вашего DNS сервера на 77.88.8.88:1253 средствами -iptables/nftables. В /etc/resolv.conf нельзя прописать DNS на нестандартном порту. - -7) blockcheck позволяет выявить рабочую стратегию обхода блокировок -По результатам blockcheck нужно понять какой вариант будете использовать : nfqws или tpws -И запомнить найденные стратегии. - -Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале. -Вероятно, все остальные домены блокированы подобным образом, но не факт. -В большинстве случаев можно обьединить несколько стратегий в одну универсальную, но для этого необходимо понимать -"что там за буковки". Если вы в сетях слабо разбираетесь, это не для вас. В противном случае читайте readme.txt. -zapret не может пробить блокировку по IP адресу -Для проверки нескольких доменов вводите их через пробел. - -Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов -с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI, -которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера). -blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки. -В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях. -Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель ---dpi-desync-fooling, чтобы не сломать сайты на более коротких дистанциях. -md5sig наиболее совместим, но работает только на linux серверах. -badseq может работать только на https и не работать на http. -badsum и вовсе перестал работать на многих провайдерах с некоторых пор, видимо включили проверку чексумм на DPI. -Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL -с каждым из этих ограничителей. - -При использовании autottl следует протестировать как можно больше разных доменов. Эта техника -может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах -она стабильна, на третьих полный хаос, и проще отказаться. - -8) Запустите install_easy.sh. -Выберите nfqws или tpws, затем согласитесь на редактирование параметров. -Откроется редактор, куда впишите найденные стратегии. -Для nfqws отдельно настраиваются стратегии на http и https для ipv4 и ipv6. -То есть по максимуму 4 разных варианта. -NFQWS_OPT_DESYNC - это общая установка, которая применяется, если какой-либо уточняющий параметр не задан -NFQWS_OPT_DESYNC_HTTP и NFQWS_OPT_DESYNC_HTTPS заменяют стратегию для http и https. -Если у вас включен ipv6, то они так же будут применены и к ipv6. Если для ipv6 нужна другая стратегия, -то можно задать уточняющие параметры NFQWS_OPT_DESYNC_HTTP6 и NFQWS_OPT_DESYNC_HTTPS6. -Если стратегии для ipv4 и ipv6 отличаются лишь ttl, то в целях экономии ресурсов роутера (меньше процессов nfqws) -следует отказаться от использования специфических для ipv6 установок. Вместо них использовать параметры ---dpi-desync-ttl и --dpi-desync-ttl6 в общих установках. Таким способом можно заставить один процесс nfqws -обрабатывать трафик на ipv4 и на ipv6 с разным ttl. - -Важным вопросом является вопрос о поддержке http keep alive. -Отвечайте N. Если вдруг на http сайтах будут хаотические сбои типа то загружается, то заглушка или сброс, -попробуйте включить поддержку keep alive. Но просто "на всякий случай" не включайте - это увеличит нагрузку на роутер. - -Если это не помогает, или хаотичное поведение наблюдается и на https, то еще раз прогоните blockcheck -с установленным числом попыток проверки не менее 5. Возможно, ваш провайдер использует балансировку нагрузки, -где на разных путях установлен разный DPI. - -9) На все остальные вопросы install_easy.sh отвечайте согласно выводимой аннонтации. - -10) Если ломаются отдельные незаблокированные ресурсы, следует вносить их в исключения, либо пользоваться ограничивающим -ipset или хост листом. Читайте основной талмуд readme.txt ради подробностей. - -Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея. -В некоторых случаях вы не обойдетесь без знаний и основного "талмуда". -Подробности и полное техническое описание расписаны в readme.txt diff --git a/docs/quick_start_windows.md b/docs/quick_start_windows.md new file mode 100644 index 0000000..07c1202 --- /dev/null +++ b/docs/quick_start_windows.md @@ -0,0 +1,117 @@ +- [Вступление](#вступление) +- [Самое простое решение](#самое-простое-решение) +- [Решение "как положено"](#решение-как-положено) + +# Вступление + +Специально для тех, кто хочет побыстрее начать, но не хочет слишком углубляться в простыню `readme.md`. + +Как обычно, компьютерная грамотность ложится полностью на вас. +Вы должны уметь работать с консолью Windows и иметь минимальные навыки обращения с командными файлами `.bat`, `.cmd`. +Если грамотность отсутствует и возникает куча "как" на базовых вещах - проходите мимо или ищите помощь в другом месте. + +Обход DPI является хакерской методикой. +Под этим словом понимается метод, которому сопротивляется окружающая среда, которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах, требуется настройка под специфические условия у вашего провайдера. +Условия могут меняться со временем, и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации. +Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать. +Могут и сломаться отдельные незаблокированные ресурсы. +Поэтому очень желательно иметь знания в области сетей, чтобы иметь возможность проанализировать техническую ситуацию. +Не будет лишним иметь обходные каналы проксирования трафика на случай, если обход DPI не помогает. + +Будем считать, что у вас есть Windows 7 или выше. Задача - обойти блокировки с самой системы. + +Есть решение самое простое, а есть "как положено". + +# Самое простое решение + +Совсем ничего не могу, все очень сложно, дайте мне таблетку. + +Скачайте и распакуйте [архив](https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip). +Запустите `zapret-winws/preset_russia.cmd` от имени администратора. +Возможно, заведется сразу. Этот вариант похож на `2_any_country.cmd` из [GoodbyeDPI](https://github.com/ValdikSS/GoodbyeDPI). + +То же самое с ограничителем по автоматически создаваемому хост-листу `preset_russia_autohostlist.cmd`. +Что такое `autohostlist` - читайте `readme.md`. Проще говоря, мы обходим только то, что долго и упорно не хочет открываться. +Сначала не будет, но надо пытаться много раз, и тогда сработает, а дальше будет всегда срабатывать. +Остальное не будет ломаться. Использовать только, если первый вариант тоже работает. + +Не помогла таблетка? Это вовсе не значит, что ничего не получится. Но придется делать по-нормальному. + +# Решение "как положено" + +1) Если у вас Windows 7, обновляйте систему. Годами не обновляемая 7-ка может не запускать драйвер `windivert`. +Поддержка 32-битных x86 Windows возможна, но в готовом виде отсутствует. +На Windows 11 ARM64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер. +Читайте `docs/windows.md`. + +Имейте в виду, что антивирусы могут плохо реагировать на `windivert`. +`cygwin` имеет внушительный список несовместимостей с антивирусами. Многие антивирусы его ломают. +Читайте [FAQ](https://www.cygwin.com/faq.html#faq.using.bloda). +Если это имеет место, используйте исключения. Если это не помогает - отключайте антивирус совсем. + +2) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам `zapret`. + +3) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. NAT не подходит. + +4) Скачайте и распакуйте [архив](https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip). + +5) Запустите `blockcheck\blockcheck.cmd`. + +`blockcheck` в начале проверяет DNS. Если выводятся сообщения о подмене адресов, то первым делом нужно решить эту проблему, иначе ничего не будет работать. Решение проблемы DNS выходит за рамки проекта. +Обычно она решается либо заменой DNS серверов от провайдера на публичные (1.1.1.1, 8.8.8.8), либо в случае перехвата провайдером обращений к сторонним серверам - через специальные средства шифрования DNS запросов, такие как DNSCrypt, DoT, DoH. +В современных броузерах чаще всего DoH включен по умолчанию, но `curl` будет использовать обычный системный DNS. +Новые билды Windows 10 и Windows 11 поддерживают системные DoH из коробки. Они не настроены по умолчанию. + +[Тут](https://hackware.ru/?p=13707) все разжевано как и где это включается. + +6) `blockcheck` позволяет выявить рабочую стратегию обхода блокировок. +Лог скрипта будет сохранен в `blockcheck\blockcheck.log`. +Запомните найденные стратегии. + +Следует понимать, что `blockcheck` проверяет доступность только конкретного домена, который вы вводите в начале. +Вероятно, все остальные домены блокированы подобным образом, но не факт. +В большинстве случаев можно объединить несколько стратегий в одну универсальную, но для этого необходимо понимать "что там за буковки". +Если вы в сетях слабо разбираетесь, это не для вас. В противном случае читайте `readme.md`. +`zapret` не может пробить блокировку по IP адресу. Для проверки нескольких доменов вводите их через пробел. + +Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов с различной длиной по ХОПам, с DPI на разных хопах. +Приходится преодолевать целый зоопарк DPI, которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера). +`blockcheck` не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки. +В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях. +Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель +`--dpi-desync-fooling`, чтобы не сломать сайты на более коротких дистанциях. +`md5sig` наиболее совместим, но работает только на Linux серверах. +`badseq` может работать только на HTTPS и не работать на HTTP. +Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL +с каждым из этих ограничителей. + +При использовании `autottl` следует протестировать как можно больше разных доменов. +Эта техника может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах она стабильна, на третьих полный хаос, и проще отказаться. + +7) Протестируйте найденные стратегии на `winws`. `winws` следует брать из `zapret-winws`. +Для этого откройте командную строку Windows от имени администратора в директории `zapret-winws`. +Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию. + +8) Обеспечьте удобную загрузку обхода блокировок. + +Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя. +Последний вариант разделяется на запуск через планировщик задач и через службы Windows. + +Если хотите ручной запуск, скопируйте `preset_russia.cmd` в `preset_my.cmd` и адаптируйте его под ваши параметра запуска. +Потом можно создать ярлык на рабочем столе на `preset_my.cmd`. Не забудьте, что требуется запускать от имени администратора. + +Но лучше будет сделать неинтерактивный автоматический запуск вместе с системой. +В `zapret-winws` есть командные файлы `task_*`, предназначенные для управления задачами планировщика. +Там следует поменять содержимое переменной `WINWS1` на свою стратегию. +Если вы не можете объединить несколько стратегий для разных протоколов в одну, дублируйте код в каждом из `.cmd` для поддержки нескольких задач: `winws1`, `winws2`, `winws3`. +После создания задач запустите их. Проверьте, что обход встает после перезагрузки Windows. + +Аналогично настраиваются и службы Windows. Смотрите `service_*.cmd`. + +9) Если ломаются отдельные незаблокированные ресурсы, используйте хост-листы. +Где они будут находиться - решайте сами. +Параметры управления хост-листами точно такие же, как в *nix. + +Это минимальная инструкция, чтобы сориентироваться с чего начать. Однако, это - не панацея. +В некоторых случаях вы не обойдетесь без знаний и основного "талмуда". +Подробности и полное техническое описание расписаны в `readme.md`. diff --git a/docs/quick_start_windows.txt b/docs/quick_start_windows.txt deleted file mode 100644 index b6fd76f..0000000 --- a/docs/quick_start_windows.txt +++ /dev/null @@ -1,117 +0,0 @@ -Специально для тех, кто хочет побыстрее начать, но не хочет слишком углубляться в простыню readme.txt. - -Как обычно, компьютерная грамотность ложится полностью на вас. -Вы должны уметь работать с консолью windows и иметь минимальные навыки обращения с командными файлами bat,cmd. -Если грамотность отсутствует и возникает куча "как" на базовых вещах - проходите мимо или ищите помощь в другом месте. - -Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда, -которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах, -требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем, -и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации. -Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать. -Могут и сломаться отдельные незаблокированные ресурсы. -Поэтому очень желательно иметь знания в области сетей, чтобы иметь возможность проанализировать техническую ситуацию. -Не будет лишним иметь обходные каналы проксирования трафика на случай, если обход DPI не помогает. - -Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы. - -Есть решение самое простое, а есть "как положено". - -САМОЕ ПРОСТОЕ РЕШЕНИЕ - -Совсем ничего не могу, все очень сложно, дайте мне таблетку. - -Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip -Запустите zapret-winws/preset_russia.cmd от имени администратора. -Возможно, заведется сразу. Этот вариант похож на "2_any_country.cmd" из GoodbyeDPI. - -То же самое с ограничителем по автоматически создаваемому хост-листу preset_russia_autohostlist.cmd. -Что такое autohostlist - читайте readme.txt. Проще говоря, мы обходим только то, что долго и упорно не хочет открываться. -Сначала не будет, но надо пытаться много раз, и тогда сработает, а дальше будет всегда срабатывать. -Остальное не будет ломаться. Использовать только, если первый вариант тоже работает. - -Не помогла таблетка ? Это вовсе не значит, что ничего не получится. Но придется делать по-нормальному. - -РЕШЕНИЕ "КАК ПОЛОЖЕНО" - -1) Если у вас windows 7, обновляйте систему. Годами не обновляемая 7-ка может не запускать драйвер windivert. -Поддержка 32-битных x86 windows возможна, но в готовом виде отсутствует. -На windows 11 arm64 выполните arm64/install_arm64.cmd от имени администратора и перезагрузите компьютер. -Читайте docs/windows.txt - -Имейте в виду, что антивирусы могут плохо реагировать на windivert. -cygwin имеет внушительный список несовместимостей с антивирусами. Многие антивирусы его ломают. -https://www.cygwin.com/faq.html#faq.using.bloda -Если это имеет место , используйте исключения. Если это не помогает - отключайте антивирус совсем. - -2) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret. - -3) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит - -4) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip - -5) Запустите blockcheck\blockcheck.cmd. blockcheck в начале проверяет DNS. Если выводятся сообщения о подмене адресов, то -первым делом нужно решить эту проблему, иначе ничего не будет работать. -Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов -от провайдера на публичные (1.1.1.1, 8.8.8.8), либо в случае перехвата провайдером обращений -к сторонним серверам - через специальные средства шифрования DNS запросов, такие как dnscrypt, DoT, DoH. -В современных броузерах чаще всего DoH включен по умолчанию, но curl будет использовать обычный системный DNS. -Новые билды win10 и win11 поддерживают системные DoH из коробки. Они не настроены по умолчанию. - -Тут все разжевано как и где это включается : https://hackware.ru/?p=13707 - -6) blockcheck позволяет выявить рабочую стратегию обхода блокировок. -Лог скрипта будет сохранен в blockcheck\blockcheck.log. -Запомните найденные стратегии. - -Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале. -Вероятно, все остальные домены блокированы подобным образом, но не факт. -В большинстве случаев можно обьединить несколько стратегий в одну универсальную, но для этого необходимо понимать -"что там за буковки". Если вы в сетях слабо разбираетесь, это не для вас. В противном случае читайте readme.txt. -zapret не может пробить блокировку по IP адресу -Для проверки нескольких доменов вводите их через пробел. - -Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов -с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI, -которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера). -blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки. -В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях. -Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель ---dpi-desync-fooling, чтобы не сломать сайты на более коротких дистанциях. -md5sig наиболее совместим, но работатет только на linux серверах. -badseq может работать только на https и не работать на http. -Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL -с каждым из этих ограничителей. - -При использовании autottl следует протестировать как можно больше разных доменов. Эта техника -может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах -она стабильна, на третьих полный хаос, и проще отказаться. - -7) Протестируйте найденные стратегии на winws. winws следует брать из zapret-winws. -Для этого откройте командную строку windows от имени администратора в директории zapret-winws. -Проще всего это сделать через _CMD_ADMIN.cmd. Он сам поднимет права и зайдет в нужную директорию. - -8) Обеспечьте удобную загрузку обхода блокировок. - -Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя. -Последний вариант разделяется на запуск через планировщик задач и через службы windows. - -Если хотите ручной запуск, скопируйте preset_russia.cmd в preset_my.cmd и адаптируйте его под ваши параметра запуска. -Потом можно создать ярлык на рабочем столе на preset_my.cmd. Не забудьте, что требуется запускать от имени администратора. - -Но лучше будет сделать неинтерактивный автоматический запуск вместе с системой. -В zapret-winws есть командные файлы task_*, предназначенные для управления задачами планировщика. -Там следует поменять содержимое переменной WINWS1 на свою стратегию. -Если вы не можете обьединить несколько стратегий для разных протоколов в одну, дублируйте код в каждом из cmd -для поддержки нескольких задач : winws1,winws2,winws3. -После создания задач запустите их. Проверьте, что обход встает после перезагрузки windows. - -Аналогично настраиваются и службы windows. Смотрите service_*.cmd - -9) Если ломаются отдельные незаблокированные ресурсы, используйте хост-листы. -Где они будут находиться - решайте сами. -Параметры управления хост-листами точно такие же, как в *nix. - -Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея. -В некоторых случаях вы не обойдетесь без знаний и основного "толмуда". -Подробности и полное техническое описание расписаны в readme.txt diff --git a/docs/readme.eng.md b/docs/readme.eng.md index d754a14..0ec735c 100644 --- a/docs/readme.eng.md +++ b/docs/readme.eng.md @@ -1,11 +1,41 @@ +- [What is it for](#what-is-it-for) +- [How it works](#how-it-works) +- [How to put this into practice in the Linux system](#how-to-put-this-into-practice-in-the-linux-system) +- [ip6tables](#ip6tables) +- [`nftables`](#nftables) +- [When it will not work](#when-it-will-not-work) +- [`nfqws`](#nfqws) + - [DPI desync attack](#dpi-desync-attack) + - [DPI desync combos](#dpi-desync-combos) + - [SYNACK mode](#synack-mode) + - [SYNDATA mode](#syndata-mode) + - [Virtual Machines](#virtual-machines) + - [CONNTRACK](#conntrack) + - [Reassemble](#reassemble) + - [UDP support](#udp-support) + - [IP fragmentation](#ip-fragmentation) +- [`tpws`](#tpws) +- [Ways to get a list of blocked IP](#ways-to-get-a-list-of-blocked-ip) +- [Domain name filtering](#domain-name-filtering) +- [**autohostlist** mode](#autohostlist-mode) +- [Choosing parameters](#choosing-parameters) +- [Screwing to the firewall control system or your launch system](#screwing-to-the-firewall-control-system-or-your-launch-system) +- [Installation](#installation) + - [Checking ISP](#checking-isp) + - [desktop Linux system](#desktop-linux-system) + - [OpenWrt](#openwrt) + - [Android](#android) + - [FreeBSD, OpenBSD, macOS](#freebsd-openbsd-macos) + - [Windows (WSL)](#windows-wsl) + - [Other devices](#other-devices) + ## What is it for A stand-alone (without 3rd party servers) DPI circumvention tool. May allow to bypass http(s) website blocking or speed shaping, resist signature tcp/udp protocol discovery. -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. +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. Mainly OpenWRT targeted but also supports traditional Linux, FreeBSD, OpenBSD, Windows, partially MacOS. @@ -13,18 +43,18 @@ Most features are also supported in Windows. ## How it works -In the simplest case you are dealing with passive DPI. Passive DPI can read passthrough traffic, -inject its own packets, but cannot drop packets. +In the simplest case you are dealing with passive DPI. +Passive DPI can read passthrough traffic, inject its own packets, but cannot drop packets. If the request is prohibited the passive DPI will inject its own RST packet and optionally http redirect packet. -If fake packets from DPI are only sent to client, you can use iptables commands to drop them if you can write -correct filter rules. This requires manual in-deep traffic analysis and tuning for specific ISP. +If fake packets from DPI are only sent to client, you can use `iptables` commands to drop them if you can write correct filter rules. +This requires manual in-deep traffic analysis and tuning for specific ISP. This is how we bypass the consequences of a ban trigger. If the passive DPI sends an RST packet also to the server, there is nothing you can do about it. -Your task is to prevent ban trigger from firing up. Iptables alone will not work. +Your task is to prevent ban trigger from firing up. `iptables` alone will not work. This project is aimed at preventing the ban rather than eliminating its consequences. To do that send what DPI does not expect and what breaks its algorithm of recognizing requests and blocking them. @@ -50,20 +80,28 @@ deal with its consequences. 2. Modification of the TCP connection at the stream level. Implemented through a proxy or transparent proxy. 3. Modification of TCP connection at the packet level. Implemented through the NFQUEUE handler and raw sockets. -For options 2 and 3, tpws and nfqws programs are implemented, respectively. -You need to run them with the necessary parameters and redirect certain traffic with iptables or nftables. +For options 2 and 3, `tpws` and `nfqws` programs are implemented, respectively. +You need to run them with the necessary parameters and redirect certain traffic with `iptables` or `nftables`. To redirect a TCP connection to a transparent proxy, the following commands are used: -forwarded traffic : -`iptables -t nat -I PREROUTING -i -p tcp --dport 80 -j DNAT --to 127.0.0.127:988` +* forwarded traffic: -outgoing traffic : -`iptables -t nat -I OUTPUT -o -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988` +```sh +iptables -t nat -I PREROUTING -i -p tcp --dport 80 -j DNAT --to 127.0.0.127:988 +``` -DNAT on localhost works in the OUTPUT chain, but does not work in the PREROUTING chain without enabling the route_localnet parameter: +* outgoing traffic: -`sysctl -w net.ipv4.conf..route_localnet=1` +```sh +iptables -t nat -I OUTPUT -o -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988 +``` + +DNAT on localhost works in the OUTPUT chain, but does not work in the PREROUTING chain without enabling the `route_localnet` parameter: + +```sh +sysctl -w net.ipv4.conf..route_localnet=1 +``` You can use `-j REDIRECT --to-port 988` instead of DNAT, but in this case the transparent proxy process should listen on the ip address of the incoming interface or on all addresses. Listen all - not good @@ -78,8 +116,8 @@ iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP ``` -Owner filter is necessary to prevent recursive redirection of connections from tpws itself. -tpws must be started under OS user `tpws`. +Owner filter is necessary to prevent recursive redirection of connections from `tpws` itself. +`tpws` must be started under OS user `tpws`. NFQUEUE redirection of the outgoing traffic and forwarded traffic going towards the external interface, can be done with the following commands: @@ -96,7 +134,7 @@ Then we can reduce CPU load, refusing to process unnecessary packets. `iptables -t mangle -I POSTROUTING -o -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass` -Mark filter does not allow nfqws-generated packets to enter the queue again. +Mark filter does not allow `nfqws`-generated packets to enter the queue again. Its necessary to use this filter when also using `connbytes 1:6`. Without it packet ordering can be changed breaking the whole idea. Some attacks require redirection of incoming packets : @@ -121,19 +159,18 @@ In the PREROUTING DNAT chain, it is possible to any global address or to the lin the packet came from. NFQUEUE works without changes. +## `nftables` -## nftables - -nftables are fine except one very big problem. -nft requires tons of RAM to load large nf sets (ip lists) with subnets/intervals. Most of the home routers can't afford that. -For example, even a 256 Mb system can't load a 100K ip list. nft process will OOM. -nf sets do not support overlapping intervals and that's why nft process applies very RAM consuming algorithm to merge intervals so they don't overlap. -There're equivalents to iptables for all other functions. Interface and protocol anonymous sets allow not to write multiple similar rules. -Flow offloading is built-in into new linux kernels and nft versions. +`nftables` are fine except one very big problem. +`nft` requires tons of RAM to load large nf sets (ip lists) with subnets/intervals. Most of the home routers can't afford that. +For example, even a 256 Mb system can't load a 100K ip list. `nft` process will OOM. +nf sets do not support overlapping intervals and that's why `nft` process applies very RAM consuming algorithm to merge intervals so they don't overlap. +There're equivalents to `iptables` for all other functions. Interface and protocol anonymous sets allow not to write multiple similar rules. +Flow offloading is built-in into new Linux kernels and `nft` versions. nft version `1.0.2` or higher is recommended. But the higher is version the better. -Some techniques can be fully used only with nftables. It's not possible to queue packets after NAT in iptables. +Some techniques can be fully used only with `nftables`. It's not possible to queue packets after NAT in `iptables`. This limits techniques that break NAT. @@ -145,7 +182,7 @@ when blocked domains are queried. If this is the case change DNS to public ones, * 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 +## `nfqws` This program is a packet modifier and a NFQUEUE queue handler. For BSD systems there is dvtws. Its built from the same source and has almost the same parameters (see bsd.eng.md). @@ -333,12 +370,14 @@ Subdomains are applied automatically. gzip lists are supported. iptables for performing the attack on the first packet : -`iptables -t mangle -I POSTROUTING -o -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass` +```sh +iptables -t mangle -I POSTROUTING -o -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass +``` This is good if DPI does not track all requests in http keep-alive session. If it does, then pass all outgoing packets for http and only first data packet for https : -``` +```sh iptables -t mangle -I POSTROUTING -o -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass iptables -t mangle -I POSTROUTING -o -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass ``` @@ -368,14 +407,14 @@ for example : `-A OUTPUT -m state --state INVALID -j DROP` In openwrt it's possible to disable the rule for both FORWARD and OUTPUT chains in /etc/config/firewall : ``` config zone - option name 'wan' - ......... - option masq_allow_invalid '1' + option name 'wan' + ......... + option masq_allow_invalid '1' ``` Unfortunately there's no OUTPUT only switch. It's not desired to remove the rule from the FORWARD chain. Add the following lines to `/etc/firewall.user` : -``` +```sh iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT ``` @@ -402,7 +441,7 @@ Set up bridge networking. nfqws is equipped with minimalistic connection tracking system (conntrack) It's used if some specific DPI circumvention methods are involved and helps to reassemble multi-packet requests. -Conntrack can track connection phase : SYN,ESTABLISHED,FIN , packet counts in both directions , sequence numbers. +Conntrack can track connection phase: SYN,ESTABLISHED,FIN, packet counts in both directions, sequence numbers. It can be fed with unidirectional or bidirectional packets. @@ -533,25 +572,27 @@ In openwrt module parameters are specified after module names separated by space In traditional linux check whether `iptables-legacy` or `iptables-nft` is used. If legacy create the file `/etc/modprobe.d/ip6table_raw.conf` with the following content : -``` + +```sh options ip6table_raw raw_before_defrag=1 ``` In some linux distros its possible to change current ip6tables using this command: `update-alternatives --config ip6tables`. If you want to stay with `nftables-nft` you need to patch and recompile your version. In `nft.c` find : -``` - { - .name = "PREROUTING", - .type = "filter", - .prio = -300, /* NF_IP_PRI_RAW */ - .hook = NF_INET_PRE_ROUTING, - }, - { - .name = "OUTPUT", - .type = "filter", - .prio = -300, /* NF_IP_PRI_RAW */ - .hook = NF_INET_LOCAL_OUT, - }, + +```c + { + .name = "PREROUTING", + .type = "filter", + .prio = -300, /* NF_IP_PRI_RAW */ + .hook = NF_INET_PRE_ROUTING, + }, + { + .name = "OUTPUT", + .type = "filter", + .prio = -300, /* NF_IP_PRI_RAW */ + .hook = NF_INET_LOCAL_OUT, + }, ``` and replace -300 to -450. @@ -565,8 +606,7 @@ nfqws sees packets with internal network source address. If fragmented NAT does This results in attempt to send packets to internet with internal IP address. You need to use nftables instead with hook priority 101 or higher. - -## tpws +## `tpws` tpws is transparent proxy. @@ -681,8 +721,8 @@ To bind to a specific ip when its interface may not be configured yet do : `--bi It's possible to bind to any nonexistent address in transparent mode but in socks mode address must exist. -In socks proxy mode no additional system privileges are required. Connections 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. +In SOCKS proxy mode no additional system privileges are required. Connections 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 activities. Domain names are resolved in multi threaded pool. Resolving does not freeze other connections. But if there're too many requests resolving delays may increase. @@ -729,8 +769,8 @@ At the output, you get `ipset/zapret-ip-user.txt` with IP addresses. 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. +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. @@ -750,7 +790,7 @@ Stored lists are already processed by ip2net. They are error free and ready for `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. +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. @@ -911,7 +951,7 @@ Its possible to change manipulation options used by tpws : nfqws options for DPI desync attack: -``` +```sh DESYNC_MARK=0x40000000 DESYNC_MARK_POSTNAT=0x20000000 NFQWS_OPT_DESYNC="--dpi-desync=fake --dpi-desync-ttl=0 --dpi-desync-fooling=badsum --dpi-desync-fwmark=$DESYNC_MARK" @@ -919,7 +959,7 @@ NFQWS_OPT_DESYNC="--dpi-desync=fake --dpi-desync-ttl=0 --dpi-desync-fooling=bads Separate nfqws options for http and https and ip protocol versions 4,6: -``` +```sh NFQWS_OPT_DESYNC_HTTP="--dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" NFQWS_OPT_DESYNC_HTTPS="--wssize=1:6 --dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" NFQWS_OPT_DESYNC_HTTP6="--dpi-desync=split --dpi-desync-ttl=5 --dpi-desync-fooling=none" @@ -935,7 +975,7 @@ If a variable is not defined, the value `NFQWS_OPT_DESYNC` is taken. Separate QUIC options for ip protocol versions : -``` +```sh NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake" NFQWS_OPT_DESYNC_QUIC6="--dpi-desync=hopbyhop" ``` @@ -963,7 +1003,7 @@ 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. -``` +```sh #DISABLE_IPV4=1 DISABLE_IPV6=1 ``` @@ -979,7 +1019,7 @@ TMPDIR=/opt/zapret/tmp ipset and nfset options : -``` +```sh SET_MAXELEM=262144 IPSET_OPT="hashsize 262144 maxelem 2097152 ``` @@ -991,14 +1031,14 @@ Do not use too high hashsize. This way you waste your RAM. And dont use too low ip2net options. separate for ipv4 and ipv6. -``` +```sh IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4" IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5" ``` autohostlist mode tuning. -``` +```sh AUTOHOSTLIST_RETRANS_THRESHOLD=3 AUTOHOSTLIST_FAIL_THRESHOLD=2 AUTOHOSTLIST_FAIL_TIME=60 @@ -1024,7 +1064,8 @@ To override this behaviour set the following variable : In openwrt wan interfaces are those having default route. Separately for ipv4 and ipv6. This can be redefined : -``` + +```sh OPENWRT_WAN4="wan4 vpn" OPENWRT_WAN6="wan6 vpn6" ``` @@ -1037,7 +1078,8 @@ Not applicable to `OpenWRT` if used with `firewall3+iptables`. 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: -``` + +```sh IFACE_LAN=eth0 IFACE_WAN=eth1 IFACE_WAN6="henet ipsec0" @@ -1057,7 +1099,7 @@ In this case, the rules for iptables should be screwed to your firewall separate The following calls allow you to apply or remove iptables rules separately: -``` +```sh /opt/zapret/init.d/sysv/zapret start_fw /opt/zapret/init.d/sysv/zapret stop_fw /opt/zapret/init.d/sysv/zapret restart_fw @@ -1065,7 +1107,7 @@ The following calls allow you to apply or remove iptables rules separately: And you can start or stop the demons separately from the firewall: -``` +```sh /opt/zapret/init.d/sysv/zapret start_daemons /opt/zapret/init.d/sysv/zapret stop_daemons /opt/zapret/init.d/sysv/zapret restart_daemons @@ -1078,26 +1120,29 @@ If your system does not touch it everything will likely be OK. Some additional nftables-only calls exist : Lookup `lanif`, `wanif`, `wanif6` and `flow table` interface sets. -``` + +```sh /opt/zapret/init.d/sysv/zapret list_ifsets ``` Renew `lanif`, `wanif`, `wanif6` and `flow table` interface sets. Taken from `IFACE_LAN`, `IFACE_WAN` config variables on traditional Linux systems. -Autoselected on `OpenWRT`. `lanif` can be extended using `OPENWRT_LAN` config variable. -``` +Autoselected on `OpenWrt`. `lanif` can be extended using `OPENWRT_LAN` config variable. + +```sh /opt/zapret/init.d/sysv/zapret reload_ifsets ``` Calls `nft -t list table inet zapret`. -``` + +```sh /opt/zapret/init.d/sysv/zapret list_table ``` It's also possible to hook with your script to any stage of zapret firewall processing. The following settings are available in the zapret config file : -``` +```sh INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up" INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down" @@ -1130,8 +1175,8 @@ Run `install_easy.sh` and answer its questions. 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. -Install openssh-sftp-server and unzip to openwrt and use sftp to transfer the file. +Another challenge would be to bring zapret to the router. You can download zip from GitHub and use it. +Install openssh-sftp-server and unzip to OpenWrt and use sftp to transfer the file. It's also not too hard to use 'nc' (netcat) for file transfer. The best way to start is to put zapret dir to `/tmp` and run `/tmp/zapret/install_easy.sh` from there. @@ -1172,7 +1217,7 @@ You can't write to `/system`, `/data`, can't run from sd card. Selinux prevents running executables in `/data/local/tmp` from apps. Use adb and adb shell. -``` +```sh mkdir /data/local/tmp/zapret adb push tpws /data/local/tmp/zapret chmod 755 /data/local/tmp/zapret /data/local/tmp/zapret/tpws diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..0a093b6 --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,1924 @@ +# zapret v.61 + +- [zapret v.61](#zapret-v61) + - [English](#english) + - [Для чего это надо](#для-чего-это-надо) + - [Как побыстрее начать](#как-побыстрее-начать) + - [Как это работает](#как-это-работает) + - [Что сейчас происходит в России](#что-сейчас-происходит-в-россии) + - [Как это реализовать на практике в системе Linux](#как-это-реализовать-на-практике-в-системе-linux) + - [Особенности применения `ip6tables`](#особенности-применения-ip6tables) + - [Особенности применения `nftables`](#особенности-применения-nftables) + - [Когда это работать не будет](#когда-это-работать-не-будет) + - [`nfqws`](#nfqws) + - [Атака десинхронизации DPI](#атака-десинхронизации-dpi) + - [Комбинирование методов десинхронизации](#комбинирование-методов-десинхронизации) + - [Режим SYNACK](#режим-synack) + - [Режим SYNDATA](#режим-syndata) + - [Виртуальные машины](#виртуальные-машины) + - [conntrack](#conntrack) + - [Реассемблинг](#реассемблинг) + - [Поддержка UDP](#поддержка-udp) + - [IP фрагментация](#ip-фрагментация) + - [`tpws`](#tpws) + - [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip) + - [IPv6](#ipv6) + - [Система исключения IP](#система-исключения-ip) + - [FreeBSD](#freebsd) + - [`ip2net`](#ip2net) + - [Фильтрация по именам доменов](#фильтрация-по-именам-доменов) + - [Режим фильтрации `autohostlist`](#режим-фильтрации-autohostlist) + - [Проверка провайдера](#проверка-провайдера) + - [Скан портов](#скан-портов) + - [Проверка на частичный IP block](#проверка-на-частичный-ip-block) + - [Пример блокировки по домену без блокировки по IP](#пример-блокировки-по-домену-без-блокировки-по-ip) + - [Пример полного IP блока или блока TCP порта при отсутствии блока по домену](#пример-полного-ip-блока-или-блока-tcp-порта-при-отсутствии-блока-по-домену) + - [Выбор параметров](#выбор-параметров) + - [Прикручивание к системе управления фаерволом или своей системе запуска](#прикручивание-к-системе-управления-фаерволом-или-своей-системе-запуска) + - [Вариант `custom`](#вариант-custom) + - [Простая установка](#простая-установка) + - [Простая установка на OpenWrt](#простая-установка-на-openwrt) + - [Android](#android) + - [Мобильные модемы и роутеры Huawei](#мобильные-модемы-и-роутеры-huawei) + - [Предупреждение](#предупреждение) + - [FreeBSD, OpenBSD, macOS](#freebsd-openbsd-macos) + - [Windows](#windows) + - [Другие прошивки](#другие-прошивки) + - [Обход блокировки через сторонний хост](#обход-блокировки-через-сторонний-хост) + - [Почему стоит вложиться в покупку VPS](#почему-стоит-вложиться-в-покупку-vps) + +## English + +For English version refer to `docs/README.eng.md`. + +## Для чего это надо + +Автономное, без задействования сторонних серверов, средство противодействия DPI. +Может помочь обойти блокировки или замедление сайтов HTTPS(S), сигнатурный анализ TCP и UDP протоколов, например, с целью блокировки VPN. + +Проект нацелен прежде всего на маломощные embedded устройства - роутеры, работающие под OpenWrt. +Поддерживаются традиционные Linux системы, FreeBSD, OpenBSD, частично macOS. +В некоторых случаях возможна самостоятельная прикрутка решения к различным прошивкам. + +Большая часть функционала работает на Windows. + +## Как побыстрее начать + +Читайте `docs/quick_start.md` для Linux и OpenWrt, `docs/quick_start_windows.md` для Windows. + +## Как это работает + +В самом простейшем случае, вы имеете дело с пассивным DPI. Пассивный DPI может читать трафик из потока, может инжектить свои пакеты, но не может блокировать проходящие пакеты. +Если запрос "плохой", пассивный DPI инжектит пакет RST, опционально дополняя его пакетом HTTP redirect. +Если фейк пакет инжектится только для клиента, в этом случае можно обойтись командами `iptables` для дропа RST и/или редиректа на заглушку по определенным условиям, которые нужно подбирать для каждого провайдера индивидуально. Так мы обходим последствия срабатывания триггера запрета. +Если пассивный DPI направляет пакет RST в том числе и серверу, то вы ничего с этим не сможете сделать. +Ваша задача - не допустить срабатывания триггера запрета. Одними `iptables` уже не обойдетесь. +Этот проект нацелен именно на предотвращение срабатывания запрета, а не на ликвидацию его последствий. + +Активный DPI ставится в разрез провода и может дропать пакеты по любым критериям, в том числе распознавать TCP потоки и блокировать любые пакеты, принадлежащие потоку. + +Как не допустить срабатывания триггера запрета? Послать то, на что DPI не рассчитывает и что ломает ему алгоритм распознавания запросов и их блокировки. + +Некоторые DPI не могут распознать HTTP запрос, если он разделен на TCP сегменты. +Например, запрос вида `GET / HTTP/1.1\r\nHost: kinozal.tv......` +мы посылаем 2 частями: сначала идет `GET`, затем `/ HTTP/1.1\r\nHost: kinozal.tv.....`. +Другие DPI спотыкаются, когда заголовок `Host:` пишется в другом регистре: например, `host:`. +Кое-где работает добавление дополнительного пробела после метода: `GET /` => `GET /` или добавление точки в конце имени хоста: `Host: kinozal.tv.` + +Существует и более продвинутая магия, направленная на преодоление DPI на пакетном уровне. + +Подробнее про DPI: + +- +- + +## Что сейчас происходит в России + +Раньше, до внедрения повсеместных систем ТСПУ, использовался зоопарк различных DPI у провайдеров. +Какие-то были активными, какие-то пассивными. +Сейчас время простых `iptables` окончательно ушло. +Везде активный DPI ТСПУ, но кое-где могут оставаться невыключенными дополнительные старые DPI из зоопарка. +В этом случае приходится обходить сразу несколько DPI. +Все больше становится внереестровых блокировок, о которых вы узнаете только по факту недоступности чего-либо, в списках этого нет. +Применяются блокировки некоторых диапазонов IP адресов (автономный обход невозможен) и протоколов (VPN). +На некоторых диапазонах IP используется более строгий фильтр, распознающий попытки обмана через сегментацию. +Должно быть, это связано с некоторыми сервисами, которые +пытаются таким образом обмануть DPI. + +## Как это реализовать на практике в системе Linux + +Если кратко, то варианты можно классифицировать по следующей схеме: + +1) Пассивный DPI, не отправляющий RST серверу. + +Помогут индивидуально настраиваемые под провайдера команды `iptables`. +На rutracker в разделе ["обход блокировок - другие способы"](https://rutracker.org/forum/viewforum.php?f=616) по этому вопросу существует отдельная тема. +В данном проекте не рассматривается. Если вы не допустите срабатывание триггера запрета, то и не придется +бороться с его последствиями. + +2) Модификация TCP соединения на уровне потока. + +Реализуется через proxy или transparent proxy. + +3) Модификация TCP соединения на уровне пакетов. + +Реализуется через обработчик очереди NFQUEUE и raw сокеты. + +Для вариантов 2 и 3 реализованы программы `tpws` и `nfqws` соответственно. +Чтобы они работали, необходимо их запустить с нужными параметрами и перенаправить на них определенный трафик +средствами `iptables` или `nftables`. + +Для перенаправления TCP соединения на transparent proxy используются команды следующего вида : + +- Проходящий трафик: + +```sh +iptables -t nat -I PREROUTING -i <внутренний_интерфейс> -p tcp --dport 80 -j DNAT --to 127.0.0.127:988 +``` + +- Исходящий трафик: + +```sh +iptables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988 +``` + +DNAT на localhost работает в цепочке OUTPUT, но не работает в цепочке PREROUTING без включения параметра route_localnet: + +```sh +sysctl -w net.ipv4.conf.<внутренний_интерфейс>.route_localnet=1 +``` + +Можно использовать `-j REDIRECT --to-port 988` вместо DNAT, однако в этом случае процесс transparent proxy должен слушать на IP адресе входящего интерфейса или на всех адресах. +Слушать на всех - не есть хорошо с точки зрения безопасности. +Слушать на одном (локальном) можно, но в случае автоматизированного скрипта придется его узнавать, потом динамически вписывать в команду. +В любом случае требуются дополнительные усилия. +Использование route_localnet тоже имеет потенциальные проблемы с безопасностью. Вы делаете доступным все, что висит на 127.0.0.0/8 для локальной подсети <внутренний_интерфейс>. +Службы обычно привязываются к 127.0.0.1, поэтому можно средствами `iptables` запретить входящие на 127.0.0.1 не с интерфейса lo, либо повесить `tpws` на любой другой IP из 127.0.0.0/8, например на 127.0.0.127, и разрешить входящие не с lo только на этот IP: + +```sh +iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT +iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP +``` + +Фильтр по owner необходим для исключения рекурсивного перенаправления соединений от самого `tpws`. +`tpws` запускается под пользователем tpws, для него задается исключающее правило. + +`tpws` может использоваться в режиме SOCKS proxy. В этом случае `iptables` не нужны, а нужно прописать SOCKS в настройки программы (например, броузера), с которой будем обходить блокировки. +transparent proxy отличается от SOCKS именно тем, что в варианте transparent настраивать клиентские программы не нужно. + +Для перенаправления на очередь NFQUEUE исходящего и проходящего в сторону внешнего интерфейса трафика используются +команды следующего вида: + +```sh +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass +``` + +Чтобы не трогать трафик на незаблокированные адреса, можно взять список заблокированных хостов, заресолвить его в IP адреса и загнать в ipset zapret, затем добавить фильтр в команду: + +```sh +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass +``` + +DPI может ловить только первый HTTP запрос, игнорируя последующие запросы в keep-alive сессии. +Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов: + +```sh +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass +``` + +Фильтр по mark нужен для отсечения от очереди пакетов, сгенерированных внутри `nfqws`. +Если применяется фильтр по connbytes 1:6, то обязательно добавлять в `iptables` и фильтр по mark. +Иначе возможно перепутывание порядка следования пакетов, что приведет к неработоспособности метода. + +Для некоторых атак на DPI требуется перенаправлять один или несколько входящих пакетов от соединения: + +```sh +iptables -t mangle -I PREROUTING -i <внешний_интерфейс> -p tcp --sport 80 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass +``` + +Получаемые пакеты будут фильтроваться по входящему интерфейсу, порту и IP источника, то есть наоборот прямому правилу. + +Некоторые техники, ломающие NAT, не всегда можно реализовать через `iptables`. Требуются `nftables`. + +Если ваше устройство поддерживает аппаратное ускорение (flow offloading, hardware nat, hardware acceleration), то `iptables` могут не работать. +При включенном offloading пакет не проходит по обычному пути netfilter. +Необходимо или его отключить, или выборочно им управлять. + +В новых ядрах (и в более старых, OpenWrt портировал изменение на 4.14) присутствует software flow offloading (SFO). +Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов `iptables`. +При включенном SFO работает DNAT/REDIRECT (`tpws`). Эти соединения исключаются из offloading. +Однако, остальные соединения идут через SFO, потому NFQUEUE будет срабатывать только до помещения соединения в flowtable. +Практически это означает, что nfqws будет работать на window size changing, но не будут работать опции по модификации содержимого пакетов. +Offload включается через специальный target в `iptables` "FLOWOFFLOAD". Не обязательно пропускать весь трафик через offload. +Можно исключить из offload соединения, которые должны попасть на `tpws` или `nfqws`. +OpenWrt не предусматривает выборочного управления offload. +Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в OpenWrt. + +## Особенности применения `ip6tables` + +`ip6tables` работают почти точно так же, как и IPv4, но есть ряд важных нюансов. +В DNAT следует брать адрес `--to` в квадратные скобки. Например: + +```sh +ip6tables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:988 +``` + +Параметра `route_localnet` не существует для IPv6. +DNAT на localhost (::1) возможен только в цепочке OUTPUT. +В цепочке PREROUTING DNAT возможен на любой global address или на link local address того же интерфейса, откуда пришел пакет. +NFQUEUE работает без изменений. + +## Особенности применения `nftables` + +Более подробно преимущества и недостатки `nftables` применительно к данной системе описаны в `docs/nftables_notes.md` +Если коротко, то в `nftables` невозможно работать с большими IP листами на системах с малым количеством RAM. +Остальные рассматриваемые здесь функции могут быть перенесены на `nftables`. + +Рекомендуется версия nft 1.0.2 или выше. Но чем выше версия, тем лучше. В nft регулярно находят баги. + +Относительно старые версии ядра и/или утилиты nft могут вызывать ошибки. +В частности, на Ubuntu 18.04 с ядром 4.15 будут проблемы. В 20.04 - работает. + +Некоторые техники можно полноценно использовать только с `nftables`. +Например, в `iptables` невозможно перенаправить пакеты на `nfqws` после NAT. +Следовательно, при использовании NAT невозможно произвести атаку, не совместимую с NAT. +В `nftables` этой проблемы не существует, потому что приоритеты хука выставляете вы сами, а не привязаны к фиксированным значениям, соответствующим разным таблицам `iptables`. +В `iptables` нет таблицы, способной перехватить пакеты после MASQUERDADE. + +## Когда это работать не будет + +- Если подменяется DNS. + +С этой проблемой легко справиться. + +- Если блокировка осуществляется по IP. + +- Если соединение проходит через фильтр, способный реконструировать TCP соединение, и который следует всем стандартам. + +Например, нас заворачивают на squid. +Соединение идет через полноценный стек TCP/IP операционной системы, фрагментация отпадает сразу как средство обхода. +Squid правильный, он все найдет как надо, обманывать его бесполезно. +НО. Заворачивать на squid могут позволить себе лишь небольшие провайдеры, поскольку это очень ресурсоёмко. +Большие компании обычно используют DPI, который рассчитан на гораздо большую пропускную способность. +Может применяться комбинированный подход, когда на DPI заворачивают только IP из "плохого" списка, и дальше уже DPI решает пропускать или нет. +Так можно снизить нагрузку на DPI в десятки, если не сотни раз, а следовательно не покупать очень дорогие решения, обойдясь чем-то существенно более дешевым. +Мелкие провайдеры могут покупать услугу фильтрации у вышестоящих, чтобы самим не морочиться, и они уже будут применять DPI. + +## `nfqws` + +Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. +Для BSD систем существует адаптированный вариант - `dvtws`, собираемый из тех же исходников (см. `docs/bsd.md`). + +``` +--debug=0|1 ; 1=выводить отладочные сообщения +--daemon ; демонизировать прогу +--pidfile= ; сохранить PID в файл +--user= ; менять uid процесса +--uid=uid[:gid] ; менять uid процесса +--qnum=N ; номер очереди N +--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных IPv4 пакетов +--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных IPv6 пакетов +--wsize=[:] ; менять TCP window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) +--wssize=[:] ; менять TCP window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) +--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N +--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут UDP. по умолчанию 60:300:60:60 +--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". +--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета +--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase +--domcase ; домен после Host: сделать таким: TeSt.cOm +--dpi-desync=[,][, ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 +--dpi-desync-ttl= ; установить TTL для десинхронизирующих пакетов +--dpi-desync-ttl6= ; установить IPv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение TTL +--dpi-desync-autottl=[[:[-]]] ; режим auto TTL для IPv4 и IPv6. по умолчанию: 1:3-20. delta=0 отключает функцию. +--dpi-desync-autottl6=[[:[-]]] ; переопределение предыдущего параметра для IPv6 +--dpi-desync-fooling= ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2 +--dpi-desync-repeats= ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) +--dpi-desync-skip-nosni=0| 1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI +--dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции +--dpi-desync-split-http-req=method|host ; разбивка http request на указанном логическом месте +--dpi-desync-split-tls=sni|sniext ; разбивка tls ClientHello на указанном логическом месте +--dpi-desync-split-seqovl= ; использовать sequence overlap перед первым отсылаемым оригинальным TCP сегментом +--dpi-desync-split-seqovl-pattern=|0xHEX ; чем заполнять фейковую часть overlap +--dpi-desync-badseq-increment= ; инкремент sequence number для badseq. по умолчанию -10000 +--dpi-desync-badack-increment= ; инкремент ACK sequence number для badseq. по умолчанию -66000 +--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по HTTP request и tls ClientHello 1=по всем непустым пакетам данных +--dpi-desync-fake-http=|0xHEX ; файл, содержащий фейковый HTTP запрос для dpi-desync=fake, на замену стандартному www.iana.org +--dpi-desync-fake-tls=|0xHEX ; файл, содержащий фейковый TLS ClientHello для dpi-desync=fake, на замену стандартному www.iana.org +--dpi-desync-fake-unknown=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт +--dpi-desync-fake-syndata=|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata +--dpi-desync-fake-quic=|0xHEX ; файл, содержащий фейковый QUIC Initial +--dpi-desync-fake-dht=|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт +--dpi-desync-fake-unknown-udp=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного UDP протокола для dpi-desync=fake, на замену стандартным нулям 64 байт +--dpi-desync-udplen-increment= ; насколько увеличивать длину UDP пейлоада в режиме udplen +--dpi-desync-udplen-pattern=|0xHEX ; чем добивать UDP пакет в режиме udplen. по умолчанию - нули +--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N +--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N +--hostlist= ; применять дурение только к хостам из листа. может быть множество листов, они объединяются. пустой обший лист = его отсутствие +--hostlist-exclude= ; не применять дурение к хостам из листа. может быть множество листов, они объединяются +--hostlist-auto= ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) +--hostlist-auto-fail-threshold= ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) +--hostlist-auto-fail-time= ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) +--hostlist-auto-retrans-threshold= ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3) +--hostlist-auto-debug= ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. +``` + +Параметры манипуляции могут сочетаться в любых комбинациях. + +**ЗАМЕЧАНИЕ.** Параметр `--wsize` считается устаревшим и более не поддерживается в скриптах. +Функции сплита выполняются в рамках атаки десинхронизации. Это быстрее и избавляет от целого ряда недостатков wsize. + +`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. +Может быть важен порядок следования опций. +`--debug` лучше всего указывать в самом начале. Опции анализируются последовательно. +Если ошибка будет при проверке опции, а до анализа `--debug` еще дело не дошло, то сообщения не будут выведены в файл или syslog. +При логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается. +Так что файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог. +Но имейте в виду, что если вы запускаете процесс под root, то будет сменен UID на не-root. +В начале на лог файл меняется owner, иначе запись будет невозможна. +Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не будет вестись. +Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду `: > filename`. + +### Атака десинхронизации DPI + +Суть её в следующем. После выполнения TCP 3-way handshake идет первый пакет с данными от клиента. +Там обычно `GET / ...` или TLS ClientHello. Мы дропаем этот пакет, заменяя чем-то другим. +Это может быть поддельная версия с безобидным, но валидным запросом HTTP или HTTPS (вариант `fake`), пакет сброса соединения (варианты `rst`, `rstack`), разбитый на части оригинальный пакет с перепутанным порядком следования сегментов + обрамление первого сегмента фейками (`disorder`), то же самое без перепутывания порядка сегментов (`split`). +`fakeknown` отличается от `fake` тем, что применяется только к распознанному протоколу. +В литературе такие атаки еще называют TCB desynchronization и TCB teardown. +Надо, чтобы фейковые пакеты дошли до DPI, но не дошли до сервера. +На вооружении есть следующие возможности: установить низкий TTL, посылать пакет с инвалидной чексуммой, добавлять TCP option "MD5 signature", испортить sequence numbers. Все они не лишены недостатков. + +- `md5sig` работает не на всех серверах. + +Пакеты с md5 обычно отбрасывают только Linux. + +- `badsum` не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. + +Наиболее распространенная настройка NAT роутера в Linux их не пропускает. +На Linux построено большинство домашних роутеров. +Непропускание обеспечивается так: настройка ядра `sysctl` по умолчанию `net.netfilter.nf_conntrack_checksum=1` заставляет conntrack проверять TCP и UDP чексуммы входящих пакетов и выставлять state INVALID для пакетов с инвалидной суммой. + +Обычно в правилах `iptables` вставляется правило для дропа пакетов с состоянием INVALID в цепочке FORWARD. +Совместное сочетание этих факторов приводит к непрохождению `badsum` через такой роутер. + +В OpenWrt из коробки `net.netfilter.nf_conntrack_checksum=0`, в других роутерах часто нет, и не всегда это можно изменить. +Чтобы `nfqws` мог работать через роутер, нужно на нем выставить указанное значение `sysctl` в 0. +`nfqws` на самом роутере будет работать и без этой настройки, потому что чексумма локально созданных пакетов не проверяется никогда. + +Если роутер за другим NAT, например провайдерским, и он не пропускает invalid packets вы ничего не сможете с этим сделать. +Но обычно провайдеры все же пропускают `badsum`. +На некоторых адаптерах/свитчах/драйверах принудительно включен rx-checksum offload, `badsum` пакеты отсекаются еще до получения в ОС. +В этом случае если что-то и можно сделать, то только модифицировать драйвер, что представляется задачей крайне нетривиальной. +Установлено, что так себя ведут некоторые роутеры на базе Mediatek. +`badsum` пакеты уходят с клиентской ОС, но роутером не видятся в br-lan через `tcpdump`. +При этом если nfqws выполняется на самом роутере, обход может работать. `badsum` нормально уходят с внешнего интерфейса. + +- Пакеты с `badseq` будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence numbers. + +По умолчанию смещение seq выбирается -10000.v +Практика показала, что некоторые DPI не пропускают seq вне определенного окна. Однако, такое небольшое смещение может вызвать проблемы при существенной потоковой передаче и потере пакетов. +Если вы используете `--dpi-desync-any-protocol`, может понадобится установить badseq increment 0x80000000. Это обеспечит надежную гарантию, что поддельный пакет не вклинится в TCP window на сервере. +Так же было замечено, что `badseq` ломает логику некоторых DPI при анализе HTTP, вызывая зависание соединения. Причем на тех же DPI TLS с `badseq` работает нормально. + +- TTL, казалось бы, - лучший вариант, но он требует индивидуальной настройки под каждого провайдера. + +Если DPI находится дальше локальных сайтов провайдера, то вы можете отрезать себе доступ к ним. +Ситуация усугубляется наличием ТСПУ на магистралах, что вынуждает делать TTL достаточно высоким, увеличивая риск пробоя фейка до сервера. +Необходим IP exclude list, заполняемый вручную. +Вместе с `ttl` можно применять `md5sig`. Это ничего не испортит, зато дает неплохой шанс работы сайтов, до которых "плохой" пакет дойдет по TTL. +Если не удается найти автоматическое решение, воспользуйтесь файлом `ipset/zapret-hosts-user-exclude.txt`. +Некоторые стоковые прошивки роутеров фиксируют исходящий TTL, без отключения этой опции через них работать не будет. +**КАКИМ СТОИТ ВЫБИРАТЬ TTL**: найдите минимальное значение, при котором обход еще работает. Это и будет номер хопа вашего DPI. + +- `hopbyhop` относится только к IPv6. Добавляется IPv6 extension header "hop-by-hop options". + +В варианте `hopbyhop2` добавляются 2 хедера, что является нарушением стандарта и гарантированно отбрасывается стеком протоколов во всех ОС. +Один хедер hop-by-hop принимается всеми ОС, однако на некоторых каналах/провайдерах такие пакеты могут фильтроваться и не доходить. +Расчет идет на то, что DPI проанализирует пакет с hop-by-hop, но он либо не дойдет до адресата в силу фильтров провайдера, либо будет отброшен сервером, потому что хедера два. + +- `datanoack` высылает фейки со снятым TCP флагом ACK. Сервера такое не принимают, а DPI может принять. + +Эта техника может ломать NAT и не всегда работает с `iptables`, если используется masquerade, даже с локальной системы (почти всегда на роутерах IPv4). На системах c `iptables` без masquerade и на `nftables` работает без ограничений. +Экспериментально выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP. +Но Linux NAT оно не пройдет, так что за домашним роутером эта техника не сработает, но может сработать с него. + +- `autottl`. Суть режима в автоматическом определении TTL, чтобы он почти наверняка прошел DPI и немного не дошел до сервера. + +Берутся базовые значения TTL 64,128,255, смотрится входящий пакет (да, требуется направить первый входящий пакет на `nfqws`!). Вычисляется длина пути, отнимается delta (1 по умолчанию). +Если TTL вне диапазона (min,max - 3,20 по умолчанию), то берутся значения min,max, чтобы вписаться в диапазон. Если при этом полученный TTL больше длины пути, то автоматизм не сработал и берутся фиксированные значения TTL для атаки. +Техника позволяет решить вопрос, когда вся сеть перегорожена шлагбаумами (DPI, ТСПУ) везде где только можно, включая магистралов. Но потенциально может давать сбои. Например, при асимметрии входящего и исходящего канала до конкретного сервера. +На каких-то провайдерах эта техника будет работать неплохо, на других доставит больше проблем, чем пользы. +Где-то может потребоваться тюнинг параметров. Лучше использовать с дополнительным ограничителем. + +Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую. + +Для режимов `fake`, `rst`, `rstack` после фейка отправляем оригинальный пакет. + +Режим `disorder` делит оригинальный пакет на 2 части и отправляет следующую комбинацию в указанном порядке: + +1. 2-я часть пакета +2. поддельная 1-я часть пакета, поле данных заполнено нулями +3. 1-я часть пакета +4. поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз. + +Оригинальный пакет дропается всегда. +Параметр `--dpi-desync-split-pos` позволяет указать байтовую позицию, на которой происходит разбивка. По умолчанию - 2. +Если позиция больше длины пакета, позиция выбирается 1. +Этой последовательностью для DPI максимально усложняется задача реконструкции начального сообщения, по которому принимается решение о блокировке. +Некоторым DPI хватит и TCP сегментов в неправильном порядке, поддельные части сделаны для дополнительной надежности и более сложных алгоритмов реконструкции. + +Режим `disorder2` отключает отправку поддельных частей. + +Режим `split` очень похож на `disorder`, только нет изменения порядка следования сегментов: + +1) поддельная 1-я часть пакета, поле данных заполнено нулями +2) 1-я часть пакета +3) поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз. +4) 2-я часть пакета + +Режим `split2` отключает отправку поддельных частей. +Он может быть использован как более быстрая альтернатива `--wsize`. + +`disorder2` и `split2` не предполагают отсылку фейк пакетов, поэтому опции `ttl` и `fooling` неактуальны. + +`seqovl` добавляет в начало первой отсылаемой части оригинального пакета (1 часть для `split` и 2 часть для `disorder`) +seqovl байт со смещенным в минус sequence number на величину seqovl. +В случае `split2` расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, +поэтому новая пришедшая часть лишь частично находится в пределах текущего окна (in-window). +Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и начинается с начала window, +поэтому попадает в сокет. +Серверное приложение получает все, что реально отсылает клиент, отбрасывая фейковую out-of-window часть. +Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация. + +Для `disorder2` overlap идет на 2-ю часть пакета. Обязательно, чтобы seqovl был меньше split_pos, иначе все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня. +При соблюдении этого условия 2-я часть пакета является полностью in-window, поэтому серверная ОС принимает ее целиком, включая фейк. Но поскольку начальная часть данных из 1 пакета еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение. +Как только приходит 1-я часть пакета, она переписывает фейковую часть в памяти ядра. Ядро получает данные из 1 и 2 части, поэтому далее идет отправка в сокет приложения. +Таково поведение всех Unix ОС, кроме Solaris - оставлять последние принятые данные. +Windows оставляет старые данные, поэтому `disorder` с seqovl будет приводить к зависаниям соединения при работе с Windows серверами. Solaris практически мертв, Windows серверов очень немного. +Можно использовать листы при необходимости. +Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными. +`split`/`disorder` вместо `split2`/`disorder2` по-прежнему добавляют дополнительные отдельные фейки. + +Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с `fooling`!) относятся только к IPv6 и заключается в добавлении хедера "hop-by-hop options", "destination options" или "fragment" во все пакеты, попадающие под десинхронизацию. +Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено к пакетам максимального размера. Это имеет место при передаче больших сообщений. +В случае невозможности отослать пакет дурение будет отменено, пакет будет выслан в оригинале. +Расчет идет на то, что DPI увидит 0 в поле next header основного заголовка IPv6 и не будет скакать по extension хедерам в поисках транспортного хедера. Таким образом не поймет, что это TCP или UDP, и пропустит пакет без анализа. Возможно, какие-то DPI на это купятся. +Может сочетаться с любыми режимами 2-й фазы, кроме варианта "ipfrag1+ipfrag2". +Например, `hopbyhop,split2` означает разбить TCP пакет на 2 сегмента, в каждый из них добавить hop-by-hop. +При `hopbyhop,ipfrag2` последовательность хедеров будет: `ipv6,hop-by-hop,fragment,tcp/udp`. +Режим `ipfrag1` может срабатывать не всегда без специальной подготовки. См. раздел [IP фрагментация](#ip-фрагментация). + +Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены. +Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1. +В варианте `disorder` обычно приходит сперва частичное подтверждение (SACK), потом полный ACK. +Если вместо ACK или SACK идет RST пакет с минимальной задержкой, то DPI вас отсекает еще на этапе вашего запроса. +Если RST идет после полного ACK спустя задержку, равную примерно пингу до сервера, тогда вероятно DPI реагирует на ответ сервера. +DPI может отстать от потока, если ClientHello его удовлетворил и не проверять ServerHello. +Тогда вам повезло. Вариант `fake` может сработать. +Если же он не отстает и упорно проверяет ServerHello, то можно попробовать заставить сервер высылать ServerHello частями через параметр `--wssize` (см. [conntrack](#conntrack)). +Если и это не помогает, то сделать с этим что-либо вряд ли возможно без помощи со стороны сервера. +Лучшее решение - **включить на сервере поддержку TLS 1.3**. В нем сертификат сервера передается в зашифрованном виде. +Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI. + +Хосты извлекаются из `Host:` хедера обычных HTTP запросов и из SNI в `TLS Client`Hello. +Субдомены учитываются автоматически. Поддерживаются листы gzip. + +`iptables` для задействования атаки на первый пакет данных : + +```sh +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass +``` + +Этот вариант применяем, когда DPI не следит за всеми запросами HTTP внутри keep-alive сессии. +Если следит, направляем только первый пакет от HTTPS и все пакеты от HTTP : + +```sh +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass +iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass +``` + +mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку.`nfqws` выставляет fwmark при его отсылке. +Хотя `nfqws` способен самостоятельно различать помеченные пакеты, фильтр в `iptables` по mark нужен при использовании connbytes, чтобы не допустить изменения порядка следования пакетов. Процессинг очереди - процесс отложенный. +Если ядро имеет пакеты на отсылку вне очереди - оно их отправляет незамедлительно. +Изменение правильного порядка следования пакетов при десинхронизации ломает всю идею. +При отсутствии ограничения на connbytes, атака будет работать и без фильтра по mark. +Но лучше его все же оставить для увеличения скорости. + +Почему `--connbytes 1:6`: + +- 1 - для работы методов десинхронизации 0-й фазы и wssize +- 2 - иногда данные идут в 3-м пакете 3-way handshake +- 3 - стандартная ситуация приема одного пакета запроса +- 4-6 - на случай ретрансмиссии или запроса длиной в несколько пакетов (TLSClientHello с kyber, например) + +### Комбинирование методов десинхронизации + +В параметре `--dpi-desync` можно указать до 3 режимов через запятую. +0 фаза предполагает работу на этапе установления соединения. Может быть `synack` или `syndata`. +На 0 фазу не действует фильтр по hostlist. +Последующие режимы отрабатывают на пакетах с данными. +Режим 1-й фазы может быть `fake`, `rst`, `rstack`. Режим 2-й фазы может быть `disorder`, `disorder2`, `split`, `split2`, `ipfrag2`. +Может быть полезно, когда у провайдера стоит не один DPI. + +### Режим SYNACK + +В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно +ролей клиента и сервера. +**ВАЖНО:** Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством +и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него. +Для реализации атаки в Linux обязательно требуется отключить стандартное правило firewall, +дропающее инвалидные пакеты в цепочке OUTPUT. Например: `-A OUTPUT -m state --state INVALID -j DROP` +В OpenWrt можно отключить drop INVALID в OUTPUT и FORWARD через опцию в `/etc/config/firewall`: + +``` +config zone + option name 'wan' + ......... + option masq_allow_invalid '1' +``` + +К сожалению, отключить только в OUTPUT таким образом нельзя. Но можно сделать иначе. Вписать в `/etc/firewall.user`: + +```sh +iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT +ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT +``` + +Лучше делать так, потому что отсутствие дропа INVALID в FORWARD может привести к нежелательным утечкам пакетов из LAN. +Если не принять эти меры, отсылка SYN,ACK сегмента вызовет ошибку и операция будет прервана. +Остальные режимы тоже не сработают. Если поймете, что вам `synack` не нужен, обязательно верните правило дропа INVALID. + +### Режим SYNDATA + +Тут все просто. Добавляются данные в пакет SYN. Все ОС их игнорируют, если не используется TCP fast open (TFO), +а DPI может воспринять, не разобравшись есть там TFO или нет. +Оригинальные соединения с TFO не трогаются, поскольку это их точно сломает. +Без уточняющего параметра добавляются 16 нулевых байтов. + +### Виртуальные машины + +Изнутри VM от VirtualBox и VMware в режиме NAT не работают многие техники пакетной магии `nfqws`. +Принудительно заменяется TTL, не проходят фейк пакеты. Необходимо настроить сеть в режиме bridge. + +### conntrack + +`nfqws` оснащен ограниченной реализацией слежения за состоянием TCP соединений (conntrack). +Он включается для реализации некоторых методов противодействия DPI. +conntrack способен следить за фазой соединения: SYN,ESTABLISHED,FIN, количеством пакетов в каждую сторону, sequence numbers. conntrack способен "кормиться" пакетами в обе или только в одну сторону. +Соединение попадает в таблицу при обнаружении пакетов с выставленными флагами SYN или SYN,ACK. +Поэтому если необходим conntrack, в правилах перенаправления `iptables` соединение должно идти на nfqws с самого первого пакета, хотя затем может обрываться по фильтру connbytes. +Для UDP инициатором попадания в таблицу является первый UDP пакет. Он же и определяет направление потока. +Считается, что первый UDP пакет исходит от клиента к серверу. Далее все пакеты с совпадающими src_ip,src_port,dst_ip,dst_port считаются принадлежащими этому потоку до истечения времени неактивности. +conntrack - простенький, он не писался с учетом всевозможных атак на соединение, он не проверяет пакеты на валидность sequence numbers или чексумму. Его задача - лишь обслуживание нужд `nfqws`, он обычно кормится только исходящим трафиком, потому нечувствителен к подменам со стороны внешней сети. +Соединение удаляется из таблицы, как только отпадает нужда в слежении за ним или по таймауту неактивности. +Существуют отдельные таймауты на каждую фазу соединения. Они могут быть изменены параметром `--ctrack-timeouts`. + +`--wssize` позволяет изменить с клиента размер TCP window для сервера, чтобы он послал следующие ответы разбитыми на части. +Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения, ответ на который должен быть разбит (например, TLS ClientHello). +Именно поэтому и необходим conntrack, чтобы знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. +В Linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. +В случае HTTPS(S) останавливаемся сразу после отсылки первого HTTP запроса или TLS ClientHello. +Если вы имеете дело с не HTTPS(S), то вам потребуется параметр `--wssize-cutoff`. Он устанавливает предел, с которого действие wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number, проще говоря, количество переданных клиентом байтов + 1. +Если проскочит пакет с HTTP request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff. +Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр `--ctrack-timeouts`. +Таймаут по умолчанию низкий - всего 5 минут. +Не забывайте, что nfqws кормится приходящими на него пакетами. Если вы ограничили поступление пакетов через connbytes, то в таблице могут остаться повисшие соединения в фазе ESTABLISHED, которые отвалятся только по таймауту. +Для диагностики состояния conntrack пошлите сигнал SIGUSR1 процессу nfqws: killall -SIGUSR1 nfqws. +Текущая таблица будет выведена nfqws в stdout. + +Обычно в SYN пакете клиент отсылает кроме window size еще и TCP extension "scaling factor". +scaling factor представляет из себя степень двойки, на которую умножается window size: 0=>1, 1=>2, 2=>4, ..., 8=>256, ... +В параметре wssize scaling factor указывается через двоеточие. +Scaling factor может только снижаться, увеличение заблокировано, чтобы не допустить превышение размера окна со стороны сервера. +Для принуждения сервера к фрагментации ServerHello, чтобы избежать просекание имени сервера из сертификата сервера на DPI, лучше всего использовать `--wssize=1:6`. Основное правило - делать scale_factor как можно больше, чтобы после восстановления +window size итоговый размер окна стал максимально возможным. Если вы сделаете 64:0, будет очень медленно. +С другой стороны нельзя допустить, чтобы ответ сервера стал достаточно большим, чтобы DPI нашел там искомое. + +На `--wssize` не влияет фильтр hostlist, поскольку он действует с самого начала соединения, когда еще нельзя принять решение о попадании в лист. +`--wssize` может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы обхода DPI, лучше применять их. + +`--dpi-desync-cutoff` позволяет задать предел, при достижении которого прекращается применение dpi-desync. +Доступны префиксы n,d,s по аналогии с `--wssize-cutoff`. +Полезно совместно с `--dpi-desync-any-protocol=1`. +На склонных к бездействию соединениях следует изменить таймауты conntrack. +Если соединение выпало из conntrack и задана опция `--dpi-desync-cutoff`, dpi desync применяться не будет. + +### Реассемблинг + +`nfqws` поддерживает реассемблинг некоторых видов запросов. +На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в Chrome включить пост-квантовую криптографию TLS-Kyber, и занимают как правило 2 или 3 пакета. Kyber включен по умолчанию, начиная с Chromium 124. +Chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть попасть любой пакет. Stateful DPI обычно реассемблирует запрос целиком, и только потом принимает решение о блокировке. +В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию на основании полностью собранного ClientHello. +При любой ошибке в процессе сборки задержанные пакеты немедленно отсылаются в сеть, а десинхронизация отменяется. + +Есть специальная поддержка всех вариантов TCP сплита для многосегментного TLS. +Если указать позицию сплита больше длины первого пакета или использовать `--dpi-desync-split-tls`, то разбивка происходит не обязательно первого пакета, а того, на который пришлась итоговая позиция. +Если, допустим, клиент послал TLS ClientHello длиной 2000, а SNI начинается с 1700, и заданы опции `fake,split2`, то перед первым пакетом идет `fake`, затем первый пакет в оригинале, а последний пакет разбивается на 2 сегмента. В итоге имеем фейк в начале и 3 реальных сегмента. + +### Поддержка UDP + +Атаки на UDP более ограничены в возможностях. UDP нельзя фрагментировать иначе, чем на уровне IP. +Для UDP действуют только режимы десинхронизации `fake`, `hopbyhop`, `destopt`, `ipfrag1`, `ipfrag2`, `udplen`, `tamper`. +Возможно сочетание `fake`, `hopbyhop`, `destopt` с `ipfrag2`, `fake`, `fakeknown` с `udplen` и `tamper`. +`udplen` увеличивает размер UDP пакета на указанное в `--dpi-desync-udplen-increment` количество байтов. +Паддинг заполняется нулями по умолчанию, но можно задать свой паттерн. +Предназначено для обмана DPI, ориентирующегося на размеры пакетов. +Может сработать, если пользовательский протокол не привязан жестко к размеру UDP пейлоада. +Режим `tamper` означает модификацию пакетов известных протоколов особенным для протокола образом. +На текущий момент работает только с DHT. +Поддерживается определение пакетов QUIC Initial с расшифровкой содержимого и имени хоста, то есть параметр +`--hostlist` будет работать. +Определяются пакеты WireGuard handshake initiation и DHT (начинается с 'd1', кончается 'e'). +Для десинхронизации других протоколов обязательно указывать `--dpi-desync-any-protocol`. +Реализован conntrack для UDP. Можно пользоваться `--dpi-desync-cutoff`. +Таймаут conntrack для UDP можно изменить 4-м параметром в `--ctrack-timeouts`. +Атака `fake` полезна только для stateful DPI, она бесполезна для анализа на уровне отдельных пакетов. +По умолчанию fake наполнение - 64 нуля. Можно указать файл в `--dpi-desync-fake-unknown-udp`. + +### IP фрагментация + +Современная сеть практически не пропускает фрагментированные TCP на уровне IP. +На UDP с этим дело получше, поскольку некоторые UDP протоколы могут опираться на этот механизм (IKE старых версий). +Однако, кое-где бывает, что режут и фрагментированный UDP. +Роутеры на базе Linux могут самопроизвольно собирать или перефрагментировать пакеты. +Позиция фрагментации задается отдельно для TCP и UDP. По умолчанию 24 и 8 соответственно, должна быть кратна 8. +Смещение считается с транспортного заголовка. + +Существует ряд моментов вокруг работы с фрагментами на Linux, без понимания которых может ничего не получиться. + +- IPv4: Linux дает отсылать IPv4 фрагменты, но стандартные настройки `iptables` в цепочке OUTPUT могут вызывать ошибки отправки. + +- IPv6: Нет способа для приложения гарантированно отослать фрагменты без дефрагментации в conntrack. + +На разных системах получается по-разному. Где-то нормально уходят, где-то пакеты дефрагментируются. +Для ядер <4.16 похоже, что нет иного способа решить эту проблему, кроме как выгрузить модуль `nf_conntrack`, +который подтягивает зависимость `nf_defrag_ipv6`. Он то как раз и выполняет дефрагментацию. +Для ядер 4.16+ ситуация чуть лучше. Из дефрагментации исключаются пакеты в состоянии NOTRACK. +Чтобы не загромождать описание, смотрите пример решения этой проблемы в `blockcheck.sh`. + +Иногда требуется подгружать модуль `ip6table_raw` с параметром `raw_before_defrag=1`. +В OpenWrt параметры модулей указываются через пробел после их названий в файлах `/etc/modules.d`. +В традиционных системах посмотрите, используется ли `iptables-legacy` или `iptables-nft`. Если legacy, то нужно создать файл `/etc/modprobe.d/ip6table_raw.conf` с содержимым: +`options ip6table_raw raw_before_defrag=1` + +В некоторых традиционных дистрибутивах можно изменить текущий `ip6tables` через: `update-alternatives --config ip6tables` +Если вы хотите оставаться на `iptables-nft`, вам придется пересобрать патченную версию. Патч совсем небольшой. + +В `nft.c` найдите фрагмент: + +```c + { + .name = "PREROUTING", + .type = "filter", + .prio = -300, /* NF_IP_PRI_RAW */ + .hook = NF_INET_PRE_ROUTING, + }, + { + .name = "OUTPUT", + .type = "filter", + .prio = -300, /* NF_IP_PRI_RAW */ + .hook = NF_INET_LOCAL_OUT, + }, +``` + +и замените везде -300 на -450. + +Это нужно сделать вручную, никакой автоматики в `blockcheck.sh` нет. + +Либо можно раз и навсегда избавиться от этой проблемы, используя `nftables`. Там можно создать netfilter hook +с любым приоритетом. Используйте приоритет -401 и ниже. + +При использовании `iptables` и NAT, похоже, что нет способа прицепить обработчик очереди после NAT. +Пакет попадает в `nfqws` с source адресом внутренней сети, затем фрагментируется и уже не обрабатывается NAT. +Так и уходит во внешнюю сеть с src ip 192.168.x.x. Следовательно, метод не срабатывает. +Видимо единственный рабочий метод - отказаться от `iptables` и использовать `nftables`. +Хук должен быть с приоритетом 101 или выше. + +## `tpws` + +`tpws` - это transparent proxy. + +``` +--debug=0|1|2|syslog|@ ; 0,1,2 = логирование на консоль: 0=тихо, 1(default)=подробно, 2=отладка. +--debug-level=0|1|2 ; указать уровень логирования для syslog и @ +--daemon ; демонизировать прогу +--pidfile= ; сохранить PID в файл +--user= ; менять uid процесса +--uid=uid[:gid] ; менять uid процесса +--bind-addr ; на каком адресе слушать. может быть IPv4 или IPv6 адрес + ; если указан IPv6 link local, то требуется указать, с какого он интерфейса: fe80::1%br-lan +--bind-linklocal=no|unwanted|prefer|force + ; no: биндиться только на global IPv6 + ; unwanted (default): предпочтительно global, если нет - LL + ; prefer: предпочтительно LL, если нет - global + ; force: биндиться только на LL +--bind-iface4= ; слушать на первом IPv4 интерфейса iface +--bind-iface6= ; слушать на первом IPv6 интерфейса iface +--bind-wait-ifup= ; ждать до N секунд появления и поднятия интерфейса +--bind-wait-ip= ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса) +--bind-wait-ip-linklocal= + ; имеет смысл только при задании --bind-wait-ip + ; --bind-linklocal=unwanted: согласиться на LL после N секунд + ; --bind-linklocal=prefer: согласиться на global address после N секунд +--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0. +--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть IPv4 или IPv6 адрес + ; если указан IPv6 link local, то требуется указать с какого он интерфейса: fe80::1%br-lan + ; опция может повторяться для v4 и v6 адресов + ; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local. +--socks ; вместо прозрачного прокси реализовать socks4/5 proxy +--no-resolve ; запретить ресолвинг имен через socks5 +--resolve-threads ; количество потоков ресолвера +--port= ; на каком порту слушать +--maxconn= ; максимальное количество соединений от клиентов к прокси +--maxfiles= ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга. + ; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16 +--max-orphan-time= ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений, + ; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...) + ; установление соединения в Linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных, + ; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго. + ; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию + ; эта функция не действует на успешно подключенные ранее соединения +--local-rcvbuf= ; SO_RCVBUF для соединений client-proxy +--local-sndbuf= ; SO_SNDBUF для соединений client-proxy +--remote-rcvbuf= ; SO_RCVBUF для соединений proxy-target +--remote-sndbuf= ; SO_SNDBUF для соединений proxy-target +--nosplice ; не использовать splice на Linux системах +--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split. +--local-tcp-user-timeout= ; таймаут соединений client-proxy (по умолчанию: 10 сек, 0 = оставить системное значение) +--remote-tcp-user-timeout= ; таймаут соединений proxy-target (по умолчанию: 20 сек, 0 = оставить системное значение) +--split-http-req=method|host ; способ разделения HTTP запросов на сегменты: около метода (GET,POST) или около заголовка Host +--split-pos= ; делить все посылы на сегменты в указанной позиции. единственная опция, работающая на не-HTTP. при указании split-http-req он имеет преимущество на HTTP. +--split-any-protocol ; применять split-pos к любым пакетам. по умолчанию - только к HTTP и TLS ClientHello +--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса +--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита +--oob-data=|0xHEX ; переопределить байт OOB. по умолчанию 0x00. +--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:". +--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase +--hostdot ; добавление точки после имени хоста: "Host: kinozal.tv." +--hosttab ; добавление табуляции после имени хоста: "Host: kinozal.tv\t" +--hostnospace ; убрать пробел после "Host:" +--hostpad= ; добавить паддинг-хедеров общей длиной перед Host: +--domcase ; домен после Host: сделать таким: TeSt.cOm +--methodspace ; добавить пробел после метода: "GET /" => "GET /" +--methodeol ; добавить перевод строки перед методом: "GET /" => "\r\nGET /" +--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A +--tlsrec=sni|sniext ; разбивка TLS ClientHello на 2 TLS records. режем между 1 и 2 символами hostname в SNI или между байтами длины SNI extension. Если SNI нет - отмена. +--tlsrec-pos= ; разбивка TLS ClientHello на 2 TLS records. режем на указанной позиции, если длина слишком мелкая - на позиции 1. +--mss= ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость +--mss-pf=[~]port1[-port2] ; применять MSS только к портам назначения, подпадающим под фильтр. ~ означает инверсию +--tamper-start=[n] ; начинать дурение только с указанной байтовой позиции или номера блока исходящего потока (считается позиция начала принятого блока) +--tamper-cutoff=[n] ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока) +--hostlist= ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. + ; в файле должен быть хост на каждой строке. + ; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. + ; по сигналу HUP список будет перечитан при следующем принятом соединении + ; список может быть запакован в gzip. формат автоматически распознается и разжимается + ; списков может быть множество, они объединяются. пустой общий лист = его отсутствие + ; хосты извлекаются из Host: хедера обычных HTTP запросов и из SNI в TLS ClientHello. +--hostlist-exclude= ; не применять дурение к доменам из листа. может быть множество листов, они объединяются +--hostlist-auto= ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) +--hostlist-auto-fail-threshold= ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) +--hostlist-auto-fail-time= ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) +--hostlist-auto-debug= ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. +``` + +`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. +Может быть важен порядок следования опций. `--debug` лучше всего указывать в самом начале. +Опции анализируются последовательно. Если ошибка будет при проверке опции, а до анализа `--debug` еще дело не дошло, то сообщения не будут выведены в файл или `syslog`. +`--debug=0|1|2` позволяют сразу в одном параметре включить логирование на консоль и указать уровень. +Сохранено для совместимости с более старыми версиями. Для выбора уровня в режиме syslog или file используйте +отдельный параметр `--debug-level`. Если в этих режимах `--debug` не указывать уровень через `--debug-level`, то +автоматически назначается уровень 1. +При логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается. +Так что файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог. +Но имейте в виду, что если вы запускаете процесс под root, то будет сменен UID на не-root. +В начале на лог файл меняется owner, иначе запись будет невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не будет вестись. +Вместо удаления лучше использовать truncate. +В шелле это можно сделать через команду `: > filename` + +Параметры манипуляции могут сочетаться в любых комбинациях. + +В случае HTTP запроса `split-http-req` имеет преимущество над `split-pos`. +`split-pos` по умолчанию работает только на HTTP и TLS ClientHello. +Чтобы он работал на любых пакетах, укажите `--split-any-protocol`. + +На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета. +Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет. +Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему, никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии, что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI. +Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса. +Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае. +Протокол HTTP относится к запрос-ответным протоколам. Новое сообщение посылается только тогда, когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан, но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут к отсылке сегментов данных разными IP пакетами. +Резюме: tpws гарантирует сплит только за счет раздельных вызовов send, что на практике вполне достаточно для протоколов HTTPS(S). + +`tpws` может биндиться на множество интерфейсов и IP адресов (до 32 шт). +Порт всегда только один. +Параметры `--bind-iface*` и `--bind-addr` создают новый бинд. +Остальные параметры `--bind-*` относятся к последнему бинду. +Для бинда на все IPv4 укажите `--bind-addr "0.0.0.0"`, на все IPv6 - `::`. `--bind-addr=""` - биндимся на все IPv4 и IPv6. +Выбор режима использования link local IPv6 адресов (fe80::/8): + +- `--bind-iface6 --bind-linklocal=no`: сначала приватный адрес fc00::/7, затем глобальный адрес +- `--bind-iface6 --bind-linklocal=unwanted`: сначала приватный адрес fc00::/7, затем глобальный адрес, затем link local. +- `--bind-iface6 --bind-linklocal=prefer`: сначала link local, затем приватный адрес fc00::/7, затем глобальный адрес. +- `--bind-iface6 --bind-linklocal=force`: только link local + +Если не указано ни одного бинда, то создается бинд по умолчанию на все адреса всех интерфейсов. +Для бинда на конкретный link-local address делаем так: `--bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name` +Параметры `--bind-wait*` могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят или не сконфигурирован. +В разных системах события ifup ловятся по-разному и не гарантируют, что интерфейс уже получил IP адрес определенного типа. +В общем случае не существует единого механизма повеситься на событие типа "на интерфейсе X появился link local address". +Для бинда на известный ip, когда еще интерфейс не сконфигурирован, нужно делать так: `--bind-addr=192.168.5.3 --bind-wait-ip=20` +В режиме transparent бинд возможен на любой несуществующий адрес, в режиме SOCKS - только на существующий. + +Параметры `rcvbuf` и `sndbuf` позволяют установить setsockopt SO_RCVBUF SO_SNDBUF для локального и удаленного соединения. + +Если не указан ни один из параметров модификации содержимого, `tpws` работает в режиме "TCP proxy mode". +Он отличается тем, что в оба конца применяется splice для переброски данных из одного сокета в другой без копирования в память процесса. Практически - это то же самое, но может быть чуть побыстрее. +TCP проксирование может быть полезно для обхода блокировок, когда DPI спотыкается на экзотических хедерах IP или TCP. Вы вряд ли сможете поправить хедеры, исходящие от айфончиков и гаджетиков, но на Linux сможете влиять на них в какой-то степени через sysctl. +Когда соединение проходит через `tpws`, фактически прокси-сервер сам устанавливает подключение к удаленному узлу от своего имени, и на это распространяются настройки системы, на которой работает прокси. +`tpws` можно использовать на мобильном устройстве, раздающем интернет на тарифе сотового оператора, где раздача запрещена, в SOCKS режиме даже без рута. Соединения от `tpws` неотличимы от соединений с самого раздающего устройства. Отличить можно только по содержанию (типа обновлений Windows). +Заодно можно и обойти блокировки. 2 зайца одним выстрелом. +Более подробную информацию по вопросу обхода ограничений операторов гуглите на [4pda](https://4pda.ru/). + +Режим `--socks` не требует повышенных привилегий (кроме бинда на привилегированные порты 1..1023). +Поддерживаются версии SOCKS 4 и 5 без авторизации. Версия протокола распознается автоматически. +Подключения к IP того же устройства, на котором работает `tpws`, включая localhost, запрещены. +SOCKS5 позволяет удаленно ресолвить хосты (`curl`: `--socks5-hostname`, Firefox: `socks_remote_dns=true`). +`tpws` поддерживает эту возможность асинхронно, не блокируя процессинг других соединений, используя многопоточный пул ресолверов. Количество потоков определяется автоматически в зависимости от `--maxconn`, но можно задать и вручную через параметр `--resolver-threads`. +Запрос к SOCKS выставляется на паузу, пока домен не будет преобразован в ip адрес в одном из потоков ресолвера. Ожидание может быть более длинным, если все потоки заняты. +Если задан параметр `--no-resolve`, то подключения по именам хостов запрещаются, а пул ресолверов не создается, тем самым экономятся ресурсы. + +Параметр `--hostpad=` добавляет паддинг-хедеров перед Host: на указанное количество байтов. +Если размер `` слишком большой, то идет разбивка на разные хедеры по 2K. +Общий буфер приема HTTP запроса - 64K, больший паддинг не поддерживается, да и HTTP сервера такое уже не принимают. +Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером. +Если техника работает, то после некоторого количества bytes HTTP запрос начнет проходить до сайта. +Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции `--split-...` +Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения. + +`--disorder` - это попытка симулировать режим `disorder2` из `nfqws`, используя особенности ОС по реализации stream сокетов. +Однако, в отличие от `nfqws`, здесь не требуются повышенные привилегии. +Реализовано это следующим образом. У сокета есть возможность выставить TTL. Все пакеты будут отправляться с ним. +Перед отправкой первого сегмента ставим TTL=1. Пакет будет дропнут на первом же роутере, он не дойдет ни до DPI, ни до сервера. +Затем возвращаем TTL в значение по умолчанию. ОС отсылает второй сегмент, и он уже доходит до сервера. +Сервер возвращает SACK, потому что не получил первый кусок, и ОС его отправляет повторно, но здесь уже мы ничего не делаем. +Этот режим работает как ожидается на Linux и macOS. Однако, на FreeBSD и OpenBSD он работает не так хорошо. +Ядро этих ОС отсылает ретрансмиссию в виде полного пакета. Потому выходит, что до сервера идет сначала второй кусок, а потом полный запрос без сплита. На него может отреагировать DPI штатным образом. +`--disorder` является дополнительным флагом к любому сплиту. Сам по себе он не делает ничего. + +`--tlsrec` и `--tlsrec-pos` позволяют внутри одного TCP сегмента разрезать TLS ClientHello на 2 TLS records. +`--tlsrec=sni` режет между 1 и 2 символами hostname в SNI, делая невозможным бинарный поиск паттерна без анализа +структуры данных. В случае отсутствия SNI разбиение отменяется. +`--tlsrec-pos` режет на указанной позиции. Если длина блока данных TLS меньше указанной позиции, режем на позиции 1. +Параметр сочетается с `--split-pos`. В этом случае происходит сначала разделение на уровне TLS record layer, потом на уровне TCP. +Самая изощрённая атака `--tlsrec`, `--split-pos` и `--disorder` вместе. +`--tlsrec` ломает значительное количество сайтов. Криптобиблиотеки (`openssl`, ...) на оконечных HTTP серверах +без проблем принимают разделенные TLS сегменты, но мидлбоксы - не всегда. К мидлбоксам можно отнести CDN +или системы DDoS-защиты. Поэтому применение `--tlsrec` без ограничителей вряд ли целесообразно. +В РФ `--tlsrec` обычно не работает с TLS 1.2, потому что цензор парсит сертификат сервера из ServerHello. +Работает только с TLS 1.3, поскольку там эта информация шифруется. +Впрочем, сейчас сайтов, не поддерживающих TLS 1.3, осталось немного. + +`--mss` устанавливает опцию сокета TCP_MAXSEG. Клиент выдает это значение в TCP опциях SYN пакета. +Сервер в ответ в SYN,ACK выдает свой MSS. На практике сервера обычно снижают размеры отсылаемых ими пакетов, но они все равно не вписываются в низкий MSS, указанный клиентом. Обычно чем больше указал клиент, тем больше шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет, это может обмануть DPI, секущий ответ сервера. +Схема может значительно снизить скорость и сработать не на всех сайтах. +С фильтром по hostlist совместимо только в режиме SOCKS при включенном удаленном ресолвинге хостов. +(Firefox: `network.proxy.socks_remote_dns`). Это единственный вариант, когда `tpws` может узнать имя хоста еще на этапе установления соединения. +Невозможен фильтр по версии TLS. +Взамен имеется фильтр по портам `--mss-pf`. `--mss-pf=443` применяет дурение только к HTTPS. +Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже. +Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в +3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который может привести к реакции DPI. +Использовать только когда нет ничего лучше или для отдельных ресурсов. +Работает только на Linux, не работает на BSD и macOS. + +`--skip-nodelay` может быть полезен, чтобы привести MTU к MTU системы, на которой работает tpws. +Это может быть полезно для скрытия факта использования VPN. Пониженный MTU - 1 из способов обнаружения подозрительного подключения. С TCP proxy ваши соединения неотличимы от тех, что сделал бы сам шлюз. + +`--local-tcp-user-timeout` и `--remote-tcp-user-timeout` устанавливают значение таймаута в секундах для соединений клиент-прокси и прокси-сервер. Этот таймаут соответствует опции сокета Linux TCP_USER_TIMEOUT. Под таймаутом подразумевается время, в течение которого буферизированные данные не переданы или на переданные данные не получено подтверждение (ACK) от другой стороны. +Этот таймаут никак не касается времени отсутствия какой-либо передачи через сокет лишь потому, что данных для передачи нет. Полезно для сокращения время закрытия подвисших соединений. +Поддерживается только на Linux и macOS. + +## Способы получения списка заблокированных IP + +**ВАЖНО:** nftables не могут работать с ipset-ами. Собственный аналогичный механизм требует огромного количество RAM для загрузки больших листов. Например, для загона 100K записей в `nfset` не хватает даже 256 Mb. Если вам нужны большие листы на домашних роутерах, откатывайтесь на `iptables`+`ipset`. + +1) Внесите заблокированные домены в `ipset/zapret-hosts-user.txt` и запустите `ipset/get_user.sh`. На выходе получите `ipset/zapret-ip-user.txt` с IP адресами. + +Cкрипты с названием `get_reestr_*` оперируют дампом реестра заблокированных сайтов: + +2) `ipset/get_reestr_resolve.sh` получает список доменов от [rublacklist](https://reestr.rublacklist.net/) и дальше их ресолвит в IP адреса в файл `ipset/zapret-ip.txt.gz`. + +В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде, +что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко +банят по IP: вместо этого они банят HTTP запросы с "нехорошим" заголовком `Host:` вне зависимости +от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени. +Используется мультипоточный ресолвер `mdig` (собственная разработка). + +3) `ipset/get_reestr_preresolved.sh`. То же самое, что и 2), только берется уже заресолвленый список +со стороннего ресурса. + +4) `ipset/get_reestr_preresolved_smart.sh`. То же самое, что и 3), с добавлением всего диапазона некоторых +автономных систем (прыгающие IP адреса из CloudFlare, Facebook, ...) и некоторых поддоменов блокируемых сайтов. + +Cкрипты с названием `get_antifilter_*` оперируют списками адресов и масок подсетей с сайтов [antifilter.network](https://antifilter.network) и [antifilter.download](https://antifilter.network): + +5) `ipset/get_antifilter_ip.sh`. Получает лист [https://antifilter.download/list/ip.lst](https://antifilter.download/list/ip.lst). + +6) `ipset/get_antifilter_ipsmart.sh`. Получает лист [https://antifilter.network/list/ipsmart.lst](https://antifilter.download/list/ipsmart.lst). +Умная суммаризация отдельных адресов из `ip.lst` по маскам от /32 до /22 + +7) `ipset/get_antifilter_ipsum.sh`. Получает лист [https://antifilter.download/list/ipsum.lst](https://antifilter.download/list/ipsum.lst). +Суммаризация отдельных адресов из `ip.lst` по маске /24 + +8) `ipset/get_antifilter_ipresolve.sh`. Получает лист [https://antifilter.download/list/ipresolve.lst](https://antifilter.download/list/ipresolve.lst). +Прересолвленный список, аналогичный получаемый при помощи `get_reestr_resolve.sh`. Только IPv4. + +9) `ipset/get_antifilter_allyouneed.sh`. Получает лист [https://antifilter.download/list/allyouneed.lst](https://antifilter.download/list/allyouneed.lst). +Суммарный список префиксов, созданный из `ipsum.lst` и `subnet.lst`. + +Все варианты рассмотренных скриптов автоматически создают и заполняют ipset. +Варианты 2-9 дополнительно вызывают вариант 1. + +10) `ipset/get_config.sh`. этот скрипт вызывает то, что прописано в переменной `GETLIST` из файла `config` +Если переменная не определена, то ресолвятся лишь листы для ipset nozapret/nozapret6. + +Листы РКН все время изменяются. Возникают новые тенденции. Требования к RAM могут меняться. +Поэтому необходима нечастая, но все же регулярная ревизия что же вообще у вас происходит на роутере. +Или вы можете узнать о проблеме лишь когда у вас начнет постоянно пропадать Wi-Fi, и вам придется его перезагружать каждые 2 часа (метод кувалды). + +Самые щадящие варианты по RAM - `get_antifilter_allyouneed.sh`, `get_antifilter_ipsum.sh`. + +Листы `zapret-ip.txt` и `zapret-ipban.txt` сохраняются в сжатом виде в файлы .gz. +Это позволяет снизить их размер во много раз и сэкономить место на роутере. +Отключить сжатие листов можно параметром конфига `GZIP_LISTS=0`. + +На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку. +В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней флэш памятью, то вы просто убьете роутер. + +Принудительное обновление ipset выполняет скрипт `ipset/create_ipset.sh`. +Если передан параметр "no-update", скрипт не обновляет ipset, а только создает его при его отсутствии и заполняет. +Это полезно, когда могут случиться несколько последовательных вызовов скрипта. Нет смысла несколько раз перезаполнять ipset, это длительная операция на больших листах. Листы можно обновлять раз в несколько суток, и только тогда вызывать `create_ipset` без параметра `no-update`. Во всех остальных случаях стоит применять `no-update`. + +Список РКН уже достиг внушительных размеров в сотни тысяч IP адресов. Поэтому для оптимизации ipset применяется утилита `ip2net`. Она берет список отдельных IP адресов и пытается интеллектуально создать из него подсети для сокращения количества адресов. +`ip2net` отсекает неправильные записи в листах, гарантируя отсутствие ошибок при их загрузке. +`ip2net` написан на языке C, поскольку операция ресурсоемкая. Иные способы роутер может не потянуть. + +Можно внести список доменов в `ipset/zapret-hosts-user-ipban.txt`. Их IP адреса будут помещены в отдельный ipset `ipban`. +Он может использоваться для принудительного завертывания всех соединений на прозрачный proxy `redsocks` или на VPN. + +### IPv6 + +Если включен IPv6, то дополнительно создаются листы с таким же именем, но с "6" на конце перед расширением: `zapret-ip.txt` => `zapret-ip6.txt`. +Создаются ipset-ы zapret6 и ipban6. +Листы с antifilter не содержат список IPv6 адресов. + +### Система исключения IP + +Все скрипты ресолвят файл `zapret-hosts-user-exclude.txt`, создавая `zapret-ip-exclude.txt` и `zapret-ip-exclude6.txt`. +Они загоняются в ipset-ы nozapret и nozapret6. Все правила, создаваемые init скриптами, создаются с учетом этих ipset. +Помещенные в них IP не участвуют в процессе. +`zapret-hosts-user-exclude.txt` может содержать домены, IPv4 и IPv6 адреса или подсети. + +### FreeBSD + +Скрипты `ipset/*.sh` работают так же на FreeBSD. Вместо ipset они создают lookup таблицы ipfw с аналогичными именами. +ipfw таблицы в отличие от ipset могут содержать как IPv4, так и IPv6 адреса и подсети в одной таблице, поэтому разделения нет. + +Параметр конфига LISTS_RELOAD задает произвольную команду для перезагрузки листов. +Это особенно полезно на BSD системах с PF. +`LISTS_RELOAD=-` отключает перезагрузку листов. + +## `ip2net` + +Утилита `ip2net` предназначена для преобразования IPv4 или IPv6 списка ip в список подсетей +с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в stdout. + +``` + -4 ; лист - IPv4 (по умолчанию) + -6 ; лист - IPv6 + --prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например: 22-30 (IPv4), 56-64 (IPv6) + --v4-threshold=mul/div ; IPv4: включать подсети, в которых заполнено по крайней мере mul/div адресов. например: 3/4 + --v6-threshold=N ; IPv6: минимальное количество ip для создания подсети +``` + +В списке могут присутствовать записи вида "IP/prefix" и "IP1-IP2". Такие записи выкидываются в stdout без изменений. +Они принимаются командой `ipset`. `ipset` умеет для листов hash:net из IP1-IP2 делать оптимальное покрытие IP/prefix. +`ipfw` из FreeBSD понимает ip/prefix, но не понимает IP1-IP2. +`ip2net` фильтрует входные данные, выкидывая неправильные IP адреса. + +Выбирается подсеть, в которой присутствует указанный минимум адресов. +Для IPv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для IPv6 минимум задается напрямую. + +Размер подсети выбирается следующим алгоритмом: +Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально. +Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше). +Например, заданы параметры `v6_threshold=2 prefix_length=32-64`, имеются следующие IPv6: + +``` +1234:5678:aaaa::5 +1234:5678:aaaa::6 +1234:5678:aaac::5 +``` + +Результат будет : + +``` +1234:5678:aaa8::/45 +``` + +Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой, +когда те же самые адреса вполне влезают в /45 и их ровно столько же. +Если изменить `v6_threshold=4`, то результат будет : + +``` +1234:5678:aaaa::5 +1234:5678:aaaa::6 +1234:5678:aaac::5 +``` + +То есть IP не объединятся в подсеть, потому что их слишком мало. +Если изменить `prefix_length=56-64`, результат будет : + +``` +1234:5678:aaaa::/64 +1234:5678:aaac::5 +``` + +Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа. +Если `ip2net` думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов. +Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем. +Не надо делать такое: 5000000/10000000. 1/2 - гораздо лучше. + +## Фильтрация по именам доменов + +Альтернативой `ipset` является использование `tpws` или `nfqws` со списком доменов. +Оба демона принимают неограниченное количество листов include (`--hostlist`) и exclude (`--hostlist-exclude`). +Все листы одного типа объединяются, и таким образом остаются только 2 листа. +Прежде всего проверяется exclude list. При вхождении в него происходит отказ от дурения. +Далее при наличии include list проверяется домен на вхождение в него. При невхождении в список отказ от дурения. +Пустой список приравнивается к его отсутствию. +В иных случаях происходит дурение: + +- Нет ни одного списка - дурение всегда. +- Есть только exclude список - дурение всех, кроме. +- Есть только include список - дурение только их. +- Есть оба - дурение только include, кроме exclude. + +В системе запуска это обыграно следующим образом. +Присутствуют 2 include списка : +`ipset/zapret-hosts-users.txt.gz` или `ipset/zapret-hosts-users.txt` +`ipset/zapret-hosts.txt.gz` или `ipset/zapret-hosts.txt` +и 1 exclude список +`ipset/zapret-hosts-users-exclude.txt.gz` или `ipset/zapret-hosts-users-exclude.txt` + +При режиме фильтрации `MODE_FILTER=hostlist` система запуска передает `nfqws` или `tpws` все листы, файлы которых присутствуют. +Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа. +Файл есть, но не смотря на это дурится все, кроме exclude. +Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым. + +Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает. + +Список доменов РКН может быть получен скриптами `ipset/get_reestr_hostlist.sh` или `ipset/get_antizapret_domains.sh` - кладется в `ipset/zapret-hosts.txt.gz`. + +Чтобы обновить списки, перезапускать `nfqws` или `tpws` не нужно. Обновляете файлы, затем даете сигнал HUP. +По HUP листы будут перечитаны. Если вдруг какого-то листа не окажется, процесс завершится с ошибкой. +Скрипты получения листов из ipset сами выдают HUP в конце. + +При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset. +`tpws` и `nfqws` решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (HTTP, TLS, QUIC). +При использовании больших списков, в том числе списка РКН, оцените объем RAM на роутере! +Если после запуска демона RAM под завязку или случаются oom, значит нужно отказаться от таких больших списков. + +## Режим фильтрации `autohostlist` + +Этот режим позволяет проанализировать как запросы со стороны клиента, так и ответы от сервера. +Если хост еще не находится ни в каких листах и обнаруживается ситуация, похожая на блокировку, происходит автоматическое добавление хоста в список autohostlist как в памяти, так и в файле. +`nfqws` или `tpws` сами ведут этот файл. +Чтобы какой-то хост не смог попась в autohostlist используйте `hostlist-exclude`. +Если он все-же туда попал - удалите запись из файла вручную. Процессы автоматически перечитают файл. +`tpws`/`nfqws` сами назначают владельцем файла юзера, под которым они работают после сброса привилегий, +чтобы иметь возможность обновлять лист. + +В случае `nfqws` данный режим требует перенаправления в том числе и входящего трафика. +Крайне рекомендовано использовать ограничитель connbytes, чтобы nfqws не обрабатывал гигабайты. +По этой же причине не рекомендуется использование режима на BSD системах. Там нет фильтра connbytes. + +На Linux системах при использовании `nfqws` и фильтра connbytes может понадобится: + +```sh +sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 +``` + +Было замечено, что некоторые DPI в России возвращают RST с неверным ACK. Это принимается TCP/IP стеком Linux, но через раз приобретает статус INVALID в conntrack. +Поэтому правила с connbytes срабатывают через раз, не пересылая RST пакет nfqws. + +Как вообще могут вести себя DPI, получив "плохой запрос" и приняв решение о блокировке : + +1) Зависание: просто отмораживается, блокируя прохождение пакетов по TCP каналу. +2) RST: отправляет RST клиенту и/или серверу +3) Редирект: (только для HTTP) отправляет редирект на сайт-заглушку +4) Подмена сертификата: (только для HTTPS) полный перехват TLS сеанса с попыткой всунуть что-то свое клиенту. Применяется нечасто, поскольку броузеры на такое ругаются. + +`nfqws` и `tpws` могут сечь варианты 1-3, 4 они не распознают. +Всилу специфики работы с отдельными пакетами или с TCP каналом `tpws` и `nfqws` распознают эти ситуации +по-разному. +Что считается ситуацией, похожей на блокировку: + +1) [`nfqws`] Несколько ретрансмиссий первого запроса в TCP сеансе, в котором имеется host. +2) [`nfqws`,`tpws`] RST, пришедший в ответ на первый запрос с хостом. +3) [`nfqws`,`tpws`] HTTP редирект, пришедший в ответ на первый запрос с хостом, на глобальный адрес +с доменом 2 уровня, не совпадающим с доменом 2 уровня оригинального запроса. +4) [`tpws`] закрытие соединения клиентом после отправки первого запроса с хостом, если не было на него +ответа со стороны сервера. Это обычно случается по таймауту, когда нет ответа (случай "зависание"). + +Чтобы снизить вероятность ложных срабатываний, имеется счетчик ситуаций, похожих на блокировку. +Если за определенное время произойдет более определенного их количества, хост считается заблокированным +и заносится в autohostlist. По нему сразу же начинает работать стратегия по обходу блокировки. +Если в процессе счета вебсайт отвечает без признаков блокировки, счетчик сбрасывается. +Вероятно, это был временный сбой сайта. + +На практике работа с данным режимом выглядит так. +Первый раз пользователь заходит на сайт и получает заглушку, сброс соединения или броузер подвисает, +вываливаясь по таймауту с сообщением о невозможности загрузить страницу. +Надо долбить F5, принуждая броузер повторять попытки. После некоторой попытки сайт +начинает работать, и дальше он будет работать всегда. + +С этим режимом можно использовать техники обхода, ломающие значительное количество сайтов. +Если сайт не ведет себя как заблокированный, значит обход применен не будет. +В противном случае терять все равно нечего. +Однако, могут быть временные сбои сервера, приводящие к ситуации, аналогичной блокировке. +Могут происходит ложные срабатывания. Если такое произошло, стратегия может начать ломать незаблокированный сайт. Эту ситуацию, увы, придется вам контролировать вручную. +Заносите такие домены в `ipset/zapret-hosts-user-exclude.txt`, чтобы избежать повторения. +Чтобы впоследствии разобраться почему домен был занесен в лист, можно включить autohostlist debug log. +Он полезен тем, что работает без постоянного просмотра вывода `nfqws` в режиме debug. +В лог заносятся только основные события, ведущие к занесению хоста в лист. +По логу можно понять как избежать ложных срабатываний и подходит ли вообще вам этот режим. + +Можно использовать один autohostlist с множеством процессов. Все процессы проверяют время модификации файла. +Если файл был изменен в другом процессе, то происходит перечитывание всех include листов, включая autohostlist. +Все процессы должны работать под одним uid, чтобы были права доступа на файл. + +Скрипты zapret ведут autohostlist в `ipset/zapret-hosts-auto.txt`. +`install_easy.sh` при апгрейде zapret сохраняет этот файл. +Режим autohostlist включает в себя режим hostlist. +Можно вести `ipset/zapret-hosts-user.txt`, `ipset/zapret-hosts-user-exclude.txt`. + +## Проверка провайдера + +Перед настройкой нужно провести исследование какую бяку устроил вам ваш провайдер. + +Нужно выяснить не подменяет ли он DNS и какой метод обхода DPI работает. +В этом вам поможет скрипт `blockcheck.sh`. + +Если DNS подменяется, но провайдер не перехватывает обращения к сторонним DNS, поменяйте DNS на публичный. +Например: 8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1, 9.9.9.9. +Если DNS подменяется и провайдер перехватывает обращения к сторонним DNS, настройте DNSCrypt. +Еще один эффективный вариант - использовать ресолвер от Yandex 77.88.8.88 на нестандартном порту 1253. +Многие провайдеры не анализируют обращения к DNS на нестандартных портах. + +Следует прогнать `blockcheck` по нескольким заблокированным сайтам и выявить общий характер блокировок. +Разные сайты могут быть заблокированы по-разному, нужно искать такую технику, которая работает на большинстве. +Чтобы записать вывод `blockcheck.sh` в файл, выполните: `./blockcheck.sh | tee /tmp/blockcheck.txt`. + +Проанализируйте, какие методы дурения DPI работают, в соответствии с ними настройте `/opt/zapret/config`. + +Имейте ввиду, что у провайдеров может быть несколько DPI или запросы могут идти через разные каналы по методу балансировки нагрузки. Балансировка может означать, что на разных ветках разные DPI или они находятся на разных хопах. Такая ситуация может выражаться в нестабильности работы обхода. +Дернули несколько раз `curl`. То работает, то connection reset или редирект. `blockcheck.sh` выдает странноватые результаты. То `split` работает на 2-м. хопе, то на 4-м. Достоверность результата вызывает сомнения. +В этом случае задайте несколько повторов одного и того же теста. Тест будет считаться успешным только, если все попытки пройдут успешно. + +При использовании `autottl` следует протестировать как можно больше разных доменов. Эта техника может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах она стабильна, на третьих полный хаос, и проще отказаться. + +Blockcheck имеет 3 уровня сканирования: + +- quick - нужно максимально быстро найти хоть что-то работающее. +- standard дает возможность провести исследование как и на что реагирует DPI в плане методов обхода. +- force дает максимум проверок даже в случаях, когда ресурс работает без обхода или с более простыми стратегиями. + +### Скан портов + +Если в системе присутствует совместимый `netcat` (`ncat` от `nmap` или openbsd `ncat`. в OpenWrt по умолчанию нет.), +то выполняется сканирование портов HTTP или HTTPS всех IP адресов домена. +Если ни один IP не отвечает, то результат очевиден. Можно останавливать сканирование. +Автоматически оно не остановится, потому что `netcat`-ы недостаточно подробно информируют о причинах ошибки. +Если доступна только часть IP, то можно ожидать хаотичных сбоев, т.к. подключение идет к случайному адресу +из списка. + +### Проверка на частичный IP block + +Под частичным блоком подразумевается ситуация, когда коннект на порты есть, но по определенному транспортному или прикладному протоколу всегда идет реакция DPI вне зависимости от запрашиваемого домена. +Эта проверка так же не выдаст автоматического вердикта/решения, потому что может быть очень много вариаций. +Вместо этого анализ происходящего возложен на самого пользователя или тех, кто будет читать лог. +Суть этой проверки в попытке дернуть неблокированный IP с блокированным доменом и наоборот, анализируя при этом реакцию DPI. Реакция DPI обычно проявляется в виде таймаута (зависание запроса), connection reset или HTTP redirect на заглушку. Любой другой вариант скорее всего говорит об отсутствии реакции DPI. +В частности, любые HTTP коды, кроме редиректа, ведущего именно на заглушку, а не куда-то еще. +На TLS - ошибки handshake без задержек. +Ошибка сертификата может говорить как о реакции DPI с MitM атакой (подмена сертификата), так и о том, что принимающий сервер неблокированного домена все равно принимает ваш TLS handshake с чужим доменом, пытаясь при этом выдать сертификат без запрошенного домена. Требуется дополнительный анализ. +Если на заблокированный домен есть реакция на всех IP адресах, значит есть блокировка по домену. +Если на неблокированный домен есть реакция на IP адресах блокированного домена, значит имеет место блок по IP. +Соответственно, если есть и то, и другое, значит есть и блок по IP, и блок по домену. +Неблокированный домен первым делом проверяется на доступность на оригинальном адресе. +При недоступности тест отменяется, поскольку он будет неинформативен. + +Если выяснено, что есть частичный блок по IP на DPI, то скорее всего все остальные тесты будут провалены вне зависимости от стратегий обхода. Но бывают и некоторые исключения. Например, пробитие через IPv6 option headers. Или сделать так, чтобы он не мог распознать протокол прикладного уровня. +Дальнейшие тесты могут быть не лишены смысла. + +#### Пример блокировки по домену без блокировки по IP + +``` +> testing iana.org on it's original ip +!!!!! AVAILABLE !!!!! +> testing rutracker.org on 192.0.43.8 (iana.org) +curl: (28) Operation timed out after 1002 milliseconds with 0 bytes received +> testing iana.org on 172.67.182.196 (rutracker.org) +HTTP/1.1 409 Conflict +> testing iana.org on 104.21.32.39 (rutracker.org) +HTTP/1.1 409 Conflict + +> testing iana.org on it's original ip +!!!!! AVAILABLE !!!!! +> testing rutracker.org on 192.0.43.8 (iana.org) +curl: (28) Connection timed out after 1001 milliseconds +> testing iana.org on 172.67.182.196 (rutracker.org) +curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure +> testing iana.org on 104.21.32.39 (rutracker.org) +curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure + +> testing iana.org on it's original ip +!!!!! AVAILABLE !!!!! +> testing rutracker.org on 192.0.43.8 (iana.org) +HTTP/1.1 307 Temporary Redirect +Location: https://www.gblnet.net/blocked.php +> testing iana.org on 172.67.182.196 (rutracker.org) +HTTP/1.1 409 Conflict +> testing iana.org on 104.21.32.39 (rutracker.org) +HTTP/1.1 409 Conflict + +> testing iana.org on it's original ip +!!!!! AVAILABLE !!!!! +> testing rutracker.org on 192.0.43.8 (iana.org) +curl: (35) Recv failure: Connection reset by peer +> testing iana.org on 172.67.182.196 (rutracker.org) +curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure +> testing iana.org on 104.21.32.39 (rutracker.org) +curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure +``` + +#### Пример полного IP блока или блока TCP порта при отсутствии блока по домену + +``` +* port block tests ipv4 startmail.com:80 +ncat -z -w 1 145.131.90.136 80 +145.131.90.136 does not connect. netcat code 1 +ncat -z -w 1 145.131.90.152 80 +145.131.90.152 does not connect. netcat code 1 + +* curl_test_http ipv4 startmail.com +- checking without DPI bypass +curl: (28) Connection timed out after 2002 milliseconds +UNAVAILABLE code=28 + +- IP block tests (requires manual interpretation) +> testing iana.org on it's original ip +!!!!! AVAILABLE !!!!! +> testing startmail.com on 192.0.43.8 (iana.org) +HTTP/1.1 302 Found +Location: https://www.iana.org/ +> testing iana.org on 145.131.90.136 (startmail.com) +curl: (28) Connection timed out after 2002 milliseconds +> testing iana.org on 145.131.90.152 (startmail.com) +curl: (28) Connection timed out after 2002 milliseconds +``` + +## Выбор параметров + +Файл `/opt/zapret/config` используется различными компонентами системы и содержит основные настройки. +Его нужно просмотреть и при необходимости отредактировать. + +На Linux системах можно выбрать использовать `iptables` или `nftables`. +По умолчанию на традиционных Linux выбирается `nftables`, если установлен `nft`. +На OpenWrt по умолчанию выбирается `nftables` на новых версиях с `firewall4`. + +```sh +FWTYPE=iptables +``` + +Основной режим: + +- `tpws` - `tpws` в режиме transparent +- `tpws-socks` - `tpws` в режиме SOCKS вешается на localhost и LAN интерфейс (если задан IFACE_LAN или если система - OpenWrt). порт 988 +- `nfqws` - `nfqws` +- `filter` - только заполнить ipset или загрузить hostlist +- `custom` - нужно самому запрограммировать запуск демонов в init скрипте и правила iptables + +```sh +MODE=tpws +``` + +Применять ли дурение к HTTP: + +```sh +MODE_HTTP=1 +``` + +Применять ли дурение к последовательным HTTP запросам в одном TCP соединении (HTTP keeaplive). +Относится только к `nfqws`. Выключение данной функции способно сэкономить загрузку процессора. +`tpws` всегда работает с HTTP keepalive + +```sh +MODE_HTTP_KEEPALIVE=0 +``` + +Применять ли дурение к HTTPS: + +```sh +MODE_HTTPS=1 +``` + +Применять ли дурение к QUIC: + +```sh +MODE_QUIC=0 +``` + +Режим фильтрации хостов: + +- `none` - применять дурение ко всем хостам +- `ipset` - ограничить дурение ipset-ом zapret/zapret6 +- `hostlist` - ограничить дурение списком хостов из файла +- `autohostlist` - режим hostlist + распознавание блокировок и ведения автоматического листа + +```sh +MODE_FILTER=none +``` + +Опции `tpws`: + +```sh +TPWS_OPT="--hostspell=HOST --split-http-req=method --split-pos=3" +``` + +Опции `nfqws` для атаки десинхронизации DPI: + +```sh +DESYNC_MARK=0x40000000 +DESYNC_MARK_POSTNAT=0x20000000 +NFQWS_OPT_DESYNC="--dpi-desync=fake --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" +``` + +Задание раздельных опций `nfqws` для HTTP и HTTPS и для версий ip протоколов 4,6 : + +```sh +NFQWS_OPT_DESYNC_HTTP="--dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" +NFQWS_OPT_DESYNC_HTTPS="--wssize=1:6 --dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" +NFQWS_OPT_DESYNC_HTTP6="--dpi-desync=split --dpi-desync-ttl=5 --dpi-desync-fooling=none" +NFQWS_OPT_DESYNC_HTTPS6="--wssize=1:6 --dpi-desync=split --dpi-desync-ttl=5 --dpi-desync-fooling=none" +``` + +Если какая-то из переменных `NFQWS_OPT_DESYNC_HTTP`/`NFQWS_OPT_DESYNC_HTTPS` не определена, берется значение `NFQWS_OPT_DESYNC`. +Если какая-то из переменных `NFQWS_OPT_DESYNC_HTTP6`/`NFQWS_OPT_DESYNC_HTTPS6` не определена, берется значение `NFQWS_OPT_DESYNC_HTTP`/`NFQWS_OPT_DESYNC_HTTPS`. + +Опции дурения для QUIC: + +```sh +NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake" +NFQWS_OPT_DESYNC_QUIC6="--dpi-desync=hopbyhop" +Если NFQWS_OPT_DESYNC_QUIC6 не задано, то берется NFQWS_OPT_DESYNC_QUIC. +``` + +Настройка системы управления выборочным traffic offload (только если поддерживается): + +- `donttouch`: выборочное управление отключено, используется системная настройка, простой инсталлятор выключает системную настройку, если она не совместима с выбранным режимом +- `none`: выборочное управление отключено, простой инсталлятор выключает системную настройку +- `software`: выборочное управление включено в режиме software, простой инсталлятор выключает системную настройку +- `hardware`: выборочное управление включено в режиме hardware, простой инсталлятор выключает системную настройку + +```sh +FLOWOFFLOAD=donttouch +``` + +Параметр GETLIST указывает инсталлятору `install_easy.sh` какой скрипт дергать для обновления списка заблокированных IP или хостов. +Он же вызывается через `get_config.sh` из запланированных заданий (crontab или systemd timer). +Поместите сюда название скрипта, который будете использовать для обновления листов. +Если не нужно, то параметр следует закомментировать. + +Можно индивидуально отключить IPv4 или IPv6. Если параметр закомментирован или не равен "1", использование протокола разрешено. + +```sh +#DISABLE_IPV4=1 +DISABLE_IPV6=1 +``` + +Количество потоков для многопоточного DNS ресолвера `mdig` (1..100). +Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер? + +```sh +MDIG_THREADS=30 +``` + +Место для хранения временных файлов. При скачивании огромных реестров в `/tmp` места может не хватить. +Если файловая система на нормальном носителе (не встроенная память роутера), то можно указать место на флэшке или диске. + +```sh +TMPDIR=/opt/zapret/tmp +``` + +Опции для создания ipset-ов и nfset-ов: + +```sh +SET_MAXELEM=262144 +IPSET_OPT="hashsize 262144 maxelem 2097152" +``` + +Хук, позволяющий внести ip адреса динамически. `$1` = имя таблицы +Адреса выводятся в stdout. В случае nfset автоматически решается проблема возможного пересечения интервалов. + +```sh +IPSET_HOOK="/etc/zapret.ipset.hook" +``` + +**Про ругань в `dmesg` по поводу нехватки памяти.** +Может так случиться, что памяти в системе достаточно, но при попытке заполнить огромный ipset ядро начинает громко ругаться, ipset заполняется не полностью. +Вероятная причина в том, что превышается hashsize, заданный при создании ipset (`create_ipset.sh`). +Происходит переаллокация списка, не находится непрерывных фрагментов памяти нужной длины. +Это лечится увеличением hashsize. Но чем больше hashsize, тем больше занимает ipset в памяти. +Задавать слишком большой hashsize для недостаточно больших списков нецелесообразно. + +Опции для вызова `ip2net`, отдельно для листов IPv4 и IPv6: + +```sh +IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4" +IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5" +``` + +Настройка режима `autohostlist`: + +```sh +AUTOHOSTLIST_RETRANS_THRESHOLD=3 +AUTOHOSTLIST_FAIL_THRESHOLD=2 +AUTOHOSTLIST_FAIL_TIME=60 +AUTOHOSTLIST_DEBUG=0 +``` + +Включить или выключить сжатие больших листов в скриптах `ipset/*.sh`. По умолчанию включено. + +```sh +GZIP_LISTS=1 +``` + +Команда для перезагрузки IP таблиц фаервола. +Если не указано или пустое, выбирается автоматически ipset или ipfw при их наличии. +На BSD системах с PF нет автоматической загрузки. Там нужно указать команду явно: `pfctl -f /etc/pf.conf` +На более новых `pfctl` (есть в новых FreeBSD, нет в OpenBSD 6.8) можно дать команду загрузки только таблиц: `pfctl -Tl -f /etc/pf.conf` +"-" означает отключение загрузки листов даже при наличии поддерживаемого backend. + +```sh +#LISTS_RELOAD="pfctl -f /etc/pf.conf" +#LISTS_RELOAD=- +``` + +В OpenWrt существует сеть по умолчанию 'lan'. Только трафик с этой сети будет перенаправлен на tpws. +Но возможно задать другие сети или список сетей: + +```sh +OPENWRT_LAN="lan lan2 lan3" +``` + +В OpenWrt в качестве WAN берутся интерфейсы, имеющие default route. Отдельно для IPv4 и IPv6. +Это можно переопределить: + +```sh +OPENWRT_WAN4="wan4 vpn" +OPENWRT_WAN6="wan6 vpn6" +``` + +Параметр `INIT_APPLY_FW=1` разрешает init скрипту самостоятельно применять правила iptables. +При иных значениях или если параметр закомментирован, правила применены не будут. +Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила. +На OpenWrt неприменимо при использовании `firewall3`+`iptables`. + +Следующие настройки не актуальны для OpenWrt! + +Если ваша система работает как роутер, то нужно вписать названия внутренних и внешних интерфейсов: + +```sh +IFACE_LAN=eth0 +IFACE_WAN=eth1 +IFACE_WAN6="henet ipsec0" +``` + +Несколько интерфейсов могут быть вписаны через пробел. +Если `IFACE_WAN6` не задан, то берется значение `IFACE_WAN`. + +**ВАЖНО:** настройка маршрутизации, маскарада и т.д. не входит в задачу zapret. +Включаются только режимы, обеспечивающие перехват транзитного трафика. +Возможно определить несколько интерфейсов следующим образом: + +```sh +IFACE_LAN="eth0 eth1 eth2" +``` + +## Прикручивание к системе управления фаерволом или своей системе запуска + +Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт +с имеющимся скриптом запуска. При повторном применении правил она могла бы поломать настройки `iptables` от zapret. +В этом случае правила для `iptables` должны быть прикручены к вашему фаерволу отдельно от запуска `tpws` или `nfqws`. + +Следующие вызовы позволяют применить или убрать правила `iptables` отдельно: + +```sh +/opt/zapret/init.d/sysv/zapret start_fw +/opt/zapret/init.d/sysv/zapret stop_fw +/opt/zapret/init.d/sysv/zapret restart_fw +``` + +А так можно запустить или остановить демоны отдельно от фаервола: + +```sh +/opt/zapret/init.d/sysv/zapret start_daemons +/opt/zapret/init.d/sysv/zapret stop_daemons +/opt/zapret/init.d/sysv/zapret restart_daemons +``` + +`nftables` сводят практически на нет конфликты между разными системами управления, поскольку позволяют +использовать независимые таблицы и хуки. Используется отдельная nf-таблица "zapret". +Если ваша система ее не будет трогать, скорее всего все будет нормально. + +Для `nftables` предусмотрено несколько дополнительных вызовов : + +Посмотреть set-ы интерфейсов, относящихся к LAN, WAN и WAN6. По ним идет завертывание трафика. +А так же таблицу flow table с именами интерфейсов ingress hook. + +```sh +/opt/zapret/init.d/sysv/zapret list_ifsets +``` + +Обновить set-ы интерфейсов, относящихся к LAN, WAN и WAN6. +Для традиционных Linux список интерфейсов берется из переменных конфига `IFACE_LAN`, `IFACE_WAN`. +Для OpenWrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN. +Все интерфейсы LAN и WAN так же добавляются в ingress hook от flow table. + +```sh +/opt/zapret/init.d/sysv/zapret reload_ifsets +``` + +Просмотр таблицы без содержимого set-ов. Вызывает `nft -t list table inet zapret`: + +```sh +/opt/zapret/init.d/sysv/zapret list_table +``` + +Так же возможно прицепиться своим скриптом к любой стадии применения и снятия фаервола со стороны zapret скриптов : + +```sh +INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up" +INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" +INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down" +INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down" +``` + +Эти настройки доступны в `config`. +Может быть полезно, если вам нужно использовать `nftables` set-ы, например `ipban`/`ipban6`. +nfset-ы принадлежат только одной таблице, следовательно вам придется писать правила для таблицы zapret, +а значит нужно синхронизироваться с применением/снятием правил со стороны zapret скриптов. + +## Вариант `custom` + +custom код вынесен в отдельный shell include: +`/opt/zapret/init.d/sysv/custom` +или +`/opt/zapret/init.d/openwrt/custom` + +Нужно свой код вписать в функции : + +```sh +zapret_custom_daemons +zapret_custom_firewall +zapret_custom_firewall_nft +``` + +В файле custom пишите ваш код, пользуясь хелперами из `functions` или `zapret`. +Смотрите как там сделано добавление `iptables` или запуск демонов. +Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи +типа наличия/отсутствия IPv6, является ли система роутером, имена интерфейсов, ... +Хелперы это учитывают, вам нужно сосредоточиться лишь на фильтрах {ip,nf}tables и +параметрах демонов. + +Код для OpenWrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку демонов. +Запуск это или остановка передается в параметре $1 (0 или 1). +В OpenWrt за остановку отвечает procd. + +Для фаервола кастом пишется отдельно для `iptables` и `nftables`. Все очень похоже, но отличается +написание фильтров и названия процедур хелперов. Если вам не нужны `iptables` или `nftables` - +можете не писать соответствующую функцию. + +Готовый custom скрипт `custom-tpws4http-nfqws4https` позволяет применить дурение +`tpws` к HTTP и nfqws к HTTPS. При этом поддерживаются установки из `config`. +Его можно использовать как стартовую точку для написания своих скриптов. + +## Простая установка + +`install_easy.sh` автоматизирует ручные варианты процедур установки (см `docs/manual_setup.md`). +Он поддерживает OpenWrt, Linux системы на базе systemd или openrc и macOS. + +Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров". + +Если система запуска поддерживается, но используется не поддерживаемый инсталлятором менеджер пакетов +или названия пакетов не соответствуют прописанным в инсталлятор, пакеты нужно установить вручную. +Всегда требуется `curl`. ipset - только для режима `iptables`, для `nftables` - не нужен. + +Для совсем обрезанных дистрибутивов (alpine) требуется отдельно установить `iptables` и `ip6tables`, либо `nftables`. + +В комплекте идут статические бинарники для большинства архитектур. Какой-то из них подойдет +с вероятностью 99%. Но если у вас экзотическая система, инсталлятор попробует собрать бинарники сам +через make. Для этого нужны `gcc`, `make` и необходимые `-dev` пакеты. Можно форсировать режим компиляции следующим вызовом : + +```sh +sh install_easy.sh make +``` + +Под OpenWrt все уже сразу готово для использования системы в качестве роутера. +Имена интерфейсов WAN и LAN известны из настроек системы. +Под другими системами роутер вы настраиваете самостоятельно. инсталлятор в это не вмешивается. +инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы. +Нужно понимать, что заворот проходящего трафика на tpws в прозрачном режиме происходит до выполнения маршрутизации, +следовательно возможна фильтрация по LAN и невозможна по WAN. +Решение о завороте на tpws локального исходящего трафика принимается после выполнения маршрутизации, +следовательно ситуация обратная: LAN не имеет смысла, фильтрация по WAN возможна. +Заворот на nfqws происходит всегда после маршрутизации, поэтому к нему применима только фильтрация по WAN. +Возможность прохождения трафика в том или ином направлении настраивается вами в процессе конфигурации роутера. + +Деинсталляция выполняется через `uninstall_easy.sh` + +## Простая установка на OpenWrt + +Работает только если у вас на роутере достаточно места. + +Копируем zapret на роутер в `/tmp`. + +Запускаем установщик: + +```sh +sh /tmp/zapret/install_easy.sh +``` + +Он скопирует в `/opt/zapret` только необходимый минимум файлов. + +После успешной установки можно удалить zapret из tmp для освобождения RAM: + +```sh +rm -r /tmp/zapret +``` + +Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров". + +Система простой инсталяции заточена на любое умышленное или неумышленное изменение прав доступа на файлы. +Устойчива к репаку под Windows. После копирования в /opt права будут принудительно восстановлены. + +## Android + +Без рута забудьте про `nfqws` и `tpws` в режиме transparent proxy. `tpws` будет работать только в режиме --socks. + +Ядра Android имеют поддержку NFQUEUE. `nfqws` работает. + +В стоковых ядрах нет поддержки ipset. В общем случае сложность задачи по поднятию ipset варьируется от +"не просто" до "почти невозможно". Если только вы не найдете готовое собранное ядро под ваш девайс. + +`tpws` будет работать в любом случае, он не требует чего-либо особенного. +В Android нет `/etc/passwd`, потому опция `--user` не будет работать. Вместо нее можно +пользоваться числовыми user id и опцией `--uid`. +Рекомендую использовать gid 3003 (AID_INET). Иначе можете получить permission denied на создание сокета. +Например: `--uid 1:3003` +В `iptables` укажите: `! --uid-owner 1` вместо `! --uid-owner tpws`. +Напишите шелл скрипт с `iptables` и `tpws`, запускайте его средствами вашего рут менеджера. +Скрипты автозапуска лежат тут: + +- Magisk: `/data/adb/service.d` +- SuperSU: `/system/su.d` + +`nfqws` может иметь такой глюк. При запуске с uid по умолчанию (0x7FFFFFFF) при условии работы на сотовом интерфейсе +и отключенном кабеле внешнего питания система может частично виснуть. Перестает работать тач и кнопки, +но анимация на экране может продолжаться. Если экран был погашен, то включить его кнопкой power невозможно. +Это, видимо, связано с переводом в suspend процессов с определенным UID. UID соответствует приложению или +системному сервису. По UID android определяет политику power saving. +Так же возможно, что глюк связан с кривым драйвером сотового интерфейса от китайцев, поскольку при использовании +Wi-Fi такого не наблюдается. suspend обработчика nfqueue на обычном Linux не вызывает подобных фатальных последствий. +Изменение UID на низкий (`--uid 1` подойдет) позволяет решить эту проблему. +Глюк был замечен на Android 8.1 на девайсе, основанном на платформе mediatek. + +Ответ на вопрос куда поместить `tpws` на Android без рута, чтобы потом его запускать из приложений. +Файл заливаем через `adb shell` в `/data/local/tmp/`, лучше всего в субфолдер. + +```sh +mkdir /data/local/tmp/zapret +adb push tpws /data/local/tmp/zapret +chmod 755 /data/local/tmp/zapret /data/local/tmp/zapret/tpws +chcon u:object_r:system_file:s0 /data/local/tmp/zapret/tpws +``` + +Как найти стратегию обхода сотового оператора: проще всего раздать инет на комп с Linux. +Можно записать live image Linux на флэшку и загрузиться с нее или запустить виртуалку с Linux +и пробросить в нее usb устройство от режима модема с телефона. +На компе с Linux прогнать стандартную процедуру `blockcheck.sh`. При переносе правил на телефон уменьшить TTL на 1, +если правила с TTL присутствуют в стратегии. +Можно развернуть rootfs какого-нибудь дистрибутива Linux прямо на телефоне, имея рута. +Это лучше всего делать с компа через adb shell. +Если компа нет, то это единственный вариант, хотя и неудобный. +Подойдет что-то легковесное, например, alpine или даже OpenWrt. +Если это не эмулятор Android, то универсальная архитектура - ARM (любой вариант). +Если вы точно знаете, что ОС у вас 64-разрядная, то лучше вместо ARM - aarch64. + +```sh +mount --bind /dev /data/linux/dev +mount --bind /proc /data/linux/proc +mount --bind /sys /data/linux/sys +chroot /data/linux +``` + +Первым делом вам нужно будет один раз настроить DNS. Сам он не заведется. + +```sh +echo nameserver 1.1.1.1 >/etc/resolv.conf +``` + +Далее нужно средствами пакетного менеджера установить `iptables-legacy`. Обязательно НЕ iptables-nft, +который как правило присутствует по умолчанию. В ядре android нет nftables. + +```sh +ls -la $(which iptables) +``` + +Линк должен указывать на legacy вариант. +Если нет, значит устанавливайте нужные пакеты вашего дистрибутива, и убеждайтесь в правильности ссылок. + +```sh +iptables -S +``` + +Так можно проверить, что ваш `iptables` увидел то, что туда насовал android. `iptables-nft` выдаст ошибку. +Далее качаем zapret в `/opt/zapret`. Обычные действия с `install_prereq.sh`, `install_bin.sh`, `blockcheck.sh`. + +Учтите, что стратегии обхода сотового оператора и домашнего Wi-Fi вероятно будут разные. +Выделить сотового оператора легко через параметр `iptables -o <имя интерфейса>`. Имя может быть, например, `ccmni0`. +Его легко увидеть через `ifconfig`. +Wi-Fi сеть - обычно `wlan0`. + +Переключать `blockcheck` между оператором и Wi-Fi можно вместе со всем инетом - включив или выключив Wi-Fi. +Если найдете стратегию для Wi-Fi и впишите ее в автостарт, то при подключении к другому Wi-Fi +она может не сработать или вовсе что-то поломать, потому подумайте, стоит ли. +Может быть лучше сделать скрипты типа "запустить обход домашнего Wi-Fi", "снять обход домашнего Wi-Fi", и пользоваться ими по необходимости из терминала. Но домашний Wi-Fi лучше всё же обходить на роутере. + +## Мобильные модемы и роутеры Huawei + +Устройства типа E3372, E8372, E5770 разделяют общую идеологию построения системы. +Имеются 2 вычислительных ядра. Одно ядро выполняет vxworks, другое - Linux. +На 4pda имеются модифицированные прошивки с `telnet` и `adb`. Их и нужно использовать. + +Дальнейшие утверждения проверены на E8372. На других может быть аналогично или похоже. +Присутствуют дополнительные аппаратные блоки для offload-а сетевых функций. +Не весь трафик идет через Linux. Исходящий трафик с самого модема проходит +цепочку OUTPUT нормально, на FORWARD =>wan часть пакетов выпадает из `tcpdump`. + +`tpws` работает обычным образом. + +`nfqueue` поломан. можно собрать [фиксящий модуль](https://github.com/im-0/unfuck-nfqueue-on-e3372h), +используя исходники с Huawei open source. Исходники содержат тулчейн и полусобирающееся, +неактуальное ядро. Конфиг можно взять с рабочего модема из `/proc/config.gz`. +С помощью этих исходников умельцы могут собрать модуль `unfuck_nfqueue.ko`. +После его применения NFQUEUE и `nfqws` для ARM работают нормально. + +Чтобы избежать проблемы с offload-ом при использовании `nfqws`, следует комбинировать `tpws` в режиме TCP proxy и `nfqws`. +Правила NFQUEUE пишутся для цепочки OUTPUT. +connbytes придется опускать, поскольку модуля в ядре нет. Но это не смертельно. + +Скрипт автозапуска - `/system/etc/autorun.sh`. Создайте свой скрипт настройки zapret, +запускайте из конца `autorun.sh` через "&". Скрипт должен в начале делать `sleep 5`, чтобы дождаться +поднятия сети и `iptables` от huawei. + +### Предупреждение + +На этом модеме происходят хаотические сбросы соединений TCP по непонятным причинам. +Выглядит это так, если запускать `curl` с самого модема: + +``` +curl www.ru +curl: (7) Failed to connect to www.ru port 80: Host is unreachable +``` + +Возникает ошибка сокета EHOSTUNREACH (errno -113). То же самое видно в `tpws`. +В броузере не подгружаются части веб страниц, картинки, стили. +В tcpdump на внешнем интерфейсе eth_x виден только единственный и безответный SYN пакет, без сообщений ICMP. +ОС каким-то образом узнает о невозможности установить TCP соединение и выдает ошибку. +Если выполнять подключение с клиента, то SYN пропадают, соединение не устанавливается. +ОС клиента проводит ретрансмиссию, и с какого-то раза подключение удается. +Поэтому без TCP проксирования в этой ситуации сайты тупят, но загружаются, а с проксированием +подключение выполняется, но вскоре сбрасывается без каких-либо данных, и броузеры не пытаются установить +его заново. Поэтому качество броузинга с `tpws` может быть хуже, но дело не в `tpws`. +Частота сбросов заметно возрастает, если запущен торрент клиент, имеется много TCP соединений. +Однако, причина не в переполнении таблицы conntrack. Увеличение лимитов и очистка conntrack не помогают. +Предположительно эта особенность связана с обработкой пакетов сброса соединения в hardware offload. +Точного ответа на вопрос у меня нет. Если вы знаете - поделитесь, пожалуйста. +Чтобы не ухудшать качество броузинга, можно фильтровать заворот на `tpws` по IP фильтру. +Поддержка ipset отсутствует. Значит, все, что можно сделать - создать индивидуальные правила +на небольшое количество хостов. + +Некоторые наброски скриптов присутствуют в `files/huawei`. **Не** готовое решение! Смотрите, изучайте, приспосабливайте. +[Здесь](https://github.com/bol-van/bins) можно скачать готовые полезные статические бинарники для ARM, включая `curl`. + +## FreeBSD, OpenBSD, macOS + +Описано в `docs/bsd.md`. + +## Windows + +Описано в `docs/windows.md`. + +## Другие прошивки + +Для статических бинариков не имеет значения на чем они запущены: PC, Android, приставка, роутер, любой другой девайс. +Подойдет любая прошивка, дистрибутив Linux. Статические бинарники запустятся на всем. +Им нужно только ядро с необходимыми опциями сборки или модулями. +Но кроме бинариков в проекте используются еще и скрипты, в которых задействуются некоторые +стандартные программы. + +Основные причины почему нельзя просто так взять и установить эту систему на что угодно : + +- отсутствие доступа к девайсу через shell +- отсутствие рута +- отсутствие раздела r/w для записи и энергонезависимого хранения файлов +- отсутствие возможности поставить что-то в автозапуск +- отсутствие cron +- неотключаемый flow offload или другая проприетарщина в netfilter +- недостаток модулей ядра или опций его сборки +- недостаток модулей iptables (`/usr/lib/iptables/lib*.so`) +- недостаток стандартных программ (типа ipset, curl) или их кастрированность (облегченная замена) +- кастрированный или нестандартный шелл sh + +Если в вашей прошивке есть все необходимое, то вы можете адаптировать zapret под ваш девайс в той или иной степени. +Может быть у вас не получится поднять все части системы, однако вы можете хотя бы попытаться +поднять `tpws` и завернуть на него через `-j REDIRECT` весь трафик на порт 80. +Если вам есть куда записать tpws, есть возможность выполнять команды при старте, то как минимум это вы сделать сможете. Скорее всего поддержка REDIRECT в ядре есть. Она точно есть на любом роутере, на других устройствах под вопросом. NFQUEUE, ipset на большинстве прошивок отсутствуют из-за ненужности. + +Пересобрать ядро или модули для него будет, скорее всего, достаточно трудно. +Для этого вам необходимо будет по крайней мере получить исходники вашей прошивки. +User mode компоненты могут быть привнесены относительно безболезненно, если есть место куда их записать. +Специально для девайсов, имеющих область r/w, существует проект entware. +Некоторые прошивки даже имеют возможность его облегченной установки через веб интерфейс. +entware содержит репозиторий user-mode компонент, которые устанавливаются в `/opt`. +С их помощью можно компенсировать недостаток ПО основной прошивки, за исключением ядра. + +Можно попытаться использовать sysv init script таким образом, как это описано в разделе +"Прикручивание к системе управления фаерволом или своей системе запуска". +В случае ругани на отсутствие каких-то базовых программ, их следует восполнить посредством entware. +Перед запуском скрипта путь к дополнительным программам должен быть помещен в PATH. + +Подробное описание настроек для других прошивок выходит за рамки данного проекта. + +Openwrt является одной из немногих относительно полноценных Linux систем для embedded devices. +Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивки : + +- полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть +- корень r/w. + +это практически уникальная особенность OpenWrt. заводские и большинство альтернативных прошивок построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области встроенной памяти, называемой nvram. не имеющие r/w корня системы сильно кастрированы. они не имеют возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном на чуть более продвинутого, чем обычно, пользователя и управление имеющимся функционалом через веб интерфейс, но функционал фиксированно ограничен. альтернативные прошивки как правило могут монтировать r/w раздел в какую-то область файловой системы, заводские обычно могут монтировать лишь флэшки, подключенные к USB, и не факт, что есть поддержка unix файловых системы. может быть поддержка только fat и ntfs. + +- возможность выноса корневой файловой системы на внешний носитель (extroot) или создания на нем оверлея (overlay) +- наличие менеджера пакетов `opkg` и репозитория софта +- flow offload предсказуемо, стандартно и выборочно управляем, а так же отключаем +- в репозитории есть все модули ядра, их можно доустановить через `opkg`. ядро пересобирать не нужно. +- в репозитории есть все модули `iptables`, их можно доустановить через `opkg` +- в репозитории есть огромное количество стандартных программ и дополнительного софта +- наличие SDK, позволяющего собрать недостающее + +## Обход блокировки через сторонний хост + +Если не работает автономный обход, приходится перенаправлять трафик через сторонний хост. +Предлагается использовать прозрачный редирект через socks5 посредством `iptables`+`redsocks`, либо `iptables`+iproute+VPN. +Настройка варианта с `redsocks` на OpenWrt описана в `docs/redsocks.md`. +Настройка варианта с `iproute`+WireGuard - в `docs/wireguard/wireguard_iproute_openwrt.md`. + +## Почему стоит вложиться в покупку VPS + +VPS - это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу. +На VPS могут выполняться какие угодно задачи. От простого веб сайта до навороченной системы собственной разработки. +Можно использовать VPS и для поднятия собственного VPN или прокси. +Сама широта возможных способов применения, распространенность услуги сводят к минимуму возможности регуляторов по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая реальность, в которой придется изобретать иные решения. +Пока этого не сделали, никто не будет банить хостинги просто потому, что они предоставляют хостинг услуги. + +Вы как индивидуум скорее всего никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера. +VPN провайдер предоставляет *простую* и *доступную* услугу по обходу блокировок для масс. +Этот факт делает его первоочередной целью блокировки. РКН направит уведомление, после отказа сотрудничать заблокирует VPN. Предоплаченная сумма пропадет. +У регуляторов нет и никогда не будет ресурсов для тотальной проверки каждого сервера в сети. +Возможен китайский расклад, при котором DPI выявляет VPN протоколы и динамически банит IP серверов, предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать VPN трафик или применить другие типы VPN, более устойчивые к анализу на DPI или просто менее широкоизвестные, а следовательно с меньшей вероятностью обнаруживаемые регулятором. +У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям. +Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить не могут, или покориться системе. + +VPS можно прибрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы. +Например, вот [этот](https://vps.today/). +Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или с большим лимитом по трафику (терабайты). +Важен и тип VPS. OpenVZ подойдет для OpenVPN, но вы не поднимете на нем WireGuard, IPsec, то есть все, что требует kernel mode. Помимо этого, недобросовестный поставщик хостинга в любой момент имеет возможность наблюдать за всем, что вы делаете, при использовании данной виртуализации. +Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС Linux вместе с ядром. Подойдут KVM, Xen, Hyper-V, VMware. + +По цене можно найти предложения, которые будут дешевле готовой VPN услуги, но при этом вы сам хозяин в своей лавке и не рискуете попасть под бан регулятора, разве что "заодно" под ковровую бомбардировку с баном миллионов IP. +Кроме того, если вам совсем все кажется сложным, прочитанное вызывает ступор, и вы точно знаете, что ничего из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов SSH для получения шифрованного SOCKS proxy и прописать его в броузер. Знания Linux не нужны совсем. +Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании. diff --git a/docs/readme.txt b/docs/readme.txt deleted file mode 100644 index 7b5edaf..0000000 --- a/docs/readme.txt +++ /dev/null @@ -1,1848 +0,0 @@ -zapret v.61 - -English -------- - -For english version refer to docs/readme.eng.txt - -Для чего это надо ------------------ - -Автономное, без задействования сторонних серверов, средство противодействия DPI. -Может помочь обойти блокировки или замедление сайтов http(s), сигнатурный анализ tcp и udp протоколов, -например с целью блокировки VPN. - -Проект нацелен прежде всего на маломощные embedded устройства - роутеры, работающие под openwrt. -Поддерживаются традиционные Linux системы, FreeBSD, OpenBSD, частично MacOS. -В некоторых случаях возможна самостоятельная прикрутка решения к различным прошивкам. - -Большая часть функционала работает на windows. - -Как побыстрее начать --------------------- - -Читайте docs/quick_start.txt для linux и openwrt, docs/quick_start_windows.txt для windows. - - -Как это работает ----------------- - -В самом простейшем случае вы имеете дело с пассивным DPI. Пассивный DPI может читать трафик -из потока, может инжектить свои пакеты, но не может блокировать проходящие пакеты. -Если запрос "плохой", пассивный DPI инжектит пакет RST, опционально дополняя его пакетом http redirect. -Если фейк пакет инжектится только для клиента, в этом случае можно обойтись командами iptables -для дропа RST и/или редиректа на заглушку по определенным условиям, которые нужно подбирать -для каждого провайдера индивидуально. Так мы обходим последствия срабатывания триггера запрета. -Если пассивный DPI направляет пакет RST в том числе и серверу, то вы ничего с этим не сможете сделать. -Ваша задача - не допустить срабатывания триггера запрета. Одними iptables уже не обойдетесь. -Этот проект нацелен именно на предотвращение срабатывания запрета, а не ликвидацию его последствий. - -Активный DPI ставится в разрез провода и может дропать пакеты по любым критериям, -в том числе распознавать TCP потоки и блокировать любые пакеты, принадлежащие потоку. - -Как не допустить срабатывания триггера запрета ? Послать то, на что DPI не рассчитывает -и что ломает ему алгоритм распознавания запросов и их блокировки. - -Некоторые DPI не могут распознать http запрос, если он разделен на TCP сегменты. -Например, запрос вида "GET / HTTP/1.1\r\nHost: kinozal.tv......" -мы посылаем 2 частями : сначала идет "GET ", затем "/ HTTP/1.1\r\nHost: kinozal.tv.....". -Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:". -Кое-где работает добавление дополнительного пробела после метода : "GET /" => "GET /" -или добавление точки в конце имени хоста : "Host: kinozal.tv." - -Существует и более продвинутая магия, направленная на преодоление DPI на пакетном уровне. - -Подробнее про DPI : - https://habr.com/ru/post/335436 - https://geneva.cs.umd.edu/papers/geneva_ccs19.pdf - - -Что сейчас происходит в России ------------------------------- - -Раньше, до внедрения повсеместных систем ТСПУ, использовался зоопарк различных DPI -у провайдеров. Какие-то были активными, какие-то пассивными. -Сейчас время простых iptables окончательно ушло. Везде активный DPI ТСПУ, но кое-где -могут оставаться невыключенными дополнительные старые DPI из зоопарка. -В этом случае приходится обходить сразу несколько DPI. -Все больше становится внереестровых блокировок, о которых вы узнаете только по факту -недоступности чего-либо, в списках этого нет. -Применяются блокировки некоторых диапазонов ip адресов (автономный обход невозможен) -и протоколов (VPN). -На некоторых диапазонах IP используется более строгий фильтр, распознающий попытки -обмана через сегментацию. Должно быть это связано с некоторыми сервисами, которые -пытаются таким образом обмануть DPI. - - -Как это реализовать на практике в системе linux ------------------------------------------------ - -Если кратко, то варианты можно классифицировать по следующей схеме : - -1) Пассивный DPI, не отправляющий RST серверу. Помогут индивидуально настраиваемые под провайдера команды iptables. -На rutracker в разделе "обход блокировок - другие способы" по этому вопросу существует отдельная тема. -В данном проекте не рассматривается. Если вы не допустите срабатывание триггера запрета, то и не придется -бороться с его последствиями. -2) Модификация TCP соединения на уровне потока. Реализуется через proxy или transparent proxy. -3) Модификация TCP соединения на уровне пакетов. Реализуется через обработчик очереди NFQUEUE и raw сокеты. - -Для вариантов 2 и 3 реализованы программы tpws и nfqws соответственно. -Чтобы они работали, необходимо их запустить с нужными параметрами и перенаправить на них определенный трафик -средствами iptables или nftables. - - -Для перенаправления tcp соединения на transparent proxy используются команды следующего вида : - -проходящий трафик : -iptables -t nat -I PREROUTING -i <внутренний_интерфейс> -p tcp --dport 80 -j DNAT --to 127.0.0.127:988 -исходящий трафик : -iptables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988 - -DNAT на localhost работает в цепочке OUTPUT, но не работает в цепочке PREROUTING без включения параметра route_localnet : - -sysctl -w net.ipv4.conf.<внутренний_интерфейс>.route_localnet=1 - -Можно использовать "-j REDIRECT --to-port 988" вместо DNAT, однако в этом случае процесс transparent proxy -должен слушать на ip адресе входящего интерфейса или на всех адресах. Слушать на всех - не есть хорошо -с точки зрения безопасности. Слушать на одном (локальном) можно, но в случае автоматизированного -скрипта придется его узнавать, потом динамически вписывать в команду. В любом случае требуются дополнительные усилия. -Использование route_localnet тоже имеет потенциальные проблемы с безопасностью. Вы делаете доступным все, что висит -на 127.0.0.0/8 для локальной подсети <внутренний_интерфейс>. Службы обычно привязываются к 127.0.0.1, поэтому можно -средствами iptables запретить входящие на 127.0.0.1 не с интерфейса lo, либо повесить tpws на любой другой IP из -из 127.0.0.0/8, например на 127.0.0.127, и разрешить входящие не с lo только на этот IP. - -iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT -iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP - -Фильтр по owner необходим для исключения рекурсивного перенаправления соединений от самого tpws. -tpws запускается под пользователем "tpws", для него задается исключающее правило. - -tpws может использоваться в режиме socks proxy. В этом случае iptables не нужны, а нужно прописать socks -в настройки программы (например, броузера), с которой будем обходить блокировки. -transparent proxy отличается от socks именно тем, что в варианте transparent настраивать клиентские программы не нужно. - - -Для перенаправления на очередь NFQUEUE исходящего и проходящего в сторону внешнего интерфейса трафика используются -команды следующего вида : - -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass - - -Чтобы не трогать трафик на незаблокированные адреса, можно взять список заблокированных хостов, заресолвить его -в IP адреса и загнать в ipset zapret, затем добавить фильтр в команду : - -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass - -DPI может ловить только первый http запрос, игнорируя последующие запросы в keep-alive сессии. -Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов. - -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass - -Фильтр по mark нужен для отсечения от очереди пакетов, сгенерированных внутри nfqws. -Если применяется фильтр по connbytes 1:6, то обязательно добавлять в iptables и фильтр по mark. Иначе возможно -перепутывание порядка следования пакетов, что приведет к неработоспособности метода. - -Для некоторых атак на DPI требуется перенаправлять один или несколько входящих пакетов от соединения : - -iptables -t mangle -I PREROUTING -i <внешний_интерфейс> -p tcp --sport 80 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass - -Получаемые пакеты будут фильтроваться по входящему интерфейсу, порту и IP источника, то есть наоборот прямому правилу. - -Некоторые техники, ломающие NAT, не всегда можно реализовать через iptables. Требуются nftables. - - -Если ваше устройство поддерживает аппаратное ускорение (flow offloading, hardware nat, hardware acceleration), то iptables могут не работать. -При включенном offloading пакет не проходит по обычному пути netfilter. -Необходимо или его отключить, или выборочно им управлять. - -В новых ядрах (и в более старых, openwrt портировал изменение на 4.14) присутствует software flow offloading (SFO). -Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. -При включенном SFO работает DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. -Однако, остальные соединения идут через SFO, потому NFQUEUE будет срабатывать только до помещения -соединения в flowtable. Практически это означает, что nfqws будет работать на window size changing, -но не будут работать опции по модификации содержимого пакетов. -Offload включается через специальный target в iptables "FLOWOFFLOAD". Не обязательно пропускать весь трафик через offload. -Можно исключить из offload соединения, которые должны попасть на tpws или nfqws. -openwrt не предусматривает выборочного управления offload. -Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в openwrt. - - -Особенности применения ip6tables --------------------------------- - -ip6tables работают почти точно так же, как и ipv4, но есть ряд важных нюансов. -В DNAT следует брать адрес --to в квадратные скобки. Например : - - ip6tables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:988 - -Параметра route_localnet не существует для ipv6. -DNAT на localhost (::1) возможен только в цепочке OUTPUT. -В цепочке PREROUTING DNAT возможен на любой global address или на link local address того же интерфейса, -откуда пришел пакет. -NFQUEUE работает без изменений. - - -Особенности применения nftables -------------------------------- - -Более подробно преимущества и недостатки nftables применительно к данной системе описаны в docs/nftables_notes.txt -Если коротко, то в nftables невозможно работать с большими ip листами на системах с малым количеством RAM. -Остальные рассматриваемые здесь функции могут быть перенесены на nftables. - -Рекомендуется версия nft 1.0.2 или выше. Но чем выше версия, тем лучше. В nft регулярно находят баги. - -Относительно старые версии ядра и/или утилиты nft могут вызывать ошибки. -В частности, на ubuntu 18.04 с ядром 4.15 будут проблемы. В 20.04 - работает. - -Некоторые техники можно полноценно использовать только с nftables. -Например, в iptables невозможно перенаправить пакеты на nfqws после NAT. -Следовательно, при использовании NAT невозможно произвести атаку, не совместимую с NAT. -В nftables этой проблемы не существует, потому что приоритеты хука выставляете вы сами, а не привязаны к фиксированным -значениям, соответствующим разным таблицам iptables. В iptables нет таблицы, способной перехватить пакеты после MASQUERDADE. - - -Когда это работать не будет ---------------------------- - -* Если подменяется DNS. С этой проблемой легко справиться. -* Если блокировка осуществляется по IP. -* Если соединение проходит через фильтр, способный реконструировать TCP соединение, и который -следует всем стандартам. Например, нас заворачивают на squid. Соединение идет через полноценный стек tcpip -операционной системы, фрагментация отпадает сразу как средство обхода. Squid правильный, он все найдет -как надо, обманывать его бесполезно. -НО. Заворачивать на squid могут позволить себе лишь небольшие провайдеры, поскольку это очень ресурсоемко. -Большие компании обычно используют DPI, который рассчитан на гораздо большую пропускную способность. -Может применяться комбинированный подход, когда на DPI заворачивают только IP из "плохого" списка, -и дальше уже DPI решает пропускать или нет. Так можно снизить нагрузку на DPI в десятки, если не сотни раз, -а следовательно не покупать очень дорогие решения, обойдясь чем-то существенно более дешевым. -Мелкие провайдеры могут покупать услугу фильтрации у вышестоящих, чтобы самим не морочиться, и -они уже будут применять DPI. - - -nfqws ------ - -Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. -Для BSD систем существует адаптированный вариант - dvtws, собираемый из тех же исходников (см. bsd.txt). - - --debug=0|1 ; 1=выводить отладочные сообщения - --daemon ; демонизировать прогу - --pidfile= ; сохранить PID в файл - --user= ; менять uid процесса - --uid=uid[:gid] ; менять uid процесса - --qnum=N ; номер очереди N - --bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов - --bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов - --wsize=[:] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !) - --wssize=[:] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !) - --wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N - --ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60 - --hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:". - --hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета - --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase - --domcase ; домен после Host: сделать таким : TeSt.cOm - --dpi-desync=[,][, ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000 - --dpi-desync-ttl= ; установить ttl для десинхронизирующих пакетов - --dpi-desync-ttl6= ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl - --dpi-desync-autottl=[[:[-]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию. - --dpi-desync-autottl6=[[:[-]]] ; переопределение предыдущего параметра для ipv6 - --dpi-desync-fooling= ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2 - --dpi-desync-repeats= ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты) - --dpi-desync-skip-nosni=0| 1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI - --dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции - --dpi-desync-split-http-req=method|host ; разбивка http request на указанном логическом месте - --dpi-desync-split-tls=sni|sniext ; разбивка tls client hello на указанном логическом месте - --dpi-desync-split-seqovl= ; использовать sequence overlap перед первым отсылаемым оригинальным tcp сегментом - --dpi-desync-split-seqovl-pattern=|0xHEX ; чем заполнять фейковую часть overlap - --dpi-desync-badseq-increment= ; инкремент sequence number для badseq. по умолчанию -10000 - --dpi-desync-badack-increment= ; инкремент ack sequence number для badseq. по умолчанию -66000 - --dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных - --dpi-desync-fake-http=|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org - --dpi-desync-fake-tls=|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному - --dpi-desync-fake-unknown=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт - --dpi-desync-fake-syndata=|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata - --dpi-desync-fake-quic=|0xHEX ; файл, содержащий фейковый QUIC Initial - --dpi-desync-fake-dht=|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт - --dpi-desync-fake-unknown-udp=|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт - --dpi-desync-udplen-increment= ; насколько увеличивать длину udp пейлоада в режиме udplen - --dpi-desync-udplen-pattern=|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули - --dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N - --dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N - --hostlist= ; применять дурение только к хостам из листа. может быть множество листов, они объединяются. пустой обший лист = его отсутствие - --hostlist-exclude= ; не применять дурение к хостам из листа. может быть множество листов, они объединяются - --hostlist-auto= ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) - --hostlist-auto-fail-threshold= ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) - --hostlist-auto-fail-time= ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) - --hostlist-auto-retrans-threshold= ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3) - --hostlist-auto-debug= ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. - -Параметры манипуляции могут сочетаться в любых комбинациях. - -ЗАМЕЧАНИЕ. Параметр --wsize считается устаревшим и более не поддерживается в скриптах. -Функции сплита выполняются в рамках атаки десинхронизации. Это быстрее и избавляет от целого ряда недостатков wsize. - ---debug позволяет выводить подробный лог действий на консоль, в syslog или в файл. -Может быть важен порядок следования опций. --debug лучше всего указывать в самом начале. -Опции анализируются последовательно. Если ошибка будет при проверке опции, а до анализа --debug еще дело не дошло, -то сообщения не будут выведены в файл или syslog. -При логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается. -Так что файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог. -Но имейте в виду, что если вы запускаете процесс под root, то будет сменен UID на не-root. -В начале на лог файл меняется owner, иначе запись будет невозможна. Если вы потом удалите файл, -и у процесса не будет прав на создание файла в его директории, лог больше не будет вестись. -Вместо удаления лучше использовать truncate. -В шелле это можно сделать через команду ": >filename" - -АТАКА ДЕСИНХРОНИЗАЦИИ DPI -Суть ее в следующем. После выполнения tcp 3-way handshake идет первый пакет с данными от клиента. -Там обычно "GET / ..." или TLS ClientHello. Мы дропаем этот пакет, заменяя чем-то другим. -Это может быть поддельная версия с безобидным, но валидным запросом http или https (вариант fake), -пакет сброса соединения (варианты rst, rstack), разбитый на части оригинальный пакет с перепутанным -порядком следования сегментов + обрамление первого сегмента фейками (disorder), -то же самое без перепутывания порядка сегментов (split). -fakeknown отличается от fake тем, что применяется только к распознанному протоколу. -В литературе такие атаки еще называют TCB desynchronization и TCB teardown. -Надо, чтобы фейковые пакеты дошли до DPI, но не дошли до сервера. -На вооружении есть следующие возможности : установить низкий TTL, посылать пакет с инвалидной чексуммой, -добавлять tcp option "MD5 signature", испортить sequence numbers. Все они не лишены недостатков. - -* md5sig работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux. -* badsum не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. - Наиболее распространенная настройка NAT роутера в Linux их не пропускает. На Linux построено большинство - домашних роутеров. Непропускание обеспечивается так : настройка ядра sysctl по умолчанию - net.netfilter.nf_conntrack_checksum=1 заставляет conntrack проверять tcp и udp чексуммы входящих пакетов - и выставлять state INVALID для пакетов с инвалидной суммой. - Обычно в правилах iptables вставляется правило для дропа пакетов с состоянием INVALID в цепочке FORWARD. - Совместное сочетание этих факторов приводит к непрохождению badsum через такой роутер. - В openwrt из коробки net.netfilter.nf_conntrack_checksum=0, в других роутерах часто нет, - и не всегда это можно изменить. Чтобы nfqws мог работать через роутер, нужно на нем выставить указанное - значение sysctl в 0. nfqws на самом роутере будет работать и без этой настройки, потому что - чексумма локально созданных пакетов не проверяется никогда. - Если роутер за другим NAT, например провайдерским, и он не пропускает invalid packets - вы ничего не сможете с этим сделать. Но обычно провайдеры все же пропускают badsum. - На некоторых адаптерах/свитчах/драйверах принудительно включен rx-checksum offload, badsum пакеты отсекаются - еще до получения в ОС. В этом случае если что-то и можно сделать, то только модифицировать драйвер, - что представляется задачей крайне нетривиальной. Установлено, что так себя ведут некоторые роутеры на базе mediatek. - badsum пакеты уходят с клиентской ОС, но роутером не видятся в br-lan через tcpdump. - При этом если nfqws выполняется на самом роутере, обход может работать. badsum нормально уходят с внешнего интерфейса. -* Пакеты с badseq будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется - на sequence numbers. По умолчанию смещение seq выбирается -10000. Практика показала, что некоторые DPI - не пропускают seq вне определенного окна. Однако, такое небольшое смещение может вызвать проблемы - при существенной потоковой передаче и потере пакетов. Если вы используете --dpi-desync-any-protocol, - может понадобится установить badseq increment 0x80000000. Это обеспечит надежную гарантию, - что поддельный пакет не вклинится в tcp window на сервере. Так же было замечено, что badseq ломает логику - некоторых DPI при анализе http, вызывая зависание соединения. Причем на тех же DPI TLS с badseq работает нормально. -* TTL казалось бы - лучший вариант, но он требует индивидуальной настройки под каждого провайдера. - Если DPI находится дальше локальных сайтов провайдера, то вы можете отрезать себе доступ к ним. - Ситуация усугубляется наличием ТСПУ на магистралах, что вынуждает делать TTL достаточно высоким, увеличивая - риск пробоя фейка до сервера. - Необходим ip exclude list, заполняемый вручную. Вместе с ttl можно применять md5sig. Это ничего не испортит, - зато дает неплохой шанс работы сайтов, до которых "плохой" пакет дойдет по TTL. - Если не удается найти автоматическое решение, воспользуйтесь файлом zapret-hosts-user-exclude.txt. - Некоторые стоковые прошивки роутеров фиксируют исходящий TTL, без отключения этой опции через них работать не будет. - КАКИМ СТОИТ ВЫБИРАТЬ TTL : найдите минимальное значение, при котором обход еще работает. - Это и будет номер хопа вашего DPI. -* hopbyhop относится только к ipv6. Добавляется ipv6 extenstion header "hop-by-hop options". - В варианте hopbyhop2 добавляются 2 хедера, что является нарушением стандарта и гарантированно отбрасывается - стеком протоколов во всех ОС. Один хедер hop-by-hop принимается всеми ОС, однако на некоторых каналах/провайдерах - такие пакеты могут фильтроваться и не доходить. Расчет идет на то, что DPI проанализирует пакет с hop-by-hop, - но он либо не дойдет до адресата всилу фильтров провайдера, либо будет отброшен сервером, потому что хедера два. -* datanoack высылает фейки со снятым tcp флагом ACK. Сервера такое не принимают, а DPI может принять. - Эта техника может ломать NAT и не всегда работает с iptables, если используется masquerade, даже с локальной - системы (почти всегда на роутерах ipv4). На системах c iptables без masquerade и на nftables работает без - ограничений. Экспериментально выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому - работает даже с внутренним провайдерским IP. Но linux NAT оно не пройдет, так что за домашним роутером эта - техника не сработает, но может сработать с него. -* autottl. Суть режима в автоматическом определении TTL, чтобы он почти наверняка прошел DPI и немного не дошел до - сервера. Берутся базовые значения TTL 64,128,255, смотрится входящий пакет - (да, требуется направить первый входящий пакет на nfqws !). - Вычисляется длина пути, отнимается delta (1 по умолчанию). Если TTL вне диапазона (min,max - 3,20 по умолчанию), - то берутся значения min,max, чтобы вписаться в диапазон. Если при этом полученный TTL больше длины пути, - то автоматизм не сработал и берутся фиксированные значения TTL для атаки. - Техника позволяет решить вопрос, когда вся сеть перегорожена шлагбаумами (DPI, ТСПУ) везде где только можно, - включая магистралов. Но потенциально может давать сбои. - Например, при асимметрии входящего и исходящего канала до конкретного сервера. - На каких-то провайдерах эта техника будет работать неплохо, на других доставит больше проблем, чем пользы. - Где-то может потребоваться тюнинг параметров. Лучше использовать с дополнительным ограничителем. - -Режимы дурения могут сочетаться в любых комбинациях. --dpi-desync-fooling берет множество значений через запятую. - -Для режимов fake, rst, rstack после фейка отправляем оригинальный пакет. - -Режим disorder делит оригинальный пакет на 2 части и отправляет следующую комбинацию в указанном порядке : -1. 2-я часть пакета -2. поддельная 1-я часть пакета, поле данных заполнено нулями -3. 1-я часть пакета -4. поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз. -Оригинальный пакет дропается всегда. Параметр --dpi-desync-split-pos позволяет указать байтовую позицию, на которой -происходит разбивка. По умолчанию - 2. Если позиция больше длины пакета, позиция выбирается 1. -Этой последовательностью для DPI максимально усложняется задача реконструкции начального сообщения, -по которому принимается решение о блокировке. Некоторым DPI хватит и tcp сегментов в неправильном порядке, -поддельные части сделаны для дополнительной надежности и более сложных алгоритмов реконструкции. -Режим disorder2 отключает отправку поддельных частей. - -Режим split очень похож на disorder, только нет изменения порядка следования сегментов : -1. поддельная 1-я часть пакета, поле данных заполнено нулями -2. 1-я часть пакета -3. поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз. -4. 2-я часть пакета -Режим split2 отключает отправку поддельных частей. -Он может быть использован как более быстрая альтернатива --wsize. - -disorder2 и split2 не предполагают отсылку фейк пакетов, поэтому опции ttl и fooling неактуальны. - -seqovl добавляет в начало первой отсылаемой части оригинального пакета (1 часть для split и 2 часть для disorder) -seqovl байт со смещенным в минус sequence number на величину seqovl. -В случае split2 расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, -поэтому новая пришедшая часть лишь частично находится в пределах текущего окна (in-window). -Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и начинается с начала window, -поэтому попадает в сокет. -Серверное приложение получает все, что реально отсылает клиент, отбрасывая фейковую out-of-window часть. -Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация. - -Для disorder2 overlap идет на 2-ю часть пакета. Обязательно, чтобы seqovl был меньше split_pos, иначе -все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня. -При соблюдении этого условия 2-я часть пакета является полностью in-window, -поэтому серверная ОС принимает ее целиком, включая фейк. Но поскольку начальная часть данных из 1 пакета -еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение. -Как только приходит 1-я часть пакета, она переписывает фейковую часть в памяти ядра. -Ядро получает данные из 1 и 2 части, поэтому далее идет отправка в сокет приложения. -Таково поведение всех unix ОС, кроме solaris - оставлять последние принятые данные. -Windows оставляет старые данные, поэтому disorder с seqovl будет приводить к зависаниям соединения -при работе с Windows серверами. Solaris практически мертв, windows серверов очень немного. -Можно использовать листы при необходимости. -Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными. -split/disorder вместо split2/disorder2 по-прежнему добавляют дополнительные отдельные фейки. - -Режимы десинхронизации hopbyhop, destopt и ipfrag1 (не путать с fooling !) относятся только к ipv6 и заключается -в добавлении хедера "hop-by-hop options", "destination options" или "fragment" во все пакеты, попадающие под десинхронизацию. -Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено -к пакетам максимального размера. Это имеет место при передаче больших сообщений. -В случае невозможности отослать пакет дурение будет отменено, пакет будет выслан в оригинале. -Расчет идет на то, что DPI увидит 0 в поле next header основного заголовка ipv6 и не будет скакать по -extension хедерам в поисках транспортного хедера. Таким образом не поймет, что это tcp или udp, и пропустит пакет -без анализа. Возможно, какие-то DPI на это купятся. -Может сочетаться с любыми режимами 2-й фазы, кроме варианта "ipfrag1+ipfrag2". -Например, "hopbyhop,split2" означает разбить tcp пакет на 2 сегмента, в каждый из них добавить hop-by-hop. -При "hopbyhop,ipfrag2" последовательность хедеров будет : ipv6,hop-by-hop,fragment,tcp/udp. -Режим "ipfrag1" может срабатывать не всегда без специальной подготовки. См. раздел "IP фрагментация". - -Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены. -Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1. -В варианте disorder обычно приходит сперва частичное подтверждение (SACK), потом полный ACK. -Если вместо ACK или SACK идет RST пакет с минимальной задержкой, то DPI вас отсекает еще на этапе вашего запроса. -Если RST идет после полного ACK спустя задержку, равную примерно пингу до сервера, -тогда вероятно DPI реагирует на ответ сервера. -DPI может отстать от потока, если ClientHello его удовлетворил и не проверять ServerHello. -Тогда вам повезло. Вариант fake может сработать. -Если же он не отстает и упорно проверяет ServerHello, то можно попробовать заставить сервер высылать ServerHello частями -через параметр --wssize (см. conntrack). -Если и это не помогает, то сделать с этим что-либо вряд ли возможно без помощи со стороны сервера. -Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде. -Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI. - -Хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. -Субдомены учитываются автоматически. Поддерживаются листы gzip. - -iptables для задействования атаки на первый пакет данных : - -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass - -Этот вариант применяем, когда DPI не следит за всеми запросами http внутри keep-alive сессии. -Если следит, направляем только первый пакет от https и все пакеты от http : - -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass -iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass - -mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке. -хотя nfqws способен самостоятельно различать помеченные пакеты, фильтр в iptables по mark нужен при использовании connbytes, -чтобы не допустить изменения порядка следования пакетов. Процессинг очереди - процесс отложенный. -Если ядро имеет пакеты на отсылку вне очереди - оно их отправляет незамедлительно. -Изменение правильного порядка следования пакетов при десинхронизации ломает всю идею. -При отсутствии ограничения на connbytes, атака будет работать и без фильтра по mark. -Но лучше его все же оставить для увеличения скорости. - -Почему --connbytes 1:6 : -1 - для работы методов десинхронизации 0-й фазы и wssize -2 - иногда данные идут в 3-м пакете 3-way handshake -3 - стандартная ситуация приема одного пакета запроса -4-6 - на случай ретрансмиссии или запроса длиной в несколько пакетов (TLSClientHello с kyber, например) - -КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ -В параметре dpi-desync можно указать до 3 режимов через запятую. -0 фаза предполагает работу на этапе установления соединения. Может быть synack или syndata. -На 0 фазу не действует фильтр по hostlist. -Последующие режимы отрабатывают на пакетах с данными. -Режим 1-й фазы может быть fake,rst,rstack. Режим 2-й фазы может быть disorder,disorder2,split,split2,ipfrag2. -Может быть полезно, когда у провайдера стоит не один DPI. - -РЕЖИМ SYNACK -В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно -ролей клиента и сервера. -!!! Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством -и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него. -Для реализации атаки в linux обязательно требуется отключить стандартное правило firewall, -дропающее инвалидные пакеты в цепочке OUTPUT. Например : -A OUTPUT -m state --state INVALID -j DROP -В openwrt можно отключить drop INVALID в OUTPUT и FORWARD через опцию в /etc/config/firewall : - -config zone - option name 'wan' - ......... - option masq_allow_invalid '1' - -К сожалению, отключить только в OUTPUT таким образом нельзя. Но можно сделать иначе. Вписать в /etc/firewall.user : - -iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT -ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT - -Лучше делать так, потому что отсутствие дропа INVALID в FORWARD может привести к нежелательным утечкам пакетов из LAN. -Если не принять эти меры, отсылка SYN,ACK сегмента вызовет ошибку и операция будет прервана. -Остальные режимы тоже не сработают. Если поймете, что вам synack не нужен, обязательно верните правило дропа INVALID. - -РЕЖИМ SYNDATA -Тут все просто. Добавляются данные в пакет SYN. Все ОС их игнорируют, если не используется TCP fast open (TFO), -а DPI может воспринять, не разобравшись есть там TFO или нет. -Оригинальные соединения с TFO не трогаются, поскольку это их точно сломает. -Без уточняющего параметра добавляются 16 нулевых байтов. - -ВИРТУАЛЬНЫЕ МАШИНЫ -Изнутри VM от virtualbox и vmware в режиме NAT не работают многие техники пакетной магии nfqws. -Принудительно заменяется ttl, не проходят фейк пакеты. Необходимо настроить сеть в режиме bridge. - -CONNTRACK -nfqws оснащен ограниченной реализацией слежения за состоянием tcp соединений (conntrack). -Он включается для реализации некоторых методов противодействия DPI. -conntrack способен следить за фазой соединения : SYN,ESTABLISHED,FIN, количеством пакетов в каждую сторону, -sequence numbers. conntrack способен "кормиться" пакетами в обе или только в одну сторону. -Соединение попадает в таблицу при обнаружении пакетов с выставленными флагами SYN или SYN,ACK. -Поэтому если необходим conntrack, в правилах перенаправления iptables соединение должно идти на nfqws с самого первого -пакета, хотя затем может обрываться по фильтру connbytes. -Для UDP инициатором попадания в таблицу является первый UDP пакет. Он же и определяет направление потока. -Считается, что первый UDP пакет исходит от клиента к серверу. Далее все пакеты с совпадающими -src_ip,src_port,dst_ip,dst_port считаются принадлежащими этому потоку до истечения времени неактивности. -conntrack - простенький, он не писался с учетом всевозможных атак на соединение, он не проверяет -пакеты на валидность sequence numbers или чексумму. Его задача - лишь обслуживание нужд nfqws, он обычно -кормится только исходящим трафиком, потому нечувствителен к подменам со стороны внешней сети. -Соединение удаляется из таблицы, как только отпадает нужда в слежении за ним или по таймауту неактивности. -Существуют отдельные таймауты на каждую фазу соединения. Они могут быть изменены параметром --ctrack-timeouts. - ---wssize позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части. -Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения, -ответ на который должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы -знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически. -В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет. -В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello. -Если вы имеете дело с не http(s), то вам потребуется параметр --wssize-cutoff. Он устанавливает предел, с которого действие -wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number, -проще говоря количество переданных клиентом байтов + 1. -Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff. -Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр --ctrack-timeouts. -Таймаут по умолчанию низкий - всего 5 минут. -Не забывайте, что nfqws кормится приходящими на него пакетами. Если вы ограничили поступление пакетов через connbytes, -то в таблице могут остаться повисшие соединения в фазе ESTABLISHED, которые отвалятся только по таймауту. -Для диагностики состояния conntrack пошлите сигнал SIGUSR1 процессу nfqws : killall -SIGUSR1 nfqws. -Текущая таблица будет выведена nfqws в stdout. - -Обычно в SYN пакете клиент отсылает кроме window size еще и TCP extension "scaling factor". -scaling factor представляет из себя степень двойки, на которую умножается window size : 0=>1, 1=>2, 2=>4, ..., 8=>256, ... -В параметре wssize scaling factor указывается через двоеточие. -Scaling factor может только снижаться, увеличение заблокировано, чтобы не допустить превышение размера окна со стороны сервера. -Для принуждения сервера к фрагментации ServerHello, чтобы избежать просекание имени сервера из сертификата сервера на DPI, -лучше всего использовать --wssize=1:6 . Основное правило - делать scale_factor как можно больше, чтобы после восстановления -window size итоговый размер окна стал максимально возможным. Если вы сделаете 64:0, будет очень медленно. -С другой стороны нельзя допустить, чтобы ответ сервера стал достаточно большим, чтобы DPI нашел там искомое. - -На --wssize не влияет фильтр hostlist, поскольку он действует с самого начала соединения, когда еще нельзя -принять решение о попадании в лист. ---wssize может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы -обхода DPI, лучше применять их. - ---dpi-desync-cutoff позволяет задать предел, при достижении которого прекращается применение dpi-desync. -Доступны префиксы n,d,s по аналогии с --wssize-cutoff. -Полезно совместно с --dpi-desync-any-protocol=1. -На склонных к бездействию соединениях следует изменить таймауты conntrack. -Если соединение выпало из conntrack и задана опция --dpi-desync-cutoff, dpi desync применяться не будет. - -РЕАССЕМБЛИНГ -nfqws поддерживает реассемблинг некоторых видов запросов. -На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую -криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124. -chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть -попасть любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом -принимает решение о блокировке. -В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты -задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию -на основании полностью собранного ClientHello. -При любой ошибке в процессе сборки задержанные пакеты немедленно отсылаются в сеть, а десинхронизация отменяется. - -Есть специальная поддержка всех вариантов tcp сплита для многосегментного TLS. -Если указать позицию сплита больше длины первого пакета или использовать --dpi-desync-split-tls, -то разбивка происходит не обязательно первого пакета, а того, на который пришлась итоговая позиция. -Если, допустим, клиент послал TLS ClientHello длиной 2000, а SNI начинается с 1700, -и заданы опции fake,split2, то перед первым пакетом идет fake, затем первый пакет в оригинале, -а последний пакет разбивается на 2 сегмента. В итоге имеем фейк в начале и 3 реальных сегмента. - -ПОДДЕРЖКА UDP -Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip. -Для UDP действуют только режимы десинхронизации fake,hopbyhop,destopt,ipfrag1,ipfrag2,udplen,tamper. -Возможно сочетание fake,hopbyhop,destopt с ipfrag2, fake,fakeknown с udplen и tamper. -udplen увеличивает размер udp пакета на указанное в --dpi-desync-udplen-increment количество байтов. -Паддинг заполняется нулями по умолчанию, но можно задать свой паттерн. -Предназначено для обмана DPI, ориентирующегося на размеры пакетов. -Может сработать, если пользовательский протокол не привязан жестко к размеру udp пейлоада. -Режим tamper означает модификацию пакетов известных протоколов особенным для протокола образом. -На текущий момент работает только с DHT. -Поддерживается определение пакетов QUIC Initial с расшифровкой содержимого и имени хоста, то есть параметр ---hostlist будет работать. -Определяются пакеты wireguard handshake initiation и DHT (начинается с 'd1', кончается 'e'). -Для десинхронизации других протоколов обязательно указывать --dpi-desync-any-protocol. -Реализован conntrack для udp. Можно пользоваться --dpi-desync-cutoff. Таймаут conntrack для udp -можно изменить 4-м параметром в --ctrack-timeouts. -Атака fake полезна только для stateful DPI, она бесполезна для анализа на уровне отдельных пакетов. -По умолчанию fake наполнение - 64 нуля. Можно указать файл в --dpi-desync-fake-unknown-udp. - -IP ФРАГМЕНТАЦИЯ -Современная сеть практически не пропускает фрагментированные tcp на уровне ip. -На udp с этим дело получше, поскольку некоторые udp протоколы могут опираться на этот механизм (IKE старых версий). -Однако, кое-где бывает, что режут и фрагментированный udp. -Роутеры на базе linux могут самопроизвольно собирать или перефрагментировать пакеты. -Позиция фрагментации задается отдельно для tcp и udp. По умолчанию 24 и 8 соответственно, должна быть кратна 8. -Смещение считается с транспортного заголовка. - -Существует ряд моментов вокруг работы с фрагментами на Linux, без понимания которых может ничего не получиться. - -ipv4 : Linux дает отсылать ipv4 фрагменты, но стандартные настройки iptables в цепочке OUTPUT могут вызывать ошибки отправки. - -ipv6 : Нет способа для приложения гарантированно отослать фрагменты без дефрагментации в conntrack. -На разных системах получается по-разному. Где-то нормально уходят, где-то пакеты дефрагментируются. -Для ядер <4.16 похоже, что нет иного способа решить эту проблему, кроме как выгрузить модуль nf_conntrack, -который подтягивает зависимость nf_defrag_ipv6. Он то как раз и выполняет дефрагментацию. -Для ядер 4.16+ ситуация чуть лучше. Из дефрагментации исключаются пакеты в состоянии NOTRACK. -Чтобы не загромождать описание, смотрите пример решения этой проблемы в blockcheck.sh. - -Иногда требуется подгружать модуль ip6table_raw с параметром raw_before_defrag=1. -В openwrt параметры модулей указываются через пробел после их названий в файлах /etc/modules.d. -В традиционных системах посмотрите используется ли iptables-legacy или iptables-nft. Если legacy, то нужно создать файл -/etc/modprobe.d/ip6table_raw.conf с содержимым : -options ip6table_raw raw_before_defrag=1 -В некоторых традиционных дистрибутивах можно изменить текущий ip6tables через : update-alternatives --config ip6tables -Если вы хотите оставаться на iptables-nft, вам придется пересобрать патченную версию. Патч совсем небольшой. -В nft.c найдите фрагмент : - { - .name = "PREROUTING", - .type = "filter", - .prio = -300, /* NF_IP_PRI_RAW */ - .hook = NF_INET_PRE_ROUTING, - }, - { - .name = "OUTPUT", - .type = "filter", - .prio = -300, /* NF_IP_PRI_RAW */ - .hook = NF_INET_LOCAL_OUT, - }, -и замените везде -300 на -450. - -Это нужно сделать вручную, никакой автоматики в blockcheck.sh нет. - -Либо можно раз и навсегда избавиться от этой проблемы, используя nftables. Там можно создать netfilter hook -с любым приоритетом. Используйте приоритет -401 и ниже. - -При использовании iptables и NAT, похоже, что нет способа прицепить обработчик очереди после NAT. -Пакет попадает в nfqws с source адресом внутренней сети, затем фрагментируется и уже не обрабатывается NAT. -Так и уходит во внешюю сеть с src ip 192.168.x.x. Следовательно, метод не срабатывает. -Видимо единственный рабочий метод - отказаться от iptables и использовать nftables. -Хук должен быть с приоритетом 101 или выше. - -tpws ------ - -tpws - это transparent proxy. - --debug=0|1|2|syslog|@ ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка. - --debug-level=0|1|2 ; указать уровень логирования для syslog и @ - --daemon ; демонизировать прогу - --pidfile= ; сохранить PID в файл - --user= ; менять uid процесса - --uid=uid[:gid] ; менять uid процесса - --bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес - ; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan - --bind-linklocal=no|unwanted|prefer|force - ; no : биндаться только на global ipv6 - ; unwanted (default) : предпочтительно global, если нет - LL - ; prefer : предпочтительно LL, если нет - global - ; force : биндаться только на LL - --bind-iface4= ; слушать на первом ipv4 интерфейса iface - --bind-iface6= ; слушать на первом ipv6 интерфейса iface - --bind-wait-ifup= ; ждать до N секунд появления и поднятия интерфейса - --bind-wait-ip= ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса) - --bind-wait-ip-linklocal= - ; имеет смысл только при задании --bind-wait-ip - ; --bind-linklocal=unwanted : согласиться на LL после N секунд - ; --bind-linklocal=prefer : согласиться на global address после N секунд - --bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0. - --connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес - ; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan - ; опция может повторяться для v4 и v6 адресов - ; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local. - --socks ; вместо прозрачного прокси реализовать socks4/5 proxy - --no-resolve ; запретить ресолвинг имен через socks5 - --resolve-threads ; количество потоков ресолвера - --port= ; на каком порту слушать - --maxconn= ; максимальное количество соединений от клиентов к прокси - --maxfiles= ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга. - ; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16 - --max-orphan-time=; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений, - ; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...) - ; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных, - ; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго. - ; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию - ; эта функция не действует на успешно подключенные ранее соединения - - --local-rcvbuf= ; SO_RCVBUF для соединений client-proxy - --local-sndbuf= ; SO_SNDBUF для соединений client-proxy - --remote-rcvbuf= ; SO_RCVBUF для соединений proxy-target - --remote-sndbuf= ; SO_SNDBUF для соединений proxy-target - --nosplice ; не использовать splice на linux системах - --skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split. - --local-tcp-user-timeout= ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение) - --remote-tcp-user-timeout= ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение) - - --split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host - --split-pos= ; делить все посылы на сегменты в указанной позиции. единственная опция, работающая на не-http. при указании split-http-req он имеет преимущество на http. - --split-any-protocol ; применять split-pos к любым пакетам. по умолчанию - только к http и TLS ClientHello - --disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса - --oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита - --oob-data=|0xHEX ; переопределить байт OOB. по умолчанию 0x00. - --hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:". - --hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase - --hostdot ; добавление точки после имени хоста : "Host: kinozal.tv." - --hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t" - --hostnospace ; убрать пробел после "Host:" - --hostpad= ; добавить паддинг-хедеров общей длиной перед Host: - --domcase ; домен после Host: сделать таким : TeSt.cOm - --methodspace ; добавить пробел после метода : "GET /" => "GET /" - --methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /" - --unixeol ; конвертировать 0D0A в 0A и использовать везде 0A - --tlsrec=sni|sniext ; разбивка TLS ClientHello на 2 TLS records. режем между 1 и 2 символами hostname в SNI или между байтами длины SNI extension. Если SNI нет - отмена. - --tlsrec-pos= ; разбивка TLS ClientHello на 2 TLS records. режем на указанной позиции, если длина слишком мелкая - на позиции 1. - --mss= ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость - --mss-pf=[~]port1[-port2] ; применять MSS только к портам назначения, подпадающим под фильтр. ~ означает инверсию - --tamper-start=[n] ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока) - --tamper-cutoff=[n] ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока) - --hostlist= ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. - ; в файле должен быть хост на каждой строке. - ; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска. - ; по сигналу HUP список будет перечитан при следующем принятом соединении - ; список может быть запакован в gzip. формат автоматически распознается и разжимается - ; списков может быть множество, они объединяются. пустой общий лист = его отсутствие - ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. - --hostlist-exclude= ; не применять дурение к доменам из листа. может быть множество листов, они объединяются - --hostlist-auto= ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) - --hostlist-auto-fail-threshold= ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) - --hostlist-auto-fail-time= ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) - --hostlist-auto-debug= ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты. - - ---debug позволяет выводить подробный лог действий на консоль, в syslog или в файл. -Может быть важен порядок следования опций. --debug лучше всего указывать в самом начале. -Опции анализируются последовательно. Если ошибка будет при проверке опции, а до анализа --debug еще дело не дошло, -то сообщения не будут выведены в файл или syslog. ---debug=0|1|2 позволяют сразу в одном параметре включить логирование на консоль и указать уровень. -Сохранено для совместимости с более старыми версиями. Для выбора уровня в режиме syslog или file используйте -отдельный параметр --debug-level. Если в этих режимах --debug не указывать уровень через --debug-level, то -автоматически назначается уровень 1. -При логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается. -Так что файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог. -Но имейте в виду, что если вы запускаете процесс под root, то будет сменен UID на не-root. -В начале на лог файл меняется owner, иначе запись будет невозможна. Если вы потом удалите файл, -и у процесса не будет прав на создание файла в его директории, лог больше не будет вестись. -Вместо удаления лучше использовать truncate. -В шелле это можно сделать через команду ": >filename" - -Параметры манипуляции могут сочетаться в любых комбинациях. - -В случае http запроса split-http-req имеет преимущество над split-pos. -split-pos по умолчанию работает только на http и TLS ClientHello. -Чтобы он работал на любых пакетах, укажите --split-any-protocol. - -На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть -блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета. -Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке -отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет. -Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему, -никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии, -что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI. -Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса. -Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае. -Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда, -когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан, -но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут -к отсылке сегментов данных разными ip пакетами. -Резюме : tpws гарантирует сплит только за счет раздельных вызовов send, что на практике -вполне достаточно для протоколов http(s). - -tpws может биндаться на множество интерфейсов и IP адресов (до 32 шт). -Порт всегда только один. -Параметры --bind-iface* и --bind-addr создают новый бинд. -Остальные параметры --bind-* относятся к последнему бинду. -Для бинда на все ipv4 укажите --bind-addr "0.0.0.0", на все ipv6 - "::". --bind-addr="" - биндаемся на все ipv4 и ipv6. -Выбор режима использования link local ipv6 адресов (fe80::/8) : ---bind-iface6 --bind-linklocal=no : сначала приватный адрес fc00::/7, затем глобальный адрес ---bind-iface6 --bind-linklocal=unwanted : сначала приватный адрес fc00::/7, затем глобальный адрес, затем link local. ---bind-iface6 --bind-linklocal=prefer : сначала link local, затем приватный адрес fc00::/7, затем глобальный адрес. ---bind-iface6 --bind-linklocal=force : только link local -Если не указано ни одного бинда, то создается бинд по умолчанию на все адреса всех интерфейсов. -Для бинда на конкретный link-local address делаем так : --bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name -Параметры --bind-wait* могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят -или не сконфигурирован. -В разных системах события ifup ловятся по-разному и не гарантируют, что интерфейс уже получил IP адрес определенного типа. -В общем случае не существует единого механизма повеситься на событие типа "на интерфейсе X появился link local address". -Для бинда на известный ip, когда еще интерфейс не сконфигурирован, нужно делать так : --bind-addr=192.168.5.3 --bind-wait-ip=20 -В режиме transparent бинд возможен на любой несуществующий адрес, в режиме socks - только на существующий. - -Параметры rcvbuf и sndbuf позволяют установить setsockopt SO_RCVBUF SO_SNDBUF для локального и удаленного соединения. - -Если не указан ни один из параметров модификации содержимого, tpws работает в режиме "tcp proxy mode". -Он отличается тем, что в оба конца применяется splice для переброски данных из одного сокета в другой -без копирования в память процесса. Практически - это то же самое, но может быть чуть побыстрее. -TCP проксирование может быть полезно для обхода блокировок, когда DPI спотыкается на экзотических -хедерах IP или TCP. Вы вряд ли сможете поправить хедеры, исходящие от айфончиков и гаджетиков, -но на linux сможете влиять на них в какой-то степени через sysctl. -Когда соединение проходит через tpws, фактически прокси-сервер сам устанавливает подключение к удаленному -узлу от своего имени, и на это распространяются настройки системы, на которой работает прокси. -tpws можно использовать на мобильном устройстве, раздающем интернет на тарифе сотового оператора, -где раздача запрещена, в socks режиме даже без рута. Соединения от tpws неотличимы от соединений -с самого раздающего устройства. Отличить можно только по содержанию (типа обновлений windows). -Заодно можно и обойти блокировки. 2 зайца одним выстрелом. -Более подробную информацию по вопросу обхода ограничений операторов гуглите на 4pda.ru. - -Режим "--socks" не требует повышенных привилегий (кроме бинда на привилегированные порты 1..1023). -Поддерживаются версии socks 4 и 5 без авторизации. Версия протокола распознается автоматически. -Подключения к IP того же устройства, на котором работает tpws, включая localhost, запрещены. -socks5 позволяет удаленно ресолвить хосты (curl : --socks5-hostname firefox : socks_remote_dns=true). -tpws поддерживает эту возможность асинхронно, не блокируя процессинг других соединений, используя -многопоточный пул ресолверов. Количество потоков определяется автоматически в зависимости от "--maxconn", -но можно задать и вручную через параметр "--resolver-threads". -Запрос к socks выставляется на паузу, пока домен не будет преобразован в ip адрес в одном из потоков -ресолвера. Ожидание может быть более длинным, если все потоки заняты. -Если задан параметр "--no-resolve", то подключения по именам хостов запрещаются, а пул ресолверов не создается. -Тем самым экономятся ресурсы. - -Параметр --hostpad= добавляет паддинг-хедеров перед Host: на указанное количество байтов. -Если размер слишком большой, то идет разбивка на разные хедеры по 2K. -Общий буфер приема http запроса - 64K, больший паддинг не поддерживается, да и http сервера -такое уже не принимают. -Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером. -Если техника работает, то после некоторого количества bytes http запрос начнет проходить до сайта. -Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции --split-… -Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения. - ---disorder - это попытка симулировать режим disorder2 nfqws, используя особенности ОС по реализации stream сокетов. -Однако, в отличие от nfqws, здесь не требуются повышенные привилегии. -Реализовано это следующим образом. У сокета есть возможность выставить TTL. Все пакеты будут отправляться с ним. -Перед отправкой первого сегмента ставим TTL=1. Пакет будет дропнут на первом же роутере, он не дойдет ни до DPI, ни до сервера. -Затем возвращаем TTL в значение по умолчанию. ОС отсылает второй сегмент, и он уже доходит до сервера. -Сервер возвращает SACK, потому что не получил первый кусок, и ОС его отправляет повторно, но здесь уже мы ничего не делаем. -Этот режим работает как ожидается на Linux и MacOS. Однако, на FreeBSD и OpenBSD он работает не так хорошо. -Ядро этих ОС отсылает ретрансмиссию в виде полного пакета. Потому выходит, что до сервера идет сначала второй кусок, -а потом полный запрос без сплита. На него может отреагировать DPI штатным образом. ---disorder является дополнительным флагом к любому сплиту. Сам по себе он не делает ничего. - ---tlsrec и --tlsrec-pos позволяют внутри одного tcp сегмента разрезать TLS ClientHello на 2 TLS records. ---tlsrec=sni режет между 1 и 2 символами hostname в SNI, делая невозможным бинарный поиск паттерна без анализа -структуры данных. В случае отсутствия SNI разбиение отменяется. ---tlsrec-pos режет на указанной позиции. Если длина блока данных TLS меньше указанной позиции, режем на позиции 1. -Параметр сочетается с --split-pos. В этом случае происходит сначала разделение на уровне TLS record layer, потом на уровне TCP. -Самая изощрённая атака --tlsrec, --split-pos и --disorder вместе. ---tlsrec ломает значительное количество сайтов. Криптобиблиотеки (openssl, ...) на оконечных http серверах -без проблем принимают разделенные tls сегменты, но мидлбоксы - не всегда. К мидлбоксам можно отнести CDN -или системы ddos-защиты. Поэтому применение --tlsrec без ограничителей вряд ли целесообразно. -В РФ --tlsrec обычно не работает с TLS 1.2, потому что цензор парсит сертификат сервера из ServerHello. -Работает только с TLS 1.3, поскольку там эта информация шифруется. -Впрочем, сейчас сайтов, не поддерживающих TLS 1.3, осталось немного. - ---mss устанавливает опцию сокета TCP_MAXSEG. Клиент выдает это значение в tcp опциях SYN пакета. -Сервер в ответ в SYN,ACK выдает свой MSS. На практике сервера обычно снижают размеры отсылаемых ими пакетов, но они -все равно не вписываются в низкий MSS, указанный клиентом. Обычно чем больше указал клиент, тем больше -шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет, -это может обмануть DPI, секущий ответ сервера. -Схема может значительно снизить скорость и сработать не на всех сайтах. -С фильтром по hostlist совместимо только в режиме socks при включенном удаленном ресолвинге хостов. -(firefox network.proxy.socks_remote_dns). Это единственный вариант, когда tpws может узнать имя хоста -еще на этапе установления соединения. -Невозможен фильтр по версии TLS. -Взамен имеется фильтр по портам --mss-pf. --mss-pf=443 применяет дурение только к https. -Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже. -Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в -3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который -может привести к реакции DPI. -Использовать только когда нет ничего лучше или для отдельных ресурсов. -Работает только на linux, не работает на BSD и MacOS. - ---skip-nodelay может быть полезен, чтобы привести MTU к MTU системы, на которой работает tpws. -Это может быть полезно для скрытия факта использования VPN. Пониженный MTU - 1 из способов обнаружения -подозрительного подключения. С tcp proxy ваши соединения неотличимы от тех, что сделал бы сам шлюз. - ---local-tcp-user-timeout и --remote-tcp-user-timeout устанавливают значение таймаута в секундах -для соединений клиент-прокси и прокси-сервер. Этот таймаут соответствует опции сокета linux -TCP_USER_TIMEOUT. Под таймаутом подразумевается время, в течение которого буферизированные данные -не переданы или на переданные данные не получено подтверждение (ACK) от другой стороны. -Этот таймаут никак не касается времени отсутствия какой-либо передачи через сокет лишь потому, -что данных для передачи нет. Полезно для сокращения время закрытия подвисших соединений. -Поддерживается только на Linux и MacOS. - -Способы получения списка заблокированных IP -------------------------------------------- - -!!! nftables не могут работать с ipset-ами. Собственный аналогичный механизм требует огромного количество RAM -!!! для загрузки больших листов. Например, для загона 100K записей в nfset не хватает даже 256 Mb. -!!! Если вам нужны большие листы на домашних роутерах, откатывайтесь на iptables+ipset. - -1) Внесите заблокированные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh -На выходе получите ipset/zapret-ip-user.txt с IP адресами. - -Cкрипты с названием get_reestr_* оперируют дампом реестра заблокированных сайтов : - -2) ipset/get_reestr_resolve.sh получает список доменов от rublacklist и дальше их ресолвит в ip адреса -в файл ipset/zapret-ip.txt.gz. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде, -что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко -банят по IP : вместо этого они банят http запросы с "нехорошим" заголовком "Host:" вне зависимости -от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени. -Используется мультипоточный ресолвер mdig (собственная разработка). - -3) ipset/get_reestr_preresolved.sh. то же самое, что и 2), только берется уже заресолвленый список -со стороннего ресурса. - -4) ipset/get_reestr_preresolved_smart.sh. то же самое, что и 3), с добавлением всего диапазона некоторых -автономных систем (прыгающие IP адреса из cloudflare, facebook, ...) и некоторых поддоменов блокируемых сайтов - -Cкрипты с названием get_antifilter_* оперируют списками адресов и масок подсетей с сайтов antifilter.network и antifilter.download : - -5) ipset/get_antifilter_ip.sh. получает лист https://antifilter.download/list/ip.lst. - -6) ipset/get_antifilter_ipsmart.sh. получает лист https://antifilter.network/download/ipsmart.lst. -умная суммаризация отдельных адресов из ip.lst по маскам от /32 до /22 - -7) ipset/get_antifilter_ipsum.sh. получает лист https://antifilter.download/list/ipsum.lst. -суммаризация отдельных адресов из ip.lst по маске /24 - -8) ipset/get_antifilter_ipresolve.sh. получает лист https://antifilter.download/list/ipresolve.lst. -пре-ресолвленный список, аналогичный получаемый при помощи get_reestr_resolve. только ipv4. - -9) ipset/get_antifilter_allyouneed.sh. получает лист https://antifilter.download/list/allyouneed.lst. -Суммарный список префиксов, созданный из ipsum.lst и subnet.lst. - -Все варианты рассмотренных скриптов автоматически создают и заполняют ipset. -Варианты 2-9 дополнительно вызывают вариант 1. - -10) ipset/get_config.sh. этот скрипт вызывает то, что прописано в переменной GETLIST из файла config -Если переменная не определена, то ресолвятся лишь листы для ipset nozapret/nozapret6. - -Листы РКН все время изменяются. Возникают новые тенденции. Требования к RAM могут меняться. -Поэтому необходима нечастая, но все же регулярная ревизия что же вообще у вас происходит на роутере. -Или вы можете узнать о проблеме лишь когда у вас начнет постоянно пропадать wifi, и вам придется -его перезагружать каждые 2 часа (метод кувалды). - -Самые щадящие варианты по RAM - get_antifilter_allyouneed.sh, get_antifilter_ipsum.sh. - -Листы zapret-ip.txt и zapret-ipban.txt сохраняются в сжатом виде в файлы .gz. -Это позволяет снизить их размер во много раз и сэкономить место на роутере. -Отключить сжатие листов можно параметром конфига GZIP_LISTS=0. - -На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет -либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку. -В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней -флэш памятью, то вы просто убьете роутер. - -Принудительное обновление ipset выполняет скрипт ipset/create_ipset.sh. -Если передан параметр "no-update", скрипт не обновляет ipset, а только создает его при его отсутствии и заполняет. -Это полезно, когда могут случиться несколько последовательных вызовов скрипта. Нет смысла несколько раз перезаполнять -ipset, это длительная операция на больших листах. Листы можно обновлять раз в несколько суток, и только тогда -вызывать create_ipset без параметра "no-update". Во всех остальных случаях стоит применять "no-update". - -Список РКН уже достиг внушительных размеров в сотни тысяч IP адресов. Поэтому для оптимизации ipset -применяется утилита ip2net. Она берет список отдельных IP адресов и пытается интеллектуально создать из него подсети для сокращения -количества адресов. ip2net отсекает неправильные записи в листах, гарантируя отсутствие ошибок при их загрузке. -ip2net написан на языке C, поскольку операция ресурсоемкая. Иные способы роутер может не потянуть. - -Можно внести список доменов в ipset/zapret-hosts-user-ipban.txt. Их ip адреса будут помещены -в отдельный ipset "ipban". Он может использоваться для принудительного завертывания всех -соединений на прозрачный proxy "redsocks" или на VPN. - -IPV6 : если включен ipv6, то дополнительно создаются листы с таким же именем, но с "6" на конце перед расширением. -zapret-ip.txt => zapret-ip6.txt -Создаются ipset-ы zapret6 и ipban6. -Листы с antifilter не содержат список ipv6 адресов. - -СИСТЕМА ИСКЛЮЧЕНИЯ IP. Все скрипты ресолвят файл zapret-hosts-user-exclude.txt, создавая zapret-ip-exclude.txt и zapret-ip-exclude6.txt. -Они загоняются в ipset-ы nozapret и nozapret6. Все правила, создаваемые init скриптами, создаются с учетом этих ipset. -Помещенные в них IP не участвуют в процессе. -zapret-hosts-user-exclude.txt может содержать домены, ipv4 и ipv6 адреса или подсети. - -FreeBSD. Скрипты ipset/*.sh работают так же на FreeBSD. Вместо ipset они создают lookup таблицы ipfw с аналогичными именами. -ipfw таблицы в отличие от ipset могут содержать как ipv4, так и ipv6 адреса и подсети в одной таблице, поэтому разделения нет. - -Параметр конфига LISTS_RELOAD задает произвольную команду для перезагрузки листов. -Это особенно полезно на BSD системах с PF. -LISTS_RELOAD=- отключает перезагрузку листов. - - -ip2net ------- - -Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей -с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в stdout. - - -4 ; лист - ipv4 (по умолчанию) - -6 ; лист - ipv6 - --prefix-length=min[-max] ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6) - --v4-threshold=mul/div ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4 - --v6-threshold=N ; ipv6 : минимальное количество ip для создания подсети - -В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений. -Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix. -ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2. -ip2net фильтрует входные данные, выкидывая неправильные IP адреса. - -Выбирается подсеть, в которой присутствует указанный минимум адресов. -Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую. - -Размер подсети выбирается следующим алгоритмом : -Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально. -Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше). -Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 : -1234:5678:aaaa::5 -1234:5678:aaaa::6 -1234:5678:aaac::5 -Результат будет : -1234:5678:aaa8::/45 -Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой, -когда те же самые адреса вполне влезают в /45 и их ровно столько же. -Если изменить v6_threshold=4, то результат будет : -1234:5678:aaaa::5 -1234:5678:aaaa::6 -1234:5678:aaac::5 -То есть ip не объединятся в подсеть, потому что их слишком мало. -Если изменить prefix_length=56-64, результат будет : -1234:5678:aaaa::/64 -1234:5678:aaac::5 - -Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа. -Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов. -Учтите, что арифметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем. -Не надо делать такое : 5000000/10000000. 1/2 - гораздо лучше. - - -Фильтрация по именам доменов ----------------------------- - -Альтернативой ipset является использование tpws или nfqws со списком доменов. -Оба демона принимают неограниченное количество листов include (--hostlist) и exclude (--hostlist-exclude). -Все листы одного типа объединяются, и таким образом остаются только 2 листа. -Прежде всего проверяется exclude list. При вхождении в него происходит отказ от дурения. -Далее при наличии include list проверяется домен на вхождение в него. При невхождении в список отказ от дурения. -Пустой список приравнивается к его отсутствию. -В иных случаях происходит дурение. -Нет ни одного списка - дурение всегда. -Есть только exclude список - дурение всех, кроме. -Есть только include список - дурение только их. -Есть оба - дурение только include, кроме exclude. - -В системе запуска это обыграно следующим образом. -Присутствуют 2 include списка : -ipset/zapret-hosts-users.txt.gz или ipset/zapret-hosts-users.txt -ipset/zapret-hosts.txt.gz или ipset/zapret-hosts.txt -и 1 exclude список -ipset/zapret-hosts-users-exclude.txt.gz или ipset/zapret-hosts-users-exclude.txt - -При режиме фильтрации MODE_FILTER=hostlist система запуска передает nfqws или tpws все листы, файлы которых присутствуют. -Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа. -Файл есть, но не смотря на это дурится все, кроме exclude. -Если вам нужен именно такой режим - не обязательно удалять zapret-hosts-users.txt. Достаточно сделать его пустым. - -Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает. - -Список доменов РКН может быть получен скриптами ipset/get_reestr_hostlist.sh или ipset/get_antizapret_domains.sh -- кладется в ipset/zapret-hosts.txt.gz. - -Чтобы обновить списки, перезапускать nfqws или tpws не нужно. Обновляете файлы, затем даете сигнал HUP. -По HUP листы будут перечитаны. Если вдруг какого-то листа не окажется, процесс завершится с ошибкой. -Скрипты получения листов из ipset сами выдают HUP в конце. - -При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset. -tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic). -При использовании больших списков, в том числе списка РКН, оцените объем RAM на роутере ! -Если после запуска демона RAM под завязку или случаются oom, значит нужно отказаться от таких больших списков. - - -Режим фильтрации autohostlist ------------------------------ - -Этот режим позволяет проанализировать как запросы со стороны клиента, так и ответы от сервера. -Если хост еще не находится ни в каких листах и обнаруживается ситуация, похожая на блокировку, -происходит автоматическое добавление хоста в список autohostlist как в памяти, так и в файле. -nfqws или tpws сами ведут этот файл. -Чтобы какой-то хост не смог попась в autohostlist используйте hostlist-exclude. -Если он все-же туда попал - удалите запись из файла вручную. Процессы автоматически перечитают файл. -tpws/nfqws сами назначают владельцем файла юзера, под которым они работают после сброса привилегий, -чтобы иметь возможность обновлять лист. - -В случае nfqws данный режим требует перенаправления в том числе и входящего трафика. -Крайне рекомендовано использовать ограничитель connbytes, чтобы nfqws не обрабатывал гигабайты. -По этой же причине не рекомендуется использование режима на BSD системах. Там нет фильтра connbytes. - -На linux системах при использовании nfqws и фильтра connbytes может понадобится : -sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 -Было замечено, что некоторые DPI в России возвращают RST с неверным ACK. Это принимается tcp/ip стеком -linux, но через раз приобретает статус INVALID в conntrack. Поэтому правила с connbytes срабатывают -через раз, не пересылая RST пакет nfqws. - -Как вообще могут вести себя DPI, получив "плохой запрос" и приняв решение о блокировке : - -1) Зависание : просто отмораживается, блокируя прохождение пакетов по TCP каналу. -2) RST : отправляет RST клиенту и/или серверу -3) Редирект : (только для http) отправляет редирект на сайт-заглушку -4) Подмена сертификата : (только для https) полный перехват TLS сеанса с попыткой всунуть что-то -свое клиенту. Применяется нечасто, поскольку броузеры на такое ругаются. - -nfqws и tpws могут сечь варианты 1-3, 4 они не распознают. -Всилу специфики работы с отдельными пакетами или с TCP каналом tpws и nfqws распознают эти ситуации -по-разному. -Что считается ситуацией, похожей на блокировку : -1) [nfqws] Несколько ретрансмиссий первого запроса в TCP сеансе, в котором имеется host. -2) [nfqws,tpws] RST, пришедший в ответ на первый запрос с хостом. -3) [nfqws,tpws] HTTP редирект, пришедший в ответ на первый запрос с хостом, на глобальный адрес -с доменом 2 уровня, не совпадающим с доменом 2 уровня оригинального запроса. -4) [tpws] закрытие соединения клиентом после отправки первого запроса с хостом, если не было на него -ответа со стороны сервера. Это обычно случается по таймауту, когда нет ответа (случай "зависание"). - -Чтобы снизить вероятность ложных срабатываний, имеется счетчик ситуаций, похожих на блокировку. -Если за определенное время произойдет более определенного их количества, хост считается заблокированным -и заносится в autohostlist. По нему сразу же начинает работать стратегия по обходу блокировки. -Если в процессе счета вебсайт отвечает без признаков блокировки, счетчик сбрасывается. -Вероятно, это был временный сбой сайта. - -На практике работа с данным режимом выглядит так. -Первый раз пользователь заходит на сайт и получает заглушку, сброс соединения или броузер подвисает, -вываливаясь по таймауту с сообщением о невозможности загрузить страницу. -Надо долбить F5, принуждая броузер повторять попытки. После некоторой попытки сайт -начинает работать, и дальше он будет работать всегда. - -С этим режимом можно использовать техники обхода, ломающие значительное количество сайтов. -Если сайт не ведет себя как заблокированный, значит обход применен не будет. -В противном случае терять все равно нечего. -Однако, могут быть временные сбои сервера, приводящие к ситуации, аналогичной блокировке. -Могут происходит ложные срабатывания. Если такое произошло, стратегия может начать ломать -незаблокированный сайт. Эту ситуацию, увы, придется вам контролировать вручную. -Заносите такие домены в ipset/zapret-hosts-user-exclude.txt, чтобы избежать повторения. -Чтобы впоследствии разобраться почему домен был занесен в лист, можно включить autohostlist debug log. -Он полезен тем, что работает без постоянного просмотра вывода nfqws в режиме debug. -В лог заносятся только основные события, ведущие к занесению хоста в лист. -По логу можно понять как избежать ложных срабатываний и подходит ли вообще вам этот режим. - -Можно использовать один autohostlist с множеством процессов. Все процессы проверяют время модификации файла. -Если файл был изменен в другом процессе, то происходит перечитывание всех include листов, включая autohostlist. -Все процессы должны работать под одним uid, чтобы были права доступа на файл. - -Скрипты zapret ведут autohostlist в ipset/zapret-hosts-auto.txt. -install_easy.sh при апгрейде zapret сохраняет этот файл. -Режим autohostlist включает в себя режим hostlist. -Можно вести ipset/zapret-hosts-user.txt, ipset/zapret-hosts-user-exclude.txt. - - -Проверка провайдера -------------------- - -Перед настройкой нужно провести исследование какую бяку устроил вам ваш провайдер. - -Нужно выяснить не подменяет ли он DNS и какой метод обхода DPI работает. -В этом вам поможет скрипт blockcheck.sh. - -Если DNS подменяется, но провайдер не перехватывает обращения к сторонним DNS, поменяйте DNS на публичный. -Например : 8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1, 9.9.9.9 -Если DNS подменяется и провайдер перехватывает обращения к сторонним DNS, настройте dnscrypt. -Еще один эффективный вариант - использовать ресолвер от yandex 77.88.8.88 на нестандартном порту 1253. -Многие провайдеры не анализируют обращения к DNS на нестандартных портах. - -Следует прогнать blockcheck по нескольким заблокированным сайтам и выявить общий характер блокировок. -Разные сайты могут быть заблокированы по-разному, нужно искать такую технику, которая работает на большинстве. -Чтобы записать вывод blockcheck.sh в файл, выполните : ./blockcheck.sh | tee /tmp/blockcheck.txt - -Проанализируйте какие методы дурения DPI работают, в соответствии с ними настройте /opt/zapret/config. - -Имейте в виду, что у провайдеров может быть несколько DPI или запросы могут идти через разные каналы -по методу балансировки нагрузки. Балансировка может означать, что на разных ветках разные DPI или -они находятся на разных хопах. Такая ситуация может выражаться в нестабильности работы обхода. -Дернули несколько раз curl. То работает, то connection reset или редирект. blockcheck.sh выдает -странноватые результаты. То split работает на 2-м. хопе, то на 4-м. Достоверность результата вызывает сомнения. -В этом случае задайте несколько повторов одного и того же теста. Тест будет считаться успешным только, -если все попытки пройдут успешно. - -При использовании autottl следует протестировать как можно больше разных доменов. Эта техника -может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах -она стабильна, на третьих полный хаос, и проще отказаться. - -Blockcheck имеет 3 уровня сканирования. -Цель режима quick - максимально быстро найти хоть что-то работающее. -standard дает возможность провести исследование как и на что реагирует DPI в плане методов обхода. -force дает максимум проверок даже в случаях, когда ресурс работает без обхода или с более простыми стратегиями. - -СКАН ПОРТОВ -Если в системе присутствует совместимый netcat (ncat от nmap или openbsd ncat. в openwrt по умолчанию нет.), -то выполняется сканирование портов http или https всех IP адресов домена. -Если ни один IP не отвечает, то результат очевиден. Можно останавливать сканирование. -Автоматически оно не остановится, потому что netcat-ы недостаточно подробно информируют о причинах ошибки. -Если доступна только часть IP, то можно ожидать хаотичных сбоев, т.к. подключение идет к случайному адресу -из списка. - -ПРОВЕРКА НА ЧАСТИЧНЫЙ IP block -Под частичным блоком подразумевается ситуация, когда коннект на порты есть, но по определенному транспортному -или прикладному протоколу всегда идет реакция DPI вне зависимости от запрашиваемого домена. -Эта проверка так же не выдаст автоматического вердикта/решения, потому что может быть очень много вариаций. -Вместо этого анализ происходящего возложен на самого пользователя или тех, кто будет читать лог. -Суть этой проверки в попытке дернуть неблокированный IP с блокированным доменом и наоборот, анализируя -при этом реакцию DPI. Реакция DPI обычно проявляется в виде таймаута (зависание запроса), connection reset -или http redirect на заглушку. Любой другой вариант скорее всего говорит об отсутствии реакции DPI. -В частности, любые http коды, кроме редиректа, ведущего именно на заглушку, а не куда-то еще. -На TLS - ошибки handshake без задержек. -Ошибка сертификата может говорить как о реакции DPI с MiTM атакой (подмена сертификата), так и -о том, что принимающий сервер неблокированного домена все равно принимает ваш TLS handshake с чужим доменом, -пытаясь при этом выдать сертификат без запрошенного домена. Требуется дополнительный анализ. -Если на заблокированный домен есть реакция на всех IP адресах, значит есть блокировка по домену. -Если на неблокированный домен есть реакция на IP адресах блокированного домена, значит имеет место блок по IP. -Соответственно, если есть и то, и другое, значит есть и блок по IP, и блок по домену. -Неблокированный домен первым делом проверяется на доступность на оригинальном адресе. -При недоступности тест отменяется, поскольку он будет неинформативен. - -Если выяснено, что есть частичный блок по IP на DPI, то скорее всего все остальные тесты будут провалены -вне зависимости от стратегий обхода. Но бывают и некоторые исключения. Например, пробитие через ipv6 -option headers. Или сделать так, чтобы он не мог распознать протокол прикладного уровня. -Дальнейшие тесты могут быть не лишены смысла. - -ПРИМЕРЫ БЛОКИРОВКИ ТОЛЬКО ПО ДОМЕНУ БЕЗ БЛОКА ПО IP - -> testing iana.org on it's original ip -!!!!! AVAILABLE !!!!! -> testing rutracker.org on 192.0.43.8 (iana.org) -curl: (28) Operation timed out after 1002 milliseconds with 0 bytes received -> testing iana.org on 172.67.182.196 (rutracker.org) -HTTP/1.1 409 Conflict -> testing iana.org on 104.21.32.39 (rutracker.org) -HTTP/1.1 409 Conflict - -> testing iana.org on it's original ip -!!!!! AVAILABLE !!!!! -> testing rutracker.org on 192.0.43.8 (iana.org) -curl: (28) Connection timed out after 1001 milliseconds -> testing iana.org on 172.67.182.196 (rutracker.org) -curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure -> testing iana.org on 104.21.32.39 (rutracker.org) -curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure - -> testing iana.org on it's original ip -!!!!! AVAILABLE !!!!! -> testing rutracker.org on 192.0.43.8 (iana.org) -HTTP/1.1 307 Temporary Redirect -Location: https://www.gblnet.net/blocked.php -> testing iana.org on 172.67.182.196 (rutracker.org) -HTTP/1.1 409 Conflict -> testing iana.org on 104.21.32.39 (rutracker.org) -HTTP/1.1 409 Conflict - -> testing iana.org on it's original ip -!!!!! AVAILABLE !!!!! -> testing rutracker.org on 192.0.43.8 (iana.org) -curl: (35) Recv failure: Connection reset by peer -> testing iana.org on 172.67.182.196 (rutracker.org) -curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure -> testing iana.org on 104.21.32.39 (rutracker.org) -curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure - - -ПРИМЕР ПОЛНОГО IP БЛОКА ИЛИ БЛОКА TCP ПОРТА ПРИ ОТСУТСТВИИ БЛОКА ПО ДОМЕНУ - -* port block tests ipv4 startmail.com:80 -ncat -z -w 1 145.131.90.136 80 -145.131.90.136 does not connect. netcat code 1 -ncat -z -w 1 145.131.90.152 80 -145.131.90.152 does not connect. netcat code 1 - -* curl_test_http ipv4 startmail.com -- checking without DPI bypass -curl: (28) Connection timed out after 2002 milliseconds -UNAVAILABLE code=28 - -- IP block tests (requires manual interpretation) -> testing iana.org on it's original ip -!!!!! AVAILABLE !!!!! -> testing startmail.com on 192.0.43.8 (iana.org) -HTTP/1.1 302 Found -Location: https://www.iana.org/ -> testing iana.org on 145.131.90.136 (startmail.com) -curl: (28) Connection timed out after 2002 milliseconds -> testing iana.org on 145.131.90.152 (startmail.com) -curl: (28) Connection timed out after 2002 milliseconds - - -Выбор параметров ----------------- - -Файл /opt/zapret/config используется различными компонентами системы и содержит основные настройки. -Его нужно просмотреть и при необходимости отредактировать. - -На linux системах можно выбрать использовать iptables или nftables. -По умолчанию на традиционных linux выбирается nftables, если установлен nft. -На openwrt по умолчанию выбирается nftables на новых версиях с firewall4. - -FWTYPE=iptables - -Основной режим : -tpws - tpws в режиме transparent -tpws-socks - tpws в режиме socks - вешается на localhost и LAN интерфейс (если задан IFACE_LAN или если система - OpenWRT). порт 988 -nfqws - nfqws -filter - только заполнить ipset или загрузить hostlist -custom - нужно самому запрограммировать запуск демонов в init скрипте и правила iptables - -MODE=tpws - -Применять ли дурение к HTTP : - -MODE_HTTP=1 - -Применять ли дурение к последовательным http запросам в одном tcp соединении (http keeaplive). -Относится только к nfqws. Выключение данной функции способно сэкономить загрузку процессора. -tpws всегда работает с http keepalive - -MODE_HTTP_KEEPALIVE=0 - -Применять ли дурение к HTTPS : - -MODE_HTTPS=1 - -Применять ли дурение к QUIC : - -MODE_QUIC=0 - -Режим фильтрации хостов : -none - применять дурение ко всем хостам -ipset - ограничить дурение ipset-ом zapret/zapret6 -hostlist - ограничить дурение списком хостов из файла -autohostlist - режим hostlist + распознавание блокировок и ведения автоматического листа - -MODE_FILTER=none - -Опции tpws : - -TPWS_OPT="--hostspell=HOST --split-http-req=method --split-pos=3" - -Опции nfqws для атаки десинхронизации DPI : - -DESYNC_MARK=0x40000000 -DESYNC_MARK_POSTNAT=0x20000000 -NFQWS_OPT_DESYNC="--dpi-desync=fake --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" - -Задание раздельных опций nfqws для http и https и для версий ip протоколов 4,6 : - -NFQWS_OPT_DESYNC_HTTP="--dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" -NFQWS_OPT_DESYNC_HTTPS="--wssize=1:6 --dpi-desync=split --dpi-desync-ttl=0 --dpi-desync-fooling=badsum" -NFQWS_OPT_DESYNC_HTTP6="--dpi-desync=split --dpi-desync-ttl=5 --dpi-desync-fooling=none" -NFQWS_OPT_DESYNC_HTTPS6="--wssize=1:6 --dpi-desync=split --dpi-desync-ttl=5 --dpi-desync-fooling=none" - -Если какая-то из переменных NFQWS_OPT_DESYNC_HTTP/NFQWS_OPT_DESYNC_HTTPS не определена, -берется значение NFQWS_OPT_DESYNC. -Если какая-то из переменных NFQWS_OPT_DESYNC_HTTP6/NFQWS_OPT_DESYNC_HTTPS6 не определена, -берется значение NFQWS_OPT_DESYNC_HTTP/NFQWS_OPT_DESYNC_HTTPS. - -Опции дурения для QUIC : -NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake" -NFQWS_OPT_DESYNC_QUIC6="--dpi-desync=hopbyhop" -Если NFQWS_OPT_DESYNC_QUIC6 не задано, то берется NFQWS_OPT_DESYNC_QUIC. - -Настройка системы управления выборочным traffic offload (только если поддерживается) -donttouch : выборочное управление отключено, используется системная настройка, простой инсталлятор выключает системную настройку, если она не совместима с выбранным режимом -none : выборочное управление отключено, простой инсталлятор выключает системную настройку -software : выборочное управление включено в режиме software, простой инсталлятор выключает системную настройку -hardware : выборочное управление включено в режиме hardware, простой инсталлятор выключает системную настройку - -FLOWOFFLOAD=donttouch - -Параметр GETLIST указывает инсталлятору install_easy.sh какой скрипт дергать -для обновления списка заблокированных ip или хостов. -Он же вызывается через get_config.sh из запланированных заданий (crontab или systemd timer). -Поместите сюда название скрипта, который будете использовать для обновления листов. -Если не нужно, то параметр следует закомментировать. - -Можно индивидуально отключить ipv4 или ipv6. Если параметр закомментирован или не равен "1", -использование протокола разрешено. -#DISABLE_IPV4=1 -DISABLE_IPV6=1 - -Количество потоков для многопоточного DNS ресолвера mdig (1..100). -Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер ? -MDIG_THREADS=30 - -Место для хранения временных файлов. При скачивании огромных реестров в /tmp места может не хватить. -Если файловая система на нормальном носителе (не встроенная память роутера), то можно -указать место на флэшке или диске. -TMPDIR=/opt/zapret/tmp - -Опции для создания ipset-ов и nfset-ов - -SET_MAXELEM=262144 -IPSET_OPT="hashsize 262144 maxelem 2097152" - -Хук, позволяющий внести ip адреса динамически. $1 = имя таблицы -Адреса выводятся в stdout. В случае nfset автоматически решается проблема возможного пересечения интервалов. -IPSET_HOOK="/etc/zapret.ipset.hook" - -ПРО РУГАНЬ в dmesg по поводу нехватки памяти. -Может так случиться, что памяти в системе достаточно, но при попытке заполнить огромный ipset -ядро начинает громко ругаться, ipset заполняется не полностью. -Вероятная причина в том, что превышается hashsize, заданный при создании ipset (create_ipset.sh). -Происходит переаллокация списка, не находится непрерывных фрагментов памяти нужной длины. -Это лечится увеличением hashsize. Но чем больше hashsize, тем больше занимает ipset в памяти. -Задавать слишком большой hashsize для недостаточно больших списков нецелесообразно. - -Опции для вызова ip2net. Отдельно для листов ipv4 и ipv6. -IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4" -IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5" - -Настройка режима autohostlist. -AUTOHOSTLIST_RETRANS_THRESHOLD=3 -AUTOHOSTLIST_FAIL_THRESHOLD=2 -AUTOHOSTLIST_FAIL_TIME=60 -AUTOHOSTLIST_DEBUG=0 - -Включить или выключить сжатие больших листов в скриптах ipset/*.sh. По умолчанию включено. -GZIP_LISTS=1 - -Команда для перезагрузки ip таблиц фаервола. -Если не указано или пустое, выбирается автоматически ipset или ipfw при их наличии. -На BSD системах с PF нет автоматической загрузки. Там нужно указать команду явно : pfctl -f /etc/pf.conf -На более новых pfctl (есть в новых FreeBSD, нет в OpenBSD 6.8) можно дать команду загрузки только таблиц : pfctl -Tl -f /etc/pf.conf -"-" означает отключение загрузки листов даже при наличии поддерживаемого backend. -#LISTS_RELOAD="pfctl -f /etc/pf.conf" -#LISTS_RELOAD=- - -В openwrt существует сеть по умолчанию 'lan'. Только трафик с этой сети будет перенаправлен на tpws. -Но возможно задать другие сети или список сетей : -OPENWRT_LAN="lan lan2 lan3" - -В openwrt в качестве wan берутся интерфейсы, имеющие default route. Отдельно для ipv4 и ipv6. -Это можно переопределить : -OPENWRT_WAN4="wan4 vpn" -OPENWRT_WAN6="wan6 vpn6" - -Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables. -При иных значениях или если параметр закомментирован, правила применены не будут. -Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила. -На openwrt неприменимо при использовании firewall3+iptables. - -Следующие настройки не актуальны для openwrt : - -Если ваша система работает как роутер, то нужно вписать названия внутренних и внешних интерфейсов : -IFACE_LAN=eth0 -IFACE_WAN=eth1 -IFACE_WAN6="henet ipsec0" -Несколько интерфейсов могут быть вписаны через пробел. -Если IFACE_WAN6 не задан, то берется значение IFACE_WAN. - -ВАЖНО : настройка маршрутизации, маскарада и т.д. не входит в задачу zapret. -Включаются только режимы, обеспечивающие перехват транзитного трафика. -Возможно определить несколько интерфейсов следующим образом : IFACE_LAN="eth0 eth1 eth2" - -Прикручивание к системе управления фаерволом или своей системе запуска ----------------------------------------------------------------------- - -Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт -с имеющимся скриптом запуска. При повторном применении правил она могла бы поломать настройки iptables от zapret. -В этом случае правила для iptables должны быть прикручены к вашему фаерволу отдельно от запуска tpws или nfqws. - -Следующие вызовы позволяют применить или убрать правила iptables отдельно : - - /opt/zapret/init.d/sysv/zapret start_fw - /opt/zapret/init.d/sysv/zapret stop_fw - /opt/zapret/init.d/sysv/zapret restart_fw - -А так можно запустить или остановить демоны отдельно от фаервола : - - /opt/zapret/init.d/sysv/zapret start_daemons - /opt/zapret/init.d/sysv/zapret stop_daemons - /opt/zapret/init.d/sysv/zapret restart_daemons - -nftables сводят практически на нет конфликты между разными системами управления, поскольку позволяют -использовать независимые таблицы и хуки. Используется отдельная nf-таблица "zapret". -Если ваша система ее не будет трогать, скорее всего все будет нормально. - -Для nftables предусмотрено несколько дополнительных вызовов : - -Посмотреть set-ы интерфейсов, относящихся к lan, wan и wan6. По ним идет завертывание трафика. -А так же таблицу flow table с именами интерфейсов ingress hook. - /opt/zapret/init.d/sysv/zapret list_ifsets - -Обновить set-ы интерфейсов, относящихся к lan, wan и wan6. -Для традиционных linux список интерфейсов берется из переменных конфига IFACE_LAN, IFACE_WAN. -Для openwrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN. -Все интерфейсы lan и wan так же добавляются в ingress hook от flow table. - /opt/zapret/init.d/sysv/zapret reload_ifsets - -Просмотр таблицы без содержимого set-ов. Вызывает nft -t list table inet zapret - /opt/zapret/init.d/sysv/zapret list_table - -Так же возможно прицепиться своим скриптом к любой стадии применения и снятия фаервола со стороны zapret скриптов : - -INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up" -INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" -INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down" -INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down" - -Эти настройки доступны в config. -Может быть полезно, если вам нужно использовать nftables set-ы, например ipban/ipban6. -nfset-ы принадлежат только одной таблице, следовательно вам придется писать правила для таблицы zapret, -а значит нужно синхронизироваться с применением/снятием правил со стороны zapret скриптов. - - -Вариант custom --------------- - -custom код вынесен в отдельный shell include -/opt/zapret/init.d/sysv/custom -или -/opt/zapret/init.d/openwrt/custom - -Нужно свой код вписать в функции : -zapret_custom_daemons -zapret_custom_firewall -zapret_custom_firewall_nft - -В файле custom пишите ваш код, пользуясь хелперами из "functions" или "zapret". -Смотрите как там сделано добавление iptables или запуск демонов. -Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи -типа наличия/отсутствия ipv6, является ли система роутером, имена интерфейсов, ... -Хелперы это учитывают, вам нужно сосредоточиться лишь на фильтрах {ip,nf}tables и -параметрах демонов. - -Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку демонов. -Запуск это или остановка передается в параметре $1 (0 или 1). -В openwrt за остановку отвечает procd. - -Для фаервола кастом пишется отдельно для iptables и nftables. Все очень похоже, но отличается -написание фильтров и названия процедур хелперов. Если вам не нужны iptables или nftables - -можете не писать соответствующую функцию. - -Готовый custom скрипт custom-tpws4http-nfqws4https позволяет применить дурение -tpws к http и nfqws к https. При этом поддерживаются установки из config. -Его можно использовать как стартовую точку для написания своих скриптов. - - -Простая установка ------------------ - -install_easy.sh автоматизирует ручные варианты процедур установки (см manual_setup.txt). -Он поддерживает OpenWRT, linux системы на базе systemd или openrc и MacOS. - -Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров". - -Если система запуска поддерживается, но используется не поддерживаемый инсталлятором менеджер пакетов -или названия пакетов не соответствуют прописанным в инсталлятор, пакеты нужно установить вручную. -Всегда требуется curl. ipset - только для режима iptables, для nftables - не нужен. - -Для совсем обрезанных дистрибутивов (alpine) требуется отдельно установить iptables и ip6tables, либо nftables. - -В комплекте идут статические бинарники для большинства архитектур. Какой-то из них подойдет -с вероятностью 99%. Но если у вас экзотическая система, инсталлятор попробует собрать бинарники сам -через make. Для этого нужны gcc, make и необходимые -dev пакеты. Можно форсировать режим -компиляции следующим вызовом : - - install_easy.sh make - -Под openwrt все уже сразу готово для использования системы в качестве роутера. -Имена интерфейсов WAN и LAN известны из настроек системы. -Под другими системами роутер вы настраиваете самостоятельно. инсталлятор в это не вмешивается. -инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы. -Нужно понимать, что заворот проходящего трафика на tpws в прозрачном режиме происходит до выполнения маршрутизации, -следовательно возможна фильтрация по LAN и невозможна по WAN. -Решение о завороте на tpws локального исходящего трафика принимается после выполнения маршрутизации, -следовательно ситуация обратная : LAN не имеет смысла, фильтрация по WAN возможна. -Заворот на nfqws происходит всегда после маршрутизации, поэтому к нему применима только фильтрация по WAN. -Возможность прохождения трафика в том или ином направлении настраивается вами в процессе конфигурации роутера. - -Деинсталляция выполняется через uninstall_easy.sh - - -Простая установка на openwrt ----------------------------- - -Работает только если у вас на роутере достаточно места. - -Копируем zapret на роутер в /tmp. - -Запускаем установщик : - sh /tmp/zapret/install_easy.sh -Он скопирует в /opt/zapret только необходимый минимум файлов. - -После успешной установки можно удалить zapret из tmp для освобождения RAM : - rm -r /tmp/zapret - -Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров". - -Система простой инсталяции заточена на любое умышленное или неумышленное изменение прав доступа на файлы. -Устойчива к репаку под windows. После копирования в /opt права будут принудительно восстановлены. - -Android -------- - -Без рута забудьте про nfqws и tpws в режиме transparent proxy. tpws будет работать только в режиме --socks. - -Ядра Android имеют поддержку NFQUEUE. nfqws работает. - -В стоковых ядрах нет поддержки ipset. В общем случае сложность задачи по поднятию ipset варьируется от -"не просто" до "почти невозможно". Если только вы не найдете готовое собранное ядро под ваш девайс. - -tpws будет работать в любом случае, он не требует чего-либо особенного. -В android нет /etc/passwd, потому опция --user не будет работать. Вместо нее можно -пользоваться числовыми user id и опцией --uid. -Рекомендую использовать gid 3003 (AID_INET). Иначе можете получить permission denied на создание сокета. -Например : --uid 1:3003 -В iptables укажите : "! --uid-owner 1" вместо "! --uid-owner tpws". -Напишите шелл скрипт с iptables и tpws, запускайте его средствами вашего рут менеджера. -Скрипты автозапуска лежат тут : -magisk : /data/adb/service.d -supersu : /system/su.d - -nfqws может иметь такой глюк. При запуске с uid по умолчанию (0x7FFFFFFF) при условии работы на сотовом интерфейсе -и отключенном кабеле внешнего питания система может частично виснуть. Перестает работать тач и кнопки, -но анимация на экране может продолжаться. Если экран был погашен, то включить его кнопкой power невозможно. -Это, видимо, связано с переводом в suspend процессов с определенным UID. UID соответствует приложению или -системному сервису. По UID android определяет политику power saving. -Так же возможно, что глюк связан с кривым драйвером сотового интерфейса от китайцев, поскольку при использовании -wifi такого не наблюдается. suspend обработчика nfqueue на обычном linux не вызывает подобных фатальных последствий. -Изменение UID на низкий (--uid 1 подойдет) позволяет решить эту проблему. -Глюк был замечен на android 8.1 на девайсе, основанном на платформе mediatek. - -Ответ на вопрос куда поместить tpws на android без рута, чтобы потом его запускать из приложений. -Файл заливаем через adb shell в /data/local/tmp/, лучше всего в субфолдер. -mkdir /data/local/tmp/zapret -adb push tpws /data/local/tmp/zapret -chmod 755 /data/local/tmp/zapret /data/local/tmp/zapret/tpws -chcon u:object_r:system_file:s0 /data/local/tmp/zapret/tpws - -Как найти стратегию обхода сотового оператора : проще всего раздать инет на комп с linux. -Можно записать live image linux на флэшку и загрузиться с нее или запустить виртуалку с linux -и пробросить в нее usb устройство от режима модема с телефона. -На компе с linux прогнать стандартную процедуру blockcheck. При переносе правил на телефон уменьшить TTL на 1, -если правила с TTL присутствуют в стратегии. -Можно развернуть rootfs какого-нибудь дистрибутива linux прямо на телефоне, имея рута. -Это лучше всего делать с компа через adb shell. -Если компа нет, то это единственный вариант, хотя и неудобный. -Подойдет что-то легковесное, например, alpine или даже openwrt. -Если это не эмулятор android, то универсальная архитектура - arm (любой вариант). -Если вы точно знаете, что ОС у вас 64-разрядная, то лучше вместо arm - aarch64. - -mount --bind /dev /data/linux/dev -mount --bind /proc /data/linux/proc -mount --bind /sys /data/linux/sys -chroot /data/linux - -Первым делом вам нужно будет один раз настроить DNS. Сам он не заведется. - -echo nameserver 1.1.1.1 >/etc/resolv.conf - -Далее нужно средствами пакетного менеджера установить iptables-legacy. Обязательно НЕ iptables-nft, -который как правило присутствует по умолчанию. В ядре android нет nftables. -ls -la $(which iptables) -Линк должен указывать на legacy вариант. -Если нет, значит устанавливайте нужные пакеты вашего дистрибутива, и убеждайтесь в правильности ссылок. -iptables -S -Так можно проверить, что ваш iptables увидел то, что туда насовал android. iptables-nft выдаст ошибку. -Далее качаем zapret в /opt/zapret. Обычные действия с install_prereq.sh, install_bin.sh, blockcheck.sh. - -Учтите, что стратегии обхода сотового оператора и домашнего wifi вероятно будут разные. -Выделить сотового оператора легко через параметр iptables -o <имя интерфейса>. Имя может быть, например, ccmni0. -Его легко увидеть через ifconfig. -Wifi сеть - обычно wlan0. - -Переключать blockcheck между оператором и wifi можно вместе со всем инетом - включив или выключив wifi. -Если найдете стратегию для wifi и впишите ее в автостарт, то при подключении к другому wifi -она может не сработать или вовсе что-то поломать, потому подумайте стоит ли. -Может быть лучше сделать скрипты типа "запустить обход домашнего wifi", "снять обход домашнего wifi", -и пользоваться ими по необходимости из терминала. -Но домашний wifi лучше все-же обходить на роутере. - - -Мобильные модемы и роутеры huawei ---------------------------------- - -Устройства типа E3372, E8372, E5770 разделяют общую идеологию построения системы. -Имеются 2 вычислительных ядра. Одно ядро выполняет vxworks, другое - linux. -На 4pda имеются модифицированные прошивки с telnet и adb. Их и нужно использовать. - -Дальнейшие утверждения проверены на E8372. На других может быть аналогично или похоже. -Присутствуют дополнительные аппаратные блоки для offload-а сетевых функций. -Не весь трафик идет через linux. Исходящий трафик с самого модема проходит -цепочку OUTPUT нормально, на FORWARD =>wan часть пакетов выпадает из tcpdump. - -tpws работает обычным образом. - -nfqueue поломан. можно собрать фиксящий модуль https://github.com/im-0/unfuck-nfqueue-on-e3372h, -используя исходники с huawei open source. Исходники содержат тулчейн и полусобирающееся, -неактуальное ядро. Конфиг можно взять с рабочего модема из /proc/config.gz. -С помощью этих исходников умельцы могут собрать модуль unfuck_nfqueue.ko. -После его применения NFQUEUE и nfqws для arm работают нормально. - -Чтобы избежать проблемы с offload-ом при использовании nfqws, следует комбинировать tpws в режиме tcp proxy и nfqws. -Правила NFQUEUE пишутся для цепочки OUTPUT. -connbytes придется опускать, поскольку модуля в ядре нет. Но это не смертельно. - -Скрипт автозапуска - /system/etc/autorun.sh. Создайте свой скрипт настройки zapret, -запускайте из конца autorun.sh через "&". Скрипт должен в начале делать sleep 5, чтобы дождаться -поднятия сети и iptables от huawei. - -ПРЕДУПРЕЖДЕНИЕ. -На этом модеме происходят хаотические сбросы соединений tcp по непонятным причинам. -Выглядит это так, если запускать curl с самого модема : - curl www.ru - curl: (7) Failed to connect to www.ru port 80: Host is unreachable -Возникает ошибка сокета EHOSTUNREACH (errno -113). То же самое видно в tpws. -В броузере не подгружаются части веб страниц, картинки, стили. -В tcpdump на внешнем интерфейсе eth_x виден только единственный и безответный SYN пакет, без сообщений ICMP. -ОС каким-то образом узнает о невозможности установить TCP соединение и выдает ошибку. -Если выполнять подключение с клиента, то SYN пропадают, соединение не устанавливается. -ОС клиента проводит ретрансмиссию, и с какого-то раза подключение удается. -Поэтому без tcp проксирования в этой ситуации сайты тупят, но загружаются, а с проксированием -подключение выполняется, но вскоре сбрасывается без каких-либо данных, и броузеры не пытаются установить -его заново. Поэтому качество броузинга с tpws может быть хуже, но дело не в tpws. -Частота сбросов заметно возрастает, если запущен торент клиент, имеется много tcp соединений. -Однако, причина не в переполнении таблицы conntrack. Увеличение лимитов и очистка conntrack не помогают. -Предположительно эта особенность связана с обработкой пакетов сброса соединения в hardware offload. -Точного ответа на вопрос у меня нет. Если вы знаете - поделитесь, пожалуйста. -Чтобы не ухудшать качество броузинга, можно фильтровать заворот на tpws по ip фильтру. -Поддержка ipset отсутствует. Значит, все, что можно сделать - создать индивидуальные правила -на небольшое количество хостов. - -Некоторые наброски скриптов присутствуют в files/huawei. Не готовое решение ! Смотрите, изучайте, приспосабливайте. -Здесь можно скачать готовые полезные статические бинарники для arm, включая curl : https://github.com/bol-van/bins - - -FreeBSD, OpenBSD, MacOS ------------------------ - -Описано в docs/bsd.txt - - -Windows -------- - -Описано в docs/windows.txt - - -Другие прошивки ---------------- - -Для статических бинариков не имеет значения на чем они запущены : PC, android, приставка, роутер, любой другой девайс. -Подойдет любая прошивка, дистрибутив linux. Статические бинарники запустятся на всем. -Им нужно только ядро с необходимыми опциями сборки или модулями. -Но кроме бинариков в проекте используются еще и скрипты, в которых задействуются некоторые -стандартные программы. - -Основные причины почему нельзя просто так взять и установить эту систему на что угодно : - * отсутствие доступа к девайсу через shell - * отсутствие рута - * отсутствие раздела r/w для записи и энергонезависимого хранения файлов - * отсутствие возможности поставить что-то в автозапуск - * отсутствие cron - * неотключаемый flow offload или другая проприетарщина в netfilter - * недостаток модулей ядра или опций его сборки - * недостаток модулей iptables (/usr/lib/iptables/lib*.so) - * недостаток стандартных программ (типа ipset, curl) или их кастрированность (облегченная замена) - * кастрированный или нестандартный шелл sh - -Если в вашей прошивке есть все необходимое, то вы можете адаптировать zapret под ваш девайс в той или иной степени. -Может быть у вас не получится поднять все части системы, однако вы можете хотя бы попытаться -поднять tpws и завернуть на него через -j REDIRECT весь трафик на порт 80. -Если вам есть куда записать tpws, есть возможность выполнять команды при старте, то как минимум -это вы сделать сможете. Скорее всего поддержка REDIRECT в ядре есть. Она точно есть на любом роутере, -на других устройствах под вопросом. NFQUEUE, ipset на большинстве прошивок отсутствуют из-за ненужности. - -Пересобрать ядро или модули для него будет скорее всего достаточно трудно. -Для этого вам необходимо будет по крайней мере получить исходники вашей прошивки. -User mode компоненты могут быть привнесены относительно безболезненно, если есть место куда их записать. -Специально для девайсов, имеющих область r/w, существует проект entware. -Некоторые прошивки даже имеют возможность его облегченной установки через веб интерфейс. -entware содержит репозиторий user-mode компонент, которые устанавливаются в /opt. -С их помощью можно компенсировать недостаток ПО основной прошивки, за исключением ядра. - -Можно попытаться использовать sysv init script таким образом, как это описано в разделе -"Прикручивание к системе управления фаерволом или своей системе запуска". -В случае ругани на отсутствие каких-то базовых программ, их следует восполнить посредством entware. -Перед запуском скрипта путь к дополнительным программам должен быть помещен в PATH. - -Подробное описание настроек для других прошивок выходит за рамки данного проекта. - -Openwrt является одной из немногих относительно полноценных linux систем для embedded devices. -Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивки : - * полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть - * корень r/w. это практически уникальная особенность openwrt. заводские и большинство альтернативных прошивок - построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области - встроенной памяти, называемой nvram. не имеющие r/w корня системы сильно кастрированы. они не имеют - возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном - на чуть более продвинутого, чем обычно, пользователя и управление имеющимся функционалом через веб интерфейс, - но функционал фиксированно ограничен. альтернативные прошивки как правило могут монтировать r/w раздел - в какую-то область файловой системы, заводские обычно могут монтировать лишь флэшки, подключенные к USB, - и не факт, что есть поддержка unix файловых системы. может быть поддержка только fat и ntfs. - * возможность выноса корневой файловой системы на внешний носитель (extroot) или создания на нем оверлея (overlay) - * наличие менеджера пакетов opkg и репозитория софта - * flow offload предсказуемо, стандартно и выборочно управляем, а так же отключаем - * в репозитории есть все модули ядра, их можно доустановить через opkg. ядро пересобирать не нужно. - * в репозитории есть все модули iptables, их можно доустановить через opkg - * в репозитории есть огромное количество стандартных программ и дополнительного софта - * наличие SDK, позволяющего собрать недостающее - - -Обход блокировки через сторонний хост -------------------------------------- - -Если не работает автономный обход, приходится перенаправлять трафик через сторонний хост. -Предлагается использовать прозрачный редирект через socks5 посредством iptables+redsocks, либо iptables+iproute+vpn. -Настройка варианта с redsocks на openwrt описана в redsocks.txt. -Настройка варианта с iproute+wireguard - в wireguard_iproute_openwrt.txt. - - -Почему стоит вложиться в покупку VPS ------------------------------------- - -VPS - это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу. -На VPS могут выполняться какие угодно задачи. От простого веб сайта до навороченной системы собственной разработки. -Можно использовать VPS и для поднятия собственного vpn или прокси. -Сама широта возможных способов применения, распространенность услуги сводят к минимуму возможности -регуляторов по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая -реальность, в которой придется изобретать иные решения. -Пока этого не сделали, никто не будет банить хостинги просто потому, что они предоставляют хостинг услуги. -Вы как индивидуум скорее всего никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера. -VPN провайдер предоставляет _простую_ и _доступную_ услугу по обходу блокировок для масс. -Этот факт делает его первоочередной целью блокировки. РКН направит уведомление, после отказа сотрудничать -заблокирует VPN. Предоплаченная сумма пропадет. -У регуляторов нет и никогда не будет ресурсов для тотальной проверки каждого сервера в сети. -Возможен китайский расклад, при котором DPI выявляет vpn протоколы и динамически банит IP серверов, -предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать -vpn трафик или применить другие типы VPN, более устойчивые к анализу на DPI или просто менее широкоизвестные, -а следовательно с меньшей вероятностью обнаруживаемые регулятором. -У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям. -Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить -не могут, или покориться системе. - -VPS можно прибрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы. -Например, вот этот : https://vps.today/ -Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или -с большим лимитом по трафику (терабайты). Важен и тип VPS. Openvz подойдет для openvpn, но -вы не поднимете на нем wireguard, ipsec, то есть все, что требует kernel mode. -Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС linux -вместе с ядром. Подойдут kvm, xen, hyper-v, vmware. - -По цене можно найти предложения, которые будут дешевле готовой VPN услуги, но при этом вы сам хозяин в своей лавке -и не рискуете попасть под бан регулятора, разве что "заодно" под ковровую бомбардировку с баном миллионов IP. -Кроме того, если вам совсем все кажется сложным, прочитанное вызывает ступор, и вы точно знаете, что ничего -из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов ssh -для получения шифрованного socks proxy и прописать его в броузер. Знания linux не нужны совсем. -Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании. diff --git a/docs/redsocks.md b/docs/redsocks.md new file mode 100644 index 0000000..7f68b59 --- /dev/null +++ b/docs/redsocks.md @@ -0,0 +1,228 @@ +- [Введение](#введение) +- [Прозрачный выборочный заворот TCP соединений на роутере через SOCKS](#прозрачный-выборочный-заворот-tcp-соединений-на-роутере-через-socks) + - [Сделать так, чтобы все время при загрузке системы на некотором порту возникал SOCKS](#сделать-так-чтобы-все-время-при-загрузке-системы-на-некотором-порту-возникал-socks) + - [Организовать прозрачную соксификацию](#организовать-прозрачную-соксификацию) + - [Завертывание соединений через `iptables`](#завертывание-соединений-через-iptables) + - [Завертывание соединений через `nftables`](#завертывание-соединений-через-nftables) + - [Проверка](#проверка) + +# Введение + +Данный мануал пишется не как копипастная инструкция, а как помощь уже соображающему. +Если вы не знаете основ сетей, Linux, OpenWrt, а пытаетесь что-то скопипастить отсюда без малейшего понимания смысла, то маловероятно, что у вас что-то заработает. Не тратьте свое время напрасно. +Цель - донести принципы как это настраивается вообще, а не указать какую буковку где вписать. + +# Прозрачный выборочный заворот TCP соединений на роутере через SOCKS + +Tor поддерживает "из коробки" режим transparent proxy. Это можно использовать в теории, но практически - только на роутерах с 128 мб памяти и выше. И тор еще и тормозной. +Другой вариант напрашивается, если у вас есть доступ к какой-нибудь unix системе с SSH, где сайты не блокируются. +Например, у вас есть VPS вне России. Понятийно требуются следующие шаги: + +1) Выделять IP, на которые надо проксировать трафик. У нас уже имеется ipset `zapret`, технология создания которого отработана. +2) Сделать так, чтобы все время при загрузке системы на некотором порту возникал SOCKS. +3) Установить transparent соксификатор. Redsocks прекрасно подошел на эту роль. +4) Завернуть через `iptables` или `nftables` трафик с порта назначения 443 и на IP адреса из `ipset`/`nfset` `zapret` на соксификатор. + +Тоже самое сделать с `ipset`/`nfset` `ipban` для всех TCP портов. +Буду рассматривать систему на базе OpenWrt, где уже установлена система обхода DPI `zapret`. +Если вам не нужны функции обхода DPI, можно выбрать режим `MODE=filter`. + +## Сделать так, чтобы все время при загрузке системы на некотором порту возникал 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`, потом: + +```sh +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 серверу: + +```sh +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`: + +```sh +# !/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.127; + local_port = 1099; + ip = 127.0.0.1; + port = 1098; + type = socks5; +} +``` + +После чего перезапускаем: `/etc/init.d/redsocks restart`. +Смотрим появился ли листенер: `netstat -tnlp | grep 1099`. + +В `zapret` для перенаправления DNAT на интерфейс lo используется 127.0.0.127. +Ко всем остальным адресам из 127.0.0.0/8 DNAT может быть заблокирован. Читайте `readme.md` про `route_localnet`. + +## Завертывание соединений через `iptables` + +**ВНИМАНИЕ:** Версии OpenWrt до 21.02 включительно используют `iptables` + `fw3`. +Более новые перешили на `nftables` по умолчанию. +В новых OpenWrt можно снести `firewall4` и `nftables`, заменив их на `firewall3` + `iptables`. +Инструкция относится только к OpenWrt, где используется `iptables`. + +Будем завертывать любые TCP соединения на IP из ipset `ipban` и HTTPS на IP из ipset `zapret`, за исключением IP из ipset `nozapret`. + +`/etc/firewall.user`: + +```sh +SOXIFIER_PORT=1099 + +. /opt/zapret/init.d/openwrt/functions + +create_ipset no-update + +network_find_wan4_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 -m set ! --match-set nozapret dst -j REDIRECT --to-port $SOXIFIER_PORT + ipt OUTPUT -t nat -o $ext_device -p tcp -m set --match-set ipban dst -m set ! --match-set nozapret dst -j REDIRECT --to-port $SOXIFIER_PORT +done + +prepare_route_localnet + +ipt prerouting_lan_rule -t nat -p tcp --dport 443 -m set --match-set zapret dst -m set ! --match-set nozapret -j DNAT --to $TPWS_LOCALHOST4:$SOXIFIER_PORT +ipt prerouting_lan_rule -t nat -p tcp -m set --match-set ipban dst -m set ! --match-set nozapret -j DNAT --to $TPWS_LOCALHOST4:$SOXIFIER_PORT +``` + +Внести параметр "reload" в указанное место. `/etc/config/firewall`: + +``` +config include + option path '/etc/firewall.user' + option reload '1' +``` + +Перезапуск firewall: `/etc/init.d/firewall restart` + +## Завертывание соединений через `nftables` + +**ВНИМАНИЕ:** Только для версий OpenWrt старше 21.02. + +`nftables` не могут использовать ipset. Вместо `ipset` существует аналог - `nfset`. +`nfset` является частью таблицы nftable и принадлежит только к ней. Адресация `nfset` из другой nftable невозможна. +Скрипты `ipset/*` в случае `nftables` используют `nfset`-ы в таблице `zapret`. +Чтобы использовать эти `nfset`-ы в своих правилах, необходимо синхронизироваться с их созданием и вносить свои цепочки в nftable `zapret`. +Для этого существуют хуки - скрипты, вызываемые из `zapret` на определенных стадиях инициализации фаервола. + +Раскомментируйте в `/opt/zapret/config` строчку: + +```sh +INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" +``` + +Создайте файл `/etc/firewall.zapret.hook.post_up` и присвойте ему `chmod 755`: + +```sh +#!/bin/sh + +SOXIFIER_PORT=1099 + +. /opt/zapret/init.d/openwrt/functions + +cat << EOF | nft -f - 2>/dev/null + delete chain inet $ZAPRET_NFT_TABLE my_output + delete chain inet $ZAPRET_NFT_TABLE my_prerouting +EOF + +prepare_route_localnet + +cat << EOF | nft -f - + add chain inet $ZAPRET_NFT_TABLE my_output { type nat hook output priority -102; } + flush chain inet $ZAPRET_NFT_TABLE my_output + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif meta l4proto tcp ip daddr @ipban ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT + +add chain inet $ZAPRET_NFT_TABLE my_prerouting { type nat hook prerouting priority -102; } + flush chain inet $ZAPRET_NFT_TABLE my_prerouting + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif meta l4proto tcp ip daddr @ipban ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT +EOF +``` + +Перезапуск firewall: `/etc/init.d/zapret restart_fw` + +## Проверка + +Все, теперь можно проверять: + +```sh +/etc/init.d/redsocks stop +curl -4 https://rutracker.org +``` + +Должно обломаться с надписью "Connection refused". +Если не обламывается - значит IP адрес rutracker.org не в ipset, либо не сработали правила фаервола. +Например, из-за не установленных модулей `iptables`. + +```sh +/etc/init.d/redsocks start +curl -4 https://rutracker.org +``` + +Должно выдать страницу. diff --git a/docs/redsocks.txt b/docs/redsocks.txt deleted file mode 100644 index c3bc990..0000000 --- a/docs/redsocks.txt +++ /dev/null @@ -1,196 +0,0 @@ -Данный мануал пишется не как копипастная инструкция, а как помощь уже соображающему. -Если вы не знаете основ сетей, linux, openwrt, а пытаетесь что-то скопипастить отсюда без малейшего -понимания смысла, то маловероятно, что у вас что-то заработает. Не тратье свое время напрасно. -Цель - донести принципы как это настраивается вообще, а не указать какую буковку где вписать. - - -Прозрачный выборочный заворот tcp соединений на роутере через socks - -Tor поддерживает "из коробки" режим transparent proxy. Это можно использовать в теории, но практически - только на роутерах с 128 мб памяти и выше. И тор еще и тормозной. -Другой вариант напрашивается, если у вас есть доступ к какой-нибудь unix системе с SSH, где сайты не блокируются. Например, у вас есть VPS вне России. -Понятийно требуются следующие шаги : -1) Выделять IP, на которые надо проксировать трафик. У нас уже имеется ipset "zapret", технология создания которого отработана. -2) Сделать так, чтобы все время при загрузке системы на некотором порту возникал socks. -3) Установить transparent соксификатор. Redsocks прекрасно подошел на эту роль. -4) Завернуть через iptables или nftables трафик с порта назначения 443 и на ip адреса из ipset/nfset 'zapret' на соксификатор -Тоже самое сделать с ipset/nfset 'ipban' для всех tcp портов. -Буду рассматривать систему на базе openwrt, где уже установлена система обхода dpi "zapret". -Если вам не нужны функции обхода DPI, можно выбрать режим MODE=filter. - - -* Сделать так, чтобы все время при загрузке системы на некотором порту возникал 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.127; - local_port = 1099; - ip = 127.0.0.1; - port = 1098; - type = socks5; -} ---------------------------- - -После чего перезапускаем : /etc/init.d/redsocks restart -Смотрим появился ли листенер : netstat -tnlp | grep 1099 - -В zapret для перенаправления DNAT на интерфейс lo используется 127.0.0.127. -Ко всем остальным адресам из 127.0.0.0/8 DNAT может быть заблокирован. Читайте readme.txt про route_localnet. - -* Завертывание соединений через iptables - -!! Версии OpenWRT до 21.02 включительно используют iptables + fw3. Более новые перешили на nftables по умолчанию. -!! В новых OpenWRT можно снести firewall4 и nftables, заменив их на firewall3 + iptables -!! Инструкция относится только к openwrt, где используется iptables. - -Будем завертывать любые tcp соединения на ip из ipset "ipban" и https на ip из ipset "zapret", за исключением ip из ipset "nozapret". - ---- /etc/firewall.user ----- -SOXIFIER_PORT=1099 - -. /opt/zapret/init.d/openwrt/functions - -create_ipset no-update - -network_find_wan4_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 -m set ! --match-set nozapret dst -j REDIRECT --to-port $SOXIFIER_PORT - ipt OUTPUT -t nat -o $ext_device -p tcp -m set --match-set ipban dst -m set ! --match-set nozapret dst -j REDIRECT --to-port $SOXIFIER_PORT -done - -prepare_route_localnet - -ipt prerouting_lan_rule -t nat -p tcp --dport 443 -m set --match-set zapret dst -m set ! --match-set nozapret -j DNAT --to $TPWS_LOCALHOST4:$SOXIFIER_PORT -ipt prerouting_lan_rule -t nat -p tcp -m set --match-set ipban dst -m set ! --match-set nozapret -j DNAT --to $TPWS_LOCALHOST4:$SOXIFIER_PORT ----------------------------- - -Внести параметр "reload" в указанное место : ---- /etc/config/firewall --- -config include - option path '/etc/firewall.user' - option reload '1' ----------------------------- - -Перезапуск firewall : /etc/init.d/firewall restart - - -* Завертывание соединений через nftables - -!! Только для версий OpenWRT старше 21.02 - -nftables не могут использовать ipset. Вместо ipset существует аналог - nfset. -nfset является частью таблицы nftable и принадлежит только к ней. Адресация nfset из другой nftable невозможна. -Скрипты ipset/* в случае nftables используют nfset-ы в таблице zapret. -Чтобы использовать эти nfset-ы в своих правилах, необходимо синхронизироваться с их созданием и вносить свои цепочки в nftable "zapret". -Для этого существуют хуки - скрипты, вызываемые из zapret на определенных стадиях инициализации фаервола. - -Раскоментируейте в /opt/zapret/config строчку -INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" - -Создайте файл /etc/firewall.zapret.hook.post_up и присвойте ему chmod 755. - ---- /etc/firewall.zapret.hook.post_up --- -#!/bin/sh - -SOXIFIER_PORT=1099 - -. /opt/zapret/init.d/openwrt/functions - -cat << EOF | nft -f - 2>/dev/null - delete chain inet $ZAPRET_NFT_TABLE my_output - delete chain inet $ZAPRET_NFT_TABLE my_prerouting -EOF - -prepare_route_localnet - -cat << EOF | nft -f - - add chain inet $ZAPRET_NFT_TABLE my_output { type nat hook output priority -102; } - flush chain inet $ZAPRET_NFT_TABLE my_output - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif meta l4proto tcp ip daddr @ipban ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT - - add chain inet $ZAPRET_NFT_TABLE my_prerouting { type nat hook prerouting priority -102; } - flush chain inet $ZAPRET_NFT_TABLE my_prerouting - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif meta l4proto tcp ip daddr @ipban ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret dnat to $TPWS_LOCALHOST4:$SOXIFIER_PORT -EOF ----------------------------- - -Перезапуск firewall : /etc/init.d/zapret restart_fw - - -* Проверка - -Все, теперь можно проверять : -/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 -# должно выдать страницу diff --git a/docs/windows.eng.md b/docs/windows.eng.md index e624bec..fd9d22f 100644 --- a/docs/windows.eng.md +++ b/docs/windows.eng.md @@ -1,16 +1,22 @@ -### tpws +- [`tpws`](#tpws) +- [`winws`](#winws) +- [Windows 7 windivert signing](#windows-7-windivert-signing) +- [`blockcheck`](#blockcheck) +- [Autostart](#autostart) +- [`zapret-win-bundle`](#zapret-win-bundle) -Using `WSL` (Windows subsystem for Linux) it's possible to run `tpws` in socks mode under rather new builds of -windows 10 and windows server. -Its not required to install any linux distributions as suggested in most articles. -tpws is static binary. It doesn't need a distribution. +## `tpws` + +Using `WSL` (Windows subsystem for Linux) it's possible to run `tpws` in SOCKS mode under rather new builds of Windows 10 and Windows server. +It's not required to install any Linux distributions as suggested in most articles. +`tpws` is static binary. It doesn't need a distribution. Install `WSL` : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all` Copy `binaries/x86_64/tpws_wsl.tgz` to the target system. Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz` -Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 ` +Run `tpws`: `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 ` Configure socks as `127.0.0.1:1080` in a browser or another program. @@ -18,40 +24,41 @@ Cleanup : `wsl --unregister tpws` Tested in windows 10 build 19041 (20.04). -`--oob` , `--mss` and `--disorder` do not work. +`--oob`, `--mss` and `--disorder` do not work. RST detection in autohostlist scheme may not work. WSL may glitch with splice. `--nosplice` may be required. +## `winws` -### winws - -`winws` is `nfqws` version for windows. It's based on `windivert`. Most functions are working. -Large ip filters (ipsets) are not possible. Forwarded traffic and connection sharing are not supported. +`winws` is `nfqws` version for Windows. It's based on `windivert`. Most functions are working. +Large IP filters (IP sets) are not possible. Forwarded traffic and connection sharing are not supported. Administrator rights are required. -Working with packet filter consists of two parts +Working with packet filter consists of two parts: 1. In-kernel packet selection and passing selected packets to a packet filter in user mode. In *nix it's done by `iptables`, `nftables`, `pf`, `ipfw`. 2. User mode packet filter processes packets and does DPI bypass magic. Windows does not have part 1. No `iptables` exist. That's why 3rd party packet redirector is used. -It's called `windivert`. It works starting from `windows 7`. Kernel driver is signed but it may require to disable secure boot -or update windows 7. Read below for windows 7 windivert signing info. +It's called `windivert`. It works starting from `Windows 7`. +Kernel driver is signed but it may require to disable secure boot or update Windows 7. +Read below for Windows 7 windivert signing info. -Task of `iptables` is done inside `winws` through `windivert` filters. `Windivert` has it's own [filter language](https://reqrypt.org/windivert-doc.html#filter_language). +Task of `iptables` is done inside `winws` through `windivert` filters. +`Windivert` has it's own [filter language](https://reqrypt.org/windivert-doc.html#filter_language). `winws` can automate filter construction using simple ip version and port filter. Raw filters are also supported. ``` - --wf-iface=[:] ; numeric network interface and subinterface indexes - --wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. - --wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed. - --wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed. - --wf-raw=|@ ; raw windivert filter string or filename - --wf-save= ; save windivert filter string to a file and exit - --ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected - --nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted. - --nlm-list[=all] ; list Network List Manager (NLM) networks. connected only or all. +--wf-iface=[:] ; numeric network interface and subinterface indexes +--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed. +--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed. +--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed. +--wf-raw=|@ ; raw windivert filter string or filename +--wf-save= ; save windivert filter string to a file and exit +--ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified Wi-Fi SSIDs connected +--nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted. +--nlm-list[=all] ; list Network List Manager (NLM) networks. connected only or all. ``` `--wf-l3`, `--wf-tcp`, `--wf-udp` can take multiple comma separated arguments. @@ -66,8 +73,10 @@ Multiple `winws` processes are allowed. However, it's discouraged to intersect t SSID names must be written in the same case as the system sees them. This option does not analyze routing and does not detect where traffic actually goes. If multiple connections are available, the only thing that triggers `winws` operation is wifi connection presence. That's why it's a good idea to add also `--wf-iface` filter to not break ethernet, for example. -`--nlm-filter` is like `--ssid-filter` but works with names or GUIDs from Network List Manager. NLM names are those you see in Control Panel "Network and Sharing Center". -NLM networks are adapter independent. Usually MAC address of the default router is used to distinugish networks. NLM works with any type of adapters : ethernet, wifi, vpn and others. +`--nlm-filter` is like `--ssid-filter` but works with names or GUIDs from Network List Manager. +NLM names are those you see in Control Panel "Network and Sharing Center". +NLM networks are adapter independent. Usually MAC address of the default router is used to distinguish networks. +NLM works with any type of adapters: Ethernet, Wi-Fi, VPN and others. That's why NLM is more universal than `ssid-filter`. `Cygwin` shell does not run binaries if their directory has it's own copy of `cygwin1.dll`. @@ -79,35 +88,36 @@ How to get `windows 7` and `winws` compatible `cygwin` : curl -O https://www.cygwin.com/setup-x86_64.exe setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 ``` -You must choose to install `curl`. To compile from sources install `gcc-core`,`make`,`zlib-devel`. + +You must choose to install `curl`. To compile from sources install `gcc-core`, `make`, `zlib-devel`. `winws` requires `cygwin1.dll`, `windivert.dll`, `windivert64.sys`. You can take them from `binaries/win64/zapret-winws`. It's possible to build x86 32-bit version but this version is not shipped. You have to build it yourself. -32-bit `windivert` can be downloaded from it's developer github. Required version is 2.2.2. +32-bit `windivert` can be downloaded from it's developer GitHub. Required version is 2.2.2. There's no `arm64` signed `windivert` driver and no `cygwin`. But it's possible to use unsigned driver version in test mode and user mode components with x64 emulation. x64 emulation requires `windows 11` and not supported in `windows 10`. -### windows 7 windivert signing +## Windows 7 windivert signing Requirements for windows driver signing have changed in 2021. Official free updates of windows 7 ended in 2020. After 2020 for the years paid updates were available (ESU). -One of the updates from ESU enables signatures used in windivert 2.2.2-A. -There are several options : +One of the updates from ESU enables signatures used in `windivert 2.2.2-A`. +There are several options: 1. Take `windivert64.sys` and `windivert.dll` version `2.2.0-C` or `2.2.0-D` from [here](https://reqrypt.org/download). Replace these 2 files in every location they are present. In `zapret-win-bundle` they are in `zapret-winws` и `blockcheck/zapret/nfq` folders. -However this option still requires 10+ year old patch that enables SHA256 signatures. +However, this option still requires 10+ year old patch that enables SHA256 signatures. 2. [Hack ESU](https://hackandpwn.com/windows-7-esu-patching) -3. Use `UpdatePack7R2` from simplix : https://blog.simplix.info +3. Use `UpdatePack7R2` from [simplix](https://blog.simplix.info). If you are in Russia or Belarus temporary change region in Control Panel. -### blockcheck +## `blockcheck` `blockcheck.sh` is written in posix shell and uses some standard posix utilites. Windows does not have them. To execute `blockcheck.sh` use `cygwin` command prompt run as administrator. @@ -122,23 +132,21 @@ cd "/cygdrive/c/Users/vasya" ``` `Cygwin` is required only for `blockcheck.sh`. Standalone `winws` can be run without it. - -### auto start +## Autostart To start `winws` with windows use windows task scheduler. There are `task_*.cmd` batch files in `binaries/win64/zapret-winws`. They create, remove, start and stop scheduled task `winws1`. They must be run as administrator. -Edit `task_create.cmd` and write your `winws` parameters to `%WINWS1%` variable. If you need multiple `winws` instances -clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,...`. +Edit `task_create.cmd` and write your `winws` parameters to `%WINWS1%` variable. +If you need multiple `winws` instances, clone the code in all `cmd` files to support multiple tasks `winws1, winws2, winws3,...`. Tasks can also be controlled from GUI `taskschd.msc`. -Also you can use windows services the same way with `service_*.cmd`. +Also you can use Windows services the same way with `service_*.cmd`. +## `zapret-win-bundle` -### zapret-win-bundle - -To make your life easier there's ready to use [bundle](https://github.com/bol-van/zapret-win-bundle) with `cygwin`,`blockcheck` and `winws`. +To make your life easier there's ready to use [bundle](https://github.com/bol-van/zapret-win-bundle) with `cygwin`, `blockcheck` and `winws`. * `/zapret-winws` - standalone version of `winws` for everyday use. does not require any other folders. * `/zapret-winws/_CMD_ADMIN.cmd` - open `cmd` as administrator in the current folder @@ -146,10 +154,10 @@ To make your life easier there's ready to use [bundle](https://github.com/bol-va * `/cygwin/cygwin.cmd` - run `cygwin` shell as current user * `/cygwin/cygwin-admin.cmd` - run `cygwin` shell as administrator -There're aliases in cygwin shell for `winws`,`blockcheck`,`ip2net`,`mdig`. No need to mess with paths. -It's possible to send signals to `winws` using standard unix utilites : `pidof,kill,killall,pgrep,pkill`. -`Cygwin` shares common process list per `cygwin1.dll` copy. If you run a `winws` from `zapret-winws` -you won't be able to `kill` it because this folder contain its own copy of `cygwin1.dll`. +There're aliases in `cygwin` shell for `winws`, `blockcheck`, `ip2net`, `mdig`. No need to mess with paths. +It's possible to send signals to `winws` using standard unix utilities: `pidof`, `kill`, `killall`, `pgrep`, `pkill`. +`Cygwin` shares common process list per `cygwin1.dll` copy. +If you run a `winws` from `zapret-winws`, you won't be able to `kill` it because this folder contain its own copy of `cygwin1.dll`. It's possible to use `cygwin` shell to make `winws` debug log. Use `tee` command like this : diff --git a/docs/windows.md b/docs/windows.md new file mode 100644 index 0000000..149101a --- /dev/null +++ b/docs/windows.md @@ -0,0 +1,229 @@ +- [`tpws`](#tpws) +- [`winws`](#winws) +- [Windows 7 и `windivert`](#windows-7-и-windivert) +- [`blockcheck`](#blockcheck) +- [Автозапуск `winws`](#автозапуск-winws) +- [`zapret-win-bundle`](#zapret-win-bundle) + +## `tpws` + +Запуск `tpws` возможен только в Linux варианте под WSL. +Нативного варианта под Windows нет, поскольку он использует epoll, которого под Windows не существует. + +`tpws` в режиме SOCKS можно запускать под более-менее современными билдами Windows 10 и Windows Server +с установленным WSL. Совсем не обязательно устанавливать дистрибутив Ubuntu, как вам напишут почти в каждой +статье про WSL, которую вы найдете в сети. `tpws` - статический бинарник, ему дистрибутив не нужен. + +Установить WSL: `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all` + +Скопировать на целевую систему: `binaries/x86_64/tpws_wsl.tgz`. + +Выполнить: `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz` + +Запустить: `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <параметры_дурения>` + +Прописать SOCKS `127.0.0.1:1080` в броузер или другую программу. + +Удаление: `wsl --unregister tpws` + +Проверено на Windows 10 build 19041 (20.04). + +Не работают функции `--oob` и `--mss` из-за ограничений реализации WSL. +`--disorder` не работает из-за особенностей TCP/IP стека Windows. +Может не срабатывать детект RST в `autohostlist`. +WSL может глючить со `splice`, приводя к зацикливанию процесса. Может потребоваться `--nosplice`. +Не поддерживается TCP user timeout. +Чтобы избавиться от сообщений об ошибке, добавляйте `--local-tcp-user-timeout=0 --remote-tcp-user-timeout=0`. +Эти сообщения только информативные, на работу они не влияют. + +## `winws` + +Это вариант пакетного фильтра `nfqws` для Windows, построенный на базе `windivert`. +Все функции работоспособны, однако функционал `ipset` отсутствует. Фильтры по большому количеству IP адресов невозможны. +Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется. +Для работы с `windivert` требуются права администратора. +Специфические для unix параметры, такие как `--uid`, `--user` и т.д., исключены. Все остальные параметры аналогичны `nfqws` и `dvtws`. + +Работа с пакетным фильтром основана на двух действиях. + +1) Выделение перенаправляемого трафика в режиме ядра и передача его пакетному фильтру в user mode. +2) Собственно обработка перенаправленных пакетов в пакетном фильтре. + +В Windows отсутствуют встроенные средства для перенаправления трафика, такие как `iptables`, `nftables`, `pf` или `ipfw`. +Поэтому используется сторонний драйвер ядра `windivert`. Он работает, начиная с Windows 7. На системах с включенным +Secure Boot могут быть проблемы из-за подписи драйвера. В этом случае отключите Secure Boot или включите режим testsigning. +На Windows 7 вероятно будут проблемы с загрузкой `windivert`. Читайте ниже соответствующий раздел. + +Задача `iptables` в `winws` решается внутренними средствами через фильтры `windivert`. +У `windivert` существует собственный язык фильтров, похожий на язык фильтров wireshark. +Документация по фильтрам `windivert` [здесь](https://reqrypt.org/windivert-doc.html#filter_language). +Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров. + +``` +--wf-iface=[.] ; числовые индексы интерфейса и суб-интерфейса +--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены IPv4 и IPv6. +--wf-tcp=[~]port1[-port2] ; фильтр портов для TCP. ~ означает отрицание +--wf-udp=[~]port1[-port2] ; фильтр портов для UDP. ~ означает отрицание +--wf-raw=|@ ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @. +--wf-save= ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную +--ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных Wi-Fi сетей +--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM +--nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех. +``` + +Параметры `--wf-l3`, `--wf-tcp`, `--wf-udp` могут брать несколько значений через запятую. + +Номера интерфейсов можно узнать так: `netsh int ip show int`. +Некоторых типы соединений там не увидеть. В этом случае запускайте `winws` с параметром `--debug` и смотрите `IfIdx` там. +`SubInterface` используется `windivert`, но практически всегда 0, его можно не указывать. Вероятно он нужен в редких случаях. + +Конструктор фильтров автоматически включает входящие TCP пакеты с TCP SYNACK и TCP RST для корректной работы функций +`autottl` и `autohostlist`. При включении `autohostlist` так же перенаправляются пакеты данных с HTTP redirect с кодами 302 и 307. +Всегда добавляется фильтр на исключение не-интернет адресов IPv4 и IPv6. +Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона, +сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - 8 Kb. + +Можно запускать несколько процессов `winws` с разными стратегиями. Однако, не следует делать пересекающиеся фильтры. + +В `--ssid-filter` можно через запятую задать неограниченное количество имен Wi-Fi сетей (SSID). Если задана хотя бы одна сеть, +то `winws` включается только, если подключен указанный SSID. Если SSID исчезает, `winws` отключается. Если SSID появляется снова, +`winws` включается. Это нужно, чтобы можно было применять раздельное дурение к каждой отдельной Wi-Fi сети. +Названия сетей должны быть написаны в том регистре, в котором их видит система. Сравнение идет с учетом регистра! +При этом нет никаких проверок того, куда реально идет трафик. Если одновременно подключен, допустим, Ethernet, +и трафик идет туда, то дурение включается и выключается просто по факту наличия Wi-Fi сети, на которую трафик может и не идти. +И это может сломать дурение на Ethernet. Поэтому полезно так же будет добавить фильтр `--wf-iface` на индекс интерфейса Wi-Fi адаптера, +чтобы не трогать другой трафик. + +`--nlm-filter` аналогичен `--ssid-filter`, но работает с именами или GUIDами сетей Network List Manager (NLM). +Это те сети, которые вы видите в панели управления в разделе "Центр управления сетями и общим доступом". +Под сетью подразумевается не конкретный адаптер, а именно сетевое окружение конкретного подключения. +Обычно проверяется MAC адрес шлюза. К сети можно подключиться через любой адаптер, и она останется той же самой. +Если подключиться, допустим, к разными роутерам по кабелю, то будут разные сети. +А если к одному роутеру через 2 разных сетевых карточки на том же компе - будет одна сеть. +NLM абстрагирует типы сетевых адаптеров. Он работает как с Wi-Fi, так и с Ethernet и любыми другими. +Поэтому это более универсальный метод, чем SSID фильтр. +Однако, есть и неприятная сторона. В Windows 7 вы легко могли ткнуть на иконку сети и выбрать тип: private или public. +Там же вы могли посмотреть список сетей и объединить их. Чтобы, допустим, вы могли подключаться по кабелю и Wi-Fi +к одному роутеру, и система эти подключения воспринимала как одну сеть. +В следующих версиях Windows они эти возможности сильно порезали. Похоже нет встроенных средств полноценно управлять +network locations в Windows 10/11. Кое-что есть в `powershell`. +Можно поковыряться напрямую в реестре здесь: `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList` +Нужно менять `ProfileGUID` в `Signatures\Unmanaged`. Имена можно поменять в Profiles. +Есть кое-какие сторонние утилиты. Кое-что находится, позволяющее посмотреть и удалить network profiles, но не объединить. +Факт, что в ms они это сильно испортили. Движок network list все тот же, и он способен на все то, что было в Windows 7. +Можно не бороться с этой проблемой, а просто указывать через запятую те названия сетей или GUIDы, которые выбрала система. +Или если у вас только Wi-Fi, то использовать `--ssid-filter`. Там хотя бы есть гарантия, что SSID соответствуют реальности, +а система их не назвала как-то по-своему. + +Если в путях присутствуют национальные символы, то при вызове `winws` из `cmd` или `bat` кодировку нужно использовать OEM. +Для русского языка это 866. Пути с пробелами нужно брать в кавычки. + +Существует неочевидный момент, касающийся запуска `winws` из `cygwin` шелла. Если в директории, где находится `nfqws`, находится +копия `cygwin1.dll`, `winws` не запустится. Поэтому в `binaries/win64` существует директория zapret-winws, содержащая полный +комплект для запуска без `cygwin`. Его вы и берете для повседневного использования. +Если нужен запуск под `cygwin`, то следует запускать из `binaries/win64`. Это нужно для работы `blockcheck`. +Из `cygwin` шелла можно посылать `winws` сигналы через `kill` точно так же, как в *nix. + +Как получить совместимый с Windows 7 и winws `cygwin`: + +```powershell +curl -O https://www.cygwin.com/setup-x86_64.exe +setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 +``` + +Следует выбрать установку `curl`. + +Для сборки из исходников требуется `gcc-core`, `make`, `zlib-devel`. +Собирать из директории `nfq` командой `make cygwin`. +`winws` требует `cygwin1.dll`, `windivert.dll`, `windivert64.sys`. Их можно взять из `binaries/win64/zapret-winws`. +Версию для 32-битных x86 Windows собрать можно, но такие системы уже уходят в прошлое, поэтому если надо - собирайте сами. +32-битный `windivert` можно взять с сайта разработчика. Требуется версия 2.2.2. + +Для ARM64 Windows нет подписанного драйвера `windivert` и нет `cygwin`. +Однако, эмуляция x64 Windows 11 позволяет использовать все, кроме `WinDivert64.sys` без изменений. +Но при этом надо заменить `WinDivert64.sys` на неподписанную ARM64 версию и установить режим testsigning. + +## Windows 7 и `windivert` + +Требования к подписи драйверов Windows изменились в 2021 году. +Официальные бесплатные обновления Windows 7 закончились в 2020. +После этого несколько лет продолжали идти платные обновления по программе ESU. +Именно в этих ESU обновлениях находится обновление ядра Windows 7, позволяющее загрузить драйвер +`windivert 2.2.2-A`, который идет в поставке zapret. +Поэтому варианты следующие: + +1) Взять `windivert64.sys` и `windivert.dll` версии 2.2.0-C или 2.2.0-D [отсюда](https://reqrypt.org/download) +и заменить эти 2 файла. +В `zapret-win-bundle` есть отдельных 2 места, где находится `winws`: `zapret-winws` и `blockcheck/zapret/nfq`. +Надо менять в обоих местах. +Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 +сигнатуры, все еще необходим. + +2) Взломать ESU: [раз](https://hackandpwn.com/windows-7-esu-patching/), [два](http://www.bifido.net/tweaks-and-scripts/8-extended-security-updates-installer.html), и обновить систему + +3) Использовать UpdatePack7R2 от [simplix](https://blog.simplix.info). +Но с этим паком есть проблема. Автор из Украины, он очень обиделся на русских. +Если в панели управления стоит регион RU или BY, появляется неприятный диалог. +Чтобы эту проблему обойти, можно поставить временно любой другой регион, потом вернуть. +Так же нет никаких гарантий, что автор не насовал туда какой-то зловредный код. +Использовать на свой страх и риск. +Более безопасный вариант - скачать последнюю нормальную довоенную версию: [22.2.10](https://nnmclub.to/forum/viewtopic.php?t=1530323). +Ее достаточно, чтобы windivert 2.2.2-A заработал на Windows 7. + +## `blockcheck` + +`blockcheck.sh` написан на posix shell и требует некоторых стандартных утилит posix. В Windows, естественно, этого нет. +Потому просто так запустить `blockcheck.sh` невозможно. +Для этого требуется скачать и установить `cygwin` так, как описано в предыдущем разделе. +Следует запустить от имени администратора cygwin shell через `cygwin.bat`. +В нем нужно пройти в директорию с `zapret`. +Обратные слэши путей Windows нужно удваивать, менять на прямые слэши, либо использовать отображение на unix path. + +- Корректный вариант 1: `cd "C:\\Users\\vasya"` +- Корректный вариант 2: `cd "C:/Users/vasya"` +- Корректный вариант 3: `cd "/cygdrive/c/Users/vasya"` + +Далее все как в *nix: 1 раз `./install_bin.sh`, затем `./blockcheck.sh`. +WSL использовать нельзя, это не то же самое. + +`cygwin` для обычной работы `winws` не нужен. Разве что вы хотите посылать `winws` SIGHUP для перечитки листов без перезапуска. + +## Автозапуск `winws` + +Для запуска `winws` вместе с Windows есть 2 варианта. Планировщик задач или службы Windows. + +Можно создавать задачи и управлять ими через консольную программу `schtasks`. +В директории `binaries/win64/winws` подготовлены файлы `task_*.cmd`. +В них реализовано создание, удаление, старт и стоп одной копии процесса `winws` с параметрами из переменной `%WINWS1%`. +Исправьте параметры на нужную вам стратегию. Если для разных фильтров применяется разная стратегия, размножьте код +для задач `winws1`, `winws2`, `winws3`,... + +Аналогично настраивается вариант запуска через службы Windows. Смотрите `service_*.cmd`. +Все батники требуется запускать от имени администратора. +Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`. + +## `zapret-win-bundle` + +Можно не возиться с `cygwin`, а взять [готовый пакет](https://github.com/bol-van/zapret-win-bundle), включающий в себя `cygwin` и `blockcheck`. +Там сделан максимум удобств для сосредоточения на самом `zapret`, исключая возню с установкой `cygwin`, +заходами в директории, запусками под администратором и прочими сугубо техническими моментами, в которых могут быть +ошибки и непонимания, а новичок без базиса знаний может и вовсе запутаться. + +- `/zapret-winws` - здесь все, что нужно для запуска `winws` в повседневном рабочем режиме. остальное не нужно. +- `/zapret-winws/_CMD_ADMIN.cmd` - получить командную строку `cmd` в этой директории от имени администратора для тестирования `winws` с параметрами, вводимыми вручную +- `/blockcheck/blockcheck.cmd` - достаточно кликнуть по нему, чтобы пошел `blockcheck` с записью лога в `blockcheck/blockcheck.log` +- `/cygwin/cygwin.cmd` - запуск среды `cygwin bash` под текущим пользователем +- `/cygwin/cygwin-admin.cmd` - запуск среды `cygwin bash` под администратором + +В среде `cygwin` уже настроены alias-ы на `winws`, `blockcheck`, `ip2net`, `mdig`. С путями возиться не нужно! +Из `cygwin` можно не только тестировать `winws`, но и посылать сигналы. +Доступны команды `pidof`, `kill`, `killall`, `pgrep`, `pkill`. +Но важно понимать, что таким образом не выйдет посылать сигналы `winws`, запущенному из `zapret-winws`, +поскольку там свой `cygwin1.dll`, и они не разделяют общее пространство процессов unix. +`zapret-winws` - это отдельный комплект для повседневного использования, не требующий что-то еще, но и не связанный со средой `cygwin`. + +Среду `cygwin` можно использовать для записи в файл дебаг-лога `winws`. Для этого пользуйтесь командой `tee`: +`winws --debug --wf-tcp=80,443 | tee winws.log` + +`winws.log` будет в `cygwin/home/<имя_пользователя>` +Если у вас Windows 7, то блокнот не поймет переводы строк в стиле unix. Воспользуйтесь командой: `unix2dos winws.log` diff --git a/docs/windows.txt b/docs/windows.txt deleted file mode 100644 index b71d7ff..0000000 --- a/docs/windows.txt +++ /dev/null @@ -1,222 +0,0 @@ -tpws ----- - -Запуск tpws возможен только в Linux варианте под WSL. -Нативного варианта под Windows нет, поскольку он использует epoll, которого под windows не существует. - -tpws в режиме socks можно запускать под более-менее современными билдами windows 10 и windows server -с установленным WSL. Совсем не обязательно устанавливать дистрибутив убунту, как вам напишут почти в каждой -статье про WSL, которую вы найдете в сети. tpws - статический бинарик, ему дистрибутив не нужен. - -Установить WSL : dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all -Скопировать на целевую систему binaries/x86_64/tpws_wsl.tgz. -Выполнить : wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz -Запустить : wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <параметры_дурения> -Прописать socks 127.0.0.1:1080 в броузер или другую программу. - -Удаление : wsl --unregister tpws - -Проверено на windows 10 build 19041 (20.04). - -Не работают функции --oob и --mss из-за ограничений реализации WSL. ---disorder не работает из-за особенностей tcp/ip стека windows. -Может не срабатывать детект RST в autohostlist. -WSL может глючить со splice, приводя к зацикливанию процесса. Может потребоваться --nosplice. -Не поддерживается tcp user timeout. -Чтобы избавиться от исообщений об ошибке добавляйте "--local-tcp-user-timeout=0 --remote-tcp-user-timeout=0". -Эти сообщения только информативные, на работу они не влияют. - - -winws ------ - -Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert. -Все функции работоспособны, однако функционал ipset отсутствует. Фильтры по большому количеству IP адресов невозможны. -Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется. -Для работы с windivert требуются права администратора. -Специфические для unix параметры, такие как --uid, --user и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws. - -Работа с пакетным фильтром основана на двух действиях. -Первое - выделение перенаправляемого трафика в режиме ядра и передача его пакетному фильтру в user mode. -Второе - собственно обработка перенаправленных пакетов в пакетном фильтре. - -В windows отсутствуют встроенные средства для перенаправления трафика, такие как iptables, nftables, pf или ipfw. -Поэтому используется сторонний драйвер ядра windivert. Он работает, начиная с windows 7. На системах с включенным -secure boot могут быть проблемы из-за подписи драйвера. В этом случае отключите secureboot или включите режим testsigning. -На windows 7 вероятно будут проблемы с загрузкой windivert. Читайте ниже соответствующий раздел. - -Задача iptables в winws решается внутренними средствами через фильтры windivert. -У windivert существует собственный язык фильтров, похожий на язык фильтров wireshark. -Документация по фильтрам windivert : https://reqrypt.org/windivert-doc.html#filter_language -Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров. - - --wf-iface=[.] ; числовые индексы интерфейса и суб-интерфейса - --wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6. - --wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание - --wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание - --wf-raw=|@ ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @. - --wf-save= ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную - --ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей - --nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM - --nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех. -Параметры --wf-l3, --wf-tcp, --wf-udp могут брать несколько значений через запятую. - -Номера интерфейсов можно узнать так : netsh int ip show int. -Некоторых типы соединений там не увидеть. В этом случае запускайте winws с параметром --debug и смотрите IfIdx там. -SubInterface используется windivert, но практически всегда 0, его можно не указывать. Вероятно он нужен в редких случаях. - -Конструктор фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций -autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307. -Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6. -Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона, -сохраненного через --wf-save. Нужно править файл и подсовывать его в параметре --wf-raw. Максимальный размер фильтра - 8 Kb. - -Можно запускать несколько процессов winws с разными стратегиями. Однако, не следует делать пересекающиеся фильтры. - -В --ssid-filter можно через запятую задать неограниченное количество имен wifi сетей (SSID). Если задана хотя бы одна сеть, -то winws включается только, если подключен указанный SSID. Если SSID исчезает, winws отключается. Если SSID появляется снова, -winws включается. Это нужно, чтобы можно было применять раздельное дурение к каждой отдельной wifi сети. -Названия сетей должны быть написаны в том регистре, в котором их видит система. Сравнение идет с учетом регистра ! -При этом нет никаких проверок куда реально идет трафик. Если одновременно подключен, допустим, ethernet, -и трафик идет туда, то дурение включается и выключается просто по факту наличия wifi сети, на которую трафик может и не идти. -И это может сломать дурение на ethernet. Поэтому полезно так же будет добавить фильтр --wf-iface на индекс интерфейса wifi адаптера, -чтобы не трогать другой трафик. - ---nlm-filter аналогичен --ssid-filter, но работает с именами или GUIDами сетей Network List Manager (NLM). -Это те сети, которые вы видите в панели управления в разделе "Центр управления сетями и общим доступом". -Под сетью подразумевается не конкретный адаптер, а именно сетевое окружение конкретного подключения. -Обычно проверяется mac адрес шлюза. К сети можно подключиться через любой адаптер, и она останется той же самой. -Если подключиться, допустим, к разными роутерам по кабелю, то будут разные сети. -А если к одному роутеру через 2 разных сетевых карточки на том же компе - будет одна сеть. -NLM абстрагирует типы сетевых адаптеров. Он работает как с wifi, так и с ethernet и любыми другими. -Поэтому это более универсальный метод, чем ssid фильтр. -Однако, есть и неприятная сторона. В windows 7 вы легко могли ткнуть на иконку сети и выбрать тип : private или public. -Там же вы могли посмотреть список сетей и обьединить их. Чтобы, допустим, вы могли подключаться по кабелю и wifi -к одному роутеру, и система эти подключения воспринимала как одну сеть. -В следующих версиях windows они эти возможности сильно порезали. Похоже нет встроенных средств полноценно управлять -network locations в win10/11. Кое-что есть в powershell. -Можно поковыряться напрямую в реестре здесь : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList -Нужно менять ProfileGUID в Signatures\Unmanaged. Имена можно поменять в Profiles. -Есть кое-какие сторонние утилиты. Кое-что находится, позволяющее посмотреть и удалить network profiles, но не обьединить. -Факт, что в ms они это сильно испортили. Движок network list все тот же, и он способен на все то, что было в win7. -Можно не бороться с этой проблемой, а просто указывать через запятую те названия сетей или GUIDы, которые выбрала система. -Или если у вас только wifi, то использовать --ssid-filter. Там хотя бы есть гарантия, что SSID соответствуют реальности, -а система их не назвала как-то по-своему. - -Если в путях присутствуют национальные символы, то при вызове winws из cmd или bat кодировку нужно использовать OEM. -Для русского языка это 866. Пути с пробелами нужно брать в кавычки. - -Существует неочевидный момент, каcаемый запуска winws из cygwin шелла. Если в директории, где находится nfqws, находится -копия cygwin1.dll, winws не запустится. Поэтому в binaries/win64 существует директория zapret-winws, содержащая полный -комплект для запуска без cygwin. Его вы и берете для повседневного использования. -Если нужен запуск под cygwin, то следует запускать из binaries/win64. Это нужно для работы blockcheck. -Из cygwin шелла можно посылать winws сигналы через kill точно так же, как в *nix. - -Как получить совместимый с windows 7 и winws cygwin : -curl -O https://www.cygwin.com/setup-x86_64.exe -setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 -Следует выбрать установку curl. - -Для сборки из исходников требуется gcc-core,make,zlib-devel. -Собирать из директории nfq командой "make cygwin". -winws требует cygwin1.dll, windivert.dll, windivert64.sys. Их можно взять из binaries/win64/zapret-winws. -Версию для 32-битных x86 windows собрать можно, но такие системы уже уходят в прошлое, поэтому если надо - собирайте сами. -32-битный windivert можно взять с сайта разработчика. Требуется версия 2.2.2. - -Для arm64 windows нет подписанного драйвера windivert и нет cygwin. -Однако, эмуляция x64 windows 11 позволяет использовать все, кроме WinDivert64.sys без изменений. -Но при этом надо заменить WinDivert64.sys на неподписанную arm64 версию и установить режим testsigning. - -Windows 7 и windivert ---------------------- - -Требования к подписи драйверов windows изменились в 2021 году. -Официальные бесплатные обновления windows 7 закончились в 2020. -После этого несколько лет продолжали идти платные обновления по программе ESU. -Именно в этих ESU обновлениях находится обновление ядра windows 7, позволяющиее загрузить драйвер -windivert 2.2.2-A, который идет в поставке zapret. -Поэтому варианты следующие : - -1) Взять windivert64.sys и windivert.dll версии 2.2.0-C или 2.2.0-D отсюда : https://reqrypt.org/download -и заменить эти 2 файла. -В zapret-win-bundle есть отдельных 2 места, где находится winws : zapret-winws и blockcheck/zapret/nfq. -Надо менять в обоих местах. -Этот вариант проверен и должен работать. Тем не менее патч 10 летней давности, который включает SHA256 -сигнатуры, все еще необходим. - -2) Взломать ESU : -https://hackandpwn.com/windows-7-esu-patching/ -http://www.bifido.net/tweaks-and-scripts/8-extended-security-updates-installer.html -и обновить систему - -3) Использовать UpdatePack7R2 от simplix : https://blog.simplix.info -Но с этим паком есть проблема. Автор из Украины, он очень обиделся на русских. -Если в панели управления стоит регион RU или BY, появляется неприятный диалог. -Чтобы эту проблему обойти, можно поставить временно любой другой регион, потом вернуть. -Так же нет никаких гарантий, что автор не насовал туда какой-то зловредный код. -Использовать на свой страх и риск. -Более безопасный вариант - скачать последнюю нормальную довоенную версию : 22.2.10 -https://nnmclub.to/forum/viewtopic.php?t=1530323 -Ее достаточно, чтобы windivert 2.2.2-A заработал на windows 7. - -blockcheck ----------- - -blockcheck.sh написан на posix shell и требует некоторых стандартных утилит posix. В windows, естественно, этого нет. -Потому просто так запустить blockcheck.sh невозможно. -Для этого требуется скачать и установить cygwin так , как описано в предыдущем разделе. -Следует запустить от имени администратора cygwin shell через cygwin.bat. -В нем нужно пройти в директорию с zapret. -Обратные слэши путей windows нужно удваивать, менять на прямые слэши, либо использовать отображение на unix path. -Корректный вариант 1 : cd "C:\\Users\\vasya" -Корректный вариант 2 : cd "C:/Users/vasya" -Корректный вариант 3 : cd "/cygdrive/c/Users/vasya" -Далее все как в *nix : 1 раз ./install_bin.sh , затем ./blockcheck.sh. -WSL использовать нельзя, это не то же самое. - -cygwin для обычной работы winws не нужен. Разве что вы хотите посылать winws SIGHUP для перечитки листов без перезапуска. - -автозапуск winws ----------------- - -Для запуска winws вместе с windows есть 2 варианта. Планировщик задач или службы windows. - -Можно создавать задачи и управлять ими через консольную программу schtasks. -В директории binaries/win64/winws подготовлены файлы task_*.cmd . -В них реализовано создание, удаление, старт и стоп одной копии процесса winws с параметрами из переменной %WINWS1%. -Исправьте параметры на нужную вам стратегию. Если для разных фильтров применяется разная стратегия, размножьте код -для задач winws1,winws2,winws3,... - -Аналогично настраивается вариант запуска через службы windows. Смотрите service_*.cmd. - -Все батники требуется запускать от имени администратора. - -Управлять задачами можно так же из графической программы управления планировщиком taskschd.msc - -zapret-win-bundle ------------------ - -Можно не возиться с cygwin, а взять готовый пакет, включающий в себя cygwin и blockcheck : https://github.com/bol-van/zapret-win-bundle -Там сделан максимум удобств для сосредоточения на самом zapret, исключая возню с установкой cygwin, -заходами в директории, запусками под администратором и прочими сугубо техническими моментами, в которых могут быть -ошибки и непонимания, а новичок без базиса знаний может и вовсе запутаться. - -/zapret-winws - здесь все, что нужно для запуска winws в повседневном рабочем режиме. остальное не нужно. -/zapret-winws/_CMD_ADMIN.cmd - получить командную строку cmd в этой директории от имени администратора для тестирования winws -с параметрами, вводимыми вручную -/blockcheck/blockcheck.cmd - достаточно кликнуть по нему, чтобы пошел blockcheck с записью лога в blockcheck/blockcheck.log -/cygwin/cygwin.cmd - запуск среды cygwin bash под текущим пользователем -/cygwin/cygwin-admin.cmd - запуск среды cygwin bash под администратором - -В среде cygwin уже настроены alias-ы на winws,blockcheck,ip2net,mdig. С путями возиться не нужно ! -Из cygwin можно не только тестировать winws, но и посылать сигналы. -Доступны команды pidof,kill,killall,pgrep,pkill. -Но важно понимать, что таким образом не выйдет посылать сигналы winws, запущенному из zapret-winws, -поскольку там свой cygwin1.dll, и они не разделяют общее пространство процессов unix. -zapret-winws - это отдельный комплект для повседневного использования, не требующий что-то еще, но и не связанный со средой cygwin. - -Среду cygwin можно использовать для записи в файл дебаг-лога winws. Для этого пользуйтесь командой tee. -winws --debug --wf-tcp=80,443 | tee winws.log -winws.log будет в cygwin/home/<имя_пользователя> -Если у вас windows 7, то блокнот не поймет переводы строк в стиле unix. Воспользуйтесь командой -unix2dos winws.log diff --git a/docs/wireguard/wireguard-mod.md b/docs/wireguard/wireguard-mod.md new file mode 100644 index 0000000..60b63bd --- /dev/null +++ b/docs/wireguard/wireguard-mod.md @@ -0,0 +1,296 @@ +# Важное замечание + +Эта инструкция написана еще до включения WireGuard в ядро Linux. +Процесс сборки для in-tree модулей отличается. +Цель данного чтива - дать идею для программистов как можно исправить исходники WireGuard для преодоления DPI. +Автор не преследует цели поддерживать готовые патчи для актуальных версий. +Вместо патчинга гораздо проще использовать навесное решение ipobfs. + +# Патчинг + +Посвящено возможной блокировке в РФ 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`: + +```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`: + +```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`. + +Дописываем в конец инициализации структуры сообщения : + +```c +// MOD: randomize trash + dst->header.trash = gen_trash() +``` + +И в 1 место в `send.c` в функции `encrypt_packet`: + +```c +// 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 из Windows 10, но на практике там очень медленное I/O, по крайней мере на старых версиях Windows 10. Безумно медленное. Будете собирать вечность. +Может в новых Windows 10 что-то и улучшили, но я бы сразу рассчитывал на полноценный 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](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: + +```sh +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`: + +```sh +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 +``` + +```sh +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`, в который нужно вносить изменения в каждый файл : + +```sh +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 и выполняем: + +```sh +make package/wireguard/compile V=99 +``` + +Если не было ошибок, то получили измененные ipk. +Патч можно зафиксировать в описании пакета: + +```sh +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. Сделайте: + +```sh +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 +``` + +затем: + +```sh +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`, устанавливаем так: + +```sh +cd /tmp +rm -r /tmp/opkg-lists +opkg install *.ipk +``` + +Если требует зависимостей, то: + +```sh +opkg update +opkg install <зависимости> +rm -r /tmp/opkg-lists +opkg install *.ipk +``` + +В `/tmp/opkg-lists` `opkg` хранит кэш списка пакетов. +Если попытаться установить файл `.ipk`, и такой же пакет найдется в репозитории, opkg будет устанавливать из репозитория. +А нам это не надо. + +```sh +rmmod wireguard +kmodloader +dmesg | tail +``` + +должны увидеть что-то вроде: + +``` +[8985.415490] wireguard: WireGuard 0.0.20190123 loaded. See for information. +[8985.424178] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld . 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` модуль может не загрузиться или вызвать стабильные или хаотические падения ядра и перезагрузки (включая вариант бесконечной перезагрузки - bootloop). +Так что перед `--force-depends` убедитесь, что знаете как лечится такая ситуация, и не стоит это делать при отсутствии физического +доступа к девайсу. + +Когда поднимите линк, и вдруг ничего не будет работать, то посмотрите в wireshark UDP пакеты на порт endpoint. +Они не должны начинаться с 0,1,2,3,4. В первых 4 байтах должен быть рандом, в следующих 4 байтах - значения из измененного enum message_type. +Если пакет все еще начинается с 0..4, значит, модуль `wireguard` оригинальный, что-то не собралось, не скомпилировалось, не перезапустилось. +В противном случае должен подняться линк, пинги ходить. Значит вы победили, поздравляю. +Регулятору будет намного сложнее поймать ваш VPN. diff --git a/docs/wireguard/wireguard-mod.txt b/docs/wireguard/wireguard-mod.txt deleted file mode 100644 index 878aa44..0000000 --- a/docs/wireguard/wireguard-mod.txt +++ /dev/null @@ -1,250 +0,0 @@ -!!! Эта инструкция написана еще до включения wireguard в ядро linux. -!!! Процесс сборки для in-tree модулей отличается. -!!! Цель данного чтива - дать идею для программистов как можно исправить исходники wireguard -!!! для преодоления DPI. Автор не преследует цели поддерживать готовые патчи для актуальных версий. -!!! Вместо патчинга гораздо проще использовать навесное решение ipobfs. - -Посвящено возможной блокировке в РФ 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 . 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. diff --git a/docs/wireguard/wireguard_iproute_openwrt.md b/docs/wireguard/wireguard_iproute_openwrt.md new file mode 100644 index 0000000..788c7c8 --- /dev/null +++ b/docs/wireguard/wireguard_iproute_openwrt.md @@ -0,0 +1,730 @@ +- [Предисловие](#предисловие) +- [План действий](#план-действий) + - [Если нет своего сервера](#если-нет-своего-сервера) + - [Поднятие сервера](#поднятие-сервера) +- [Подготовка `zapret`](#подготовка-zapret) + - [Маркировка трафика `iptables`](#маркировка-трафика-iptables) + - [Маркировка трафика `nftables`](#маркировка-трафика-nftables) + - [По поводу двойного NAT](#по-поводу-двойного-nat) +- [Как мне отправлять на VPN весь трафик с bittorrent?](#как-мне-отправлять-на-vpn-весь-трафик-с-bittorrent) + - [Автоматизация проброса портов через `miniupnd`](#автоматизация-проброса-портов-через-miniupnd) + +# Предисловие + +Данный мануал пишется не как копипастная инструкция, а как помощь уже соображающему. +Если вы не знаете основ сетей, Linux, OpenWrt, а пытаетесь что-то скопипастить отсюда без малейшего понимания смысла, то маловероятно, что у вас что-то заработает. Не тратьте свое время напрасно. +Цель - донести принципы как это настраивается вообще, а не указать какую буковку где вписать. + +# План действий + +Есть возможность поднять свой 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. + +Понятийно необходимо выполнить следующие шаги : + +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. + +## Если нет своего сервера + +Но есть конфиг от VPN провайдера или от друга "Васи", который захотел с вами поделиться. +Тогда вам не надо настраивать сервер, задача упрощается. Делается невозможным вариант настройки без masquerade (см. ниже). +Из конфига вытаскиваете приватный ключ своего пира и публичный ключ сервера, IP/host/port сервера, используете их в настройках OpenWrt вместо сгенеренных самостоятельно. + +## Поднятие сервера + +WireGuard был включен в ядро Linux с версии 5.6. +Если у вас ядро >=5.6, то достаточно установить пакет `wireguard-tools`. Он содержит user-mode компоненты WireGuard. +Посмотрите, возможно, в вашем дистрибутиве ядро по умолчанию более старое, но в репозитории имеются бэкпорты новых версий. Лучше будет обновить ядро из репозитория. + +В репозитории может быть пакет `wireguard-dkms`. Это автоматизированное средство сборки WireGuard с исходников, в том числе модуль ядра. Можно пользоваться им. +Иначе вам придется собрать WireGuard самому. Ядро должно быть не ниже 3.10. +На сервере должны быть установлены заголовки ядра (`linux-headers-...`) и компилятор `gcc`. + +```sh +git clone --depth 1 https://git.zx2c4.com/wireguard-linux-compat +cd wireguard-linux-compat/src +make +strip --strip-debug wireguard.ko +sudo make install +``` + +WireGuard основан на понятии криптороутинга. Каждый пир (сервер - тоже пир) имеет пару открытый/закрытый ключ. Закрытый ключ остается у пира, открытый прописывается у его партнера. Каждый пир авторизует другого по знанию приватного ключа, соответствующего прописанному у него публичному ключу. +Протокол построен таким образом, что на все неправильные UDP пакеты не следует ответа. +Не знаешь приватный ключ? Не смог послать правильный запрос? +Долбись сколько влезет, я тебе ничего не отвечу. Это защищает от активного пробинга со стороны DPI и просто экономит ресурсы. +Значит, первым делом нужно создать 2 пары ключей: для сервера и для клиента. +`wg genkey` генерит приватный ключ, `wg pubkey` получает из него публичный ключ. + +```sh +$ 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`: + +```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 пира настраивается динамически после успешной фазы проверки ключа. + +Включаем маршрутизацию: + +```sh +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` без параметров. + +Поднятие клиента: + +```sh +opkg update +opkg install wireguard-tools +``` + +Добавляем записи в конфиги: + +`/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 сервера. + +Конечно, оно скорее всего заработает и так, потому что первый пакет пойдет от клиента к серверу и тем самым создаст запись в conntrack. +Все дальнейшие пакеты в обе стороны подпадут под состояние ESTABLISHED и будут пропущены. +Запись будет поддерживаться за счет периодических запросов keep alive. +Но если вы вдруг уберете keep alive или выставите таймаут, превышающий UDP таймаут в conntrack, то могут начаться ошибки, висы и переподключения. +Если же в фаерволе проткнута дырка, то пакеты от сервера не будут заблокированы ни при каких обстоятельствах. + +Перезапускаем фаерволл, поднимаем интерфейс и проверяем: + +```sh +/etc/init.d/firewall restart +ifup wgvps +ifconfig wgvps +ping 192.168.254.1 +``` + +Если все хорошо, должны ходить пинги. +С сервера не помешает : + +```sh +ping 192.168.254.3 +``` + +# Подготовка `zapret` + +Выполните `install_easy.sh`. Он настроит режим обхода DPI. Если обход DPI не нужен - выберите `MODE=filter`. +Так же инсталлятор заресолвит домены из `ipset/zapret-hosts-user-ipban.txt` и внесет крон-джоб для периодического обновления IP. + +Если вы используете в своих правилах ipset zapret, то он ресолвится и обновляется только, если выбран режим фильтрации обхода DPI по ipset. +По сути он вам нужен исключительно, если обход DPI не помогает. Например, удается как-то пробить HTTP, но не удается пробить HTTPS. +И при этом вы хотите, чтобы на VPN направлялись только IP из скачанного IP листа, в добавок к заресолвленному `ipset/zapret-hosts-user.txt`. +Именно этот случай и рассмотрен в данном примере. Если это не так, то убирайте правила с портом 443 из нижеприведенных правил `iptables`/`nftables`. +Если не хотите ограничиваться листом, и хотите направлять все на порт 443, то уберите фильтры из правил `iptables`/`nftables`, связанные с `ipset`/`nfset` "zapret". + +Фильтрация по именам доменов (`MODE_FILTER=hostlist`) невозможна средствами `iptables`/`nftables`. Она производится исключительно в `tpws` и `nfqws` по результатам анализа протокола прикладного уровня, иногда достаточно сложного, связанного с дешифровкой пакета (QUIC). +Скачиваются листы с именами доменов, не IP адресами. `ipset/zapret-hosts-user.txt` не ресолвится, а используется как hostlist. +Потому вам нельзя рассчитывать на ipset zapret. +Тем не менее, при выборе этого режима фильтрации, либо вовсе при ее отсутствии (`MODE_FILTER=none`), `ipset/zapret-hosts-user-ipban.txt` все равно ресолвится. +Вы всегда можете рассчитывать на `ipset`/`nfset` "ipban", "nozapret". + +"nozapret" - это `ipset`/`nfset`, связанный с системой исключения IP. Сюда загоняется все из `ipset/zapret-hosts-user-exclude.txt` после ресолвинга. +Его учет крайне желателен, чтобы вдруг из скачанного листа не просочились записи, например, 192.168.0.0/16 и не заставили лезть туда через VPN. +Хотя скрипты получения листов и пытаются отсечь IP локалок, но так будет намного надежнее. + +## Маркировка трафика `iptables` + +Завернем на VPN все из ipset zapret на TCP:443 и все из `ipban`. +OUTPUT относится к исходящим с роутера пакетам, PREROUTING - ко всем остальным. +Если с самого роутера ничего заруливать не надо, можно опустить часть, отвечающую за OUTPUT. + +`/etc/firewall.user`: + +```sh +. /opt/zapret/init.d/openwrt/functions + +create_ipset no-update + +network_find_wan4_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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 + ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 +ipt PREROUTING -t mangle -i $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 +``` + +```sh +/etc/init.d/firewall restart +``` + +## Маркировка трафика `nftables` + +В новых OpenWrt по умолчанию установлен `nftables`, `iptables` отсутствует. +Есть вариант снести `nftables` + `fw4` и заменить их на `iptables` + `fw3`. +Веб-интерфейс luci понимает прозрачно и `fw3`, и `fw4`. Однако, при установке `iptables` и `fw3` новые пакеты будут устанавливаться без сжатия squashfs. Убедитесь, что у вас достаточно места. +Либо сразу настраивайте образ через image builder. + +Фаервол `fw4` работает в одноименной nftable - "inet fw4". "inet" означает, что таблица принимает и IPv4, и IPv6. +Поскольку для маркировки трафика используется `nfset`, принадлежащий таблице zapret, цепочки необходимо помещать в ту же таблицу. +Для синхронизации лучше всего использовать хук `INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up"` +Параметр нужно раскомментировать в `/opt/zapret/config`. Далее надо создать указанный файл и дать ему `chmod 755`. + +`/etc/firewall.zapret.hook.post_up`: + +```sh +# !/bin/sh + +ZAPRET_NFT_TABLE=zapret + +cat << EOF | nft -f - 2>/dev/null + delete chain inet $ZAPRET_NFT_TABLE my_output + delete chain inet $ZAPRET_NFT_TABLE my_prerouting +EOF + +cat << EOF | nft -f - + add chain inet $ZAPRET_NFT_TABLE my_output { type route hook output priority mangle; } + flush chain inet $ZAPRET_NFT_TABLE my_output + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 + add chain inet $ZAPRET_NFT_TABLE my_prerouting { type filter hook prerouting priority mangle; } + flush chain inet $ZAPRET_NFT_TABLE my_prerouting + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 +EOF +``` + +```sh +/etc/init.d/zapret restart_fw +``` + +Проверка правил: + +```sh +/etc/init.d/zapret list_table +# или +nft -t list table inet zapret +``` + +Должны быть цепочки `my_prerouting` и `my_output`. + +Проверка заполнения nfsets: + +```sh +nft list set inet zapret zapret +nft list set inet zapret ipban +nft list set inet zapret nozapret +``` + +Проверка заполнения множеств `lanif`, `wanif`, `wanif6`, `link_local`: + +```sh +/etc/init.d/zapret list_ifsets +``` + +Должны присутствовать имена интерфейсов во множествах `lanif`, `wanif`. +`wanif6` заполняется только при включении IPv6. +`link_local` нужен только для tpws при включении IPv6. + +## По поводу двойного NAT + +В описанной конфигурации NAT выполняется дважды: на роутере-клиенте происходит замена адреса источника из LAN на 192.168.254.3 и на сервере замена 192.168.254.3 на внешний адрес сервера в инете. +Зачем так делать? Исключительно для простоты настройки. Или на случай, если сервер WireGuard не находится под вашим контролем. +Делать для вас нижеописанные настройки никто не будет с вероятностью, близкой к 100%. +Если сервер WireGuard - ваш, и вы готовы чуток еще поднапрячься и не хотите двойного 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. + +```sh +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`, что и требовалось. + +Альтернативное решение - использовать на VPSке для проброса портов не только DNAT, но и SNAT/MASQUERADE. +Тогда source address будет заменен на 192.168.254.1. Он по таблице маршрутизации пойдет на wgvps. +Но в этом случае клиентские программы, на которые осуществляется проброс портов, не будут видеть реальный IP подключенца. + +`/etc/firewall.user`: + +```sh +. /opt/zapret/init.d/openwrt/functions + +create_ipset no-update + +network_find_wan4_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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 + ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 +ipt PREROUTING -t mangle -i $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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-mark 0x800/0x800 +``` + +```sh +/etc/init.d/firewall restart +``` + +Вариант `nftables`: + +`/etc/firewall.zapret.hook.post_up`: + +```sh +# !/bin/sh + +ZAPRET_NFT_TABLE=zapret +DEVICE=wgvps + +cat << EOF | nft -f - 2>/dev/null + delete chain inet $ZAPRET_NFT_TABLE my_output + delete chain inet $ZAPRET_NFT_TABLE my_prerouting + delete chain inet $ZAPRET_NFT_TABLE my_nat +EOF + +cat << EOF | nft -f - + add chain inet $ZAPRET_NFT_TABLE my_output { type route hook output priority mangle; } + flush chain inet $ZAPRET_NFT_TABLE my_output + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif meta mark set mark or 0x1000 + + add chain inet $ZAPRET_NFT_TABLE my_prerouting { type filter hook prerouting priority mangle; } + flush chain inet $ZAPRET_NFT_TABLE my_prerouting + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname $DEVICE ct state new ct mark set ct mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname != $DEVICE meta mark set ct mark and 0x800 + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 + add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 + +add chain inet $ZAPRET_NFT_TABLE my_nat { type nat hook postrouting priority 100 ; } + flush chain inet $ZAPRET_NFT_TABLE my_nat + add rule inet $ZAPRET_NFT_TABLE my_nat oifname $DEVICE mark and 0x1000 == 0x1000 masquerade +EOF +``` + +```sh +/etc/init.d/zapret restart_fw +``` + +К сожалению, здесь возможности `nftables` немного хромают. Полноценного эквивалента `CONNMARK --restore-mark --nfmask` не существует. Оригинал `iptables` предполагал копирование одного бита 0x800 из connmark в mark. +Лучшее, что можно сделать в `nftables`, это копирование одного бита с занулением всех остальных. +Сложные выражения типа `meta mark set mark and ~0x800 or (ct mark and 0x800)` nft не понимает. +Об этом же говорит попытка перевода через `iptables-translate`. + +Сейчас уже можно с 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' +``` + +```sh +/etc/init.d/firewall restart +/etc/init.d/zapret restart_fw +``` + +`/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 PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2 + 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 PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2 +``` + +```sh +ifdown wgvps +ifup wgvps +``` + +Пример приведен для `iperf` и `iperf3`, чтобы показать как пробрасывать несколько портов TCP+UDP с минимальным количеством команд. +Проброс TCP и UDP порта так же необходим для полноценной работы bittorrent клиента, чтобы работали входящие. + +# Как мне отправлять на VPN весь трафик с bittorrent? + +Можно поступить так: посмотрите порт в настройках torrent клиента, убедитесь, что не поставлено "случайный порт", добавьте на роутер правило маркировки по порту источника. +Но мне предпочтительно иное решение. На Windows есть замечательная возможность прописать правило установки поля качества обслуживания в заголовках IP пакетов в зависимости от процесса-источника. +Для Windows 7/2008R2 необходимо будет установить ключик реестра и перезагрузить комп : + +```powershell +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 +На Windows 10 ключик реестра больше не работает, правила qos в `gpedit` применяются только для профиля домена. +Необходимо пользоваться командой `powershell New-NetQosPolicy`. Гуглите хелп по ней. Пример : + +```powershell +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' +``` + +```sh +/etc/init.d/firewall restart +``` + +Теперь все с полем dscp "1" идет на VPN. Клиент сам решает какой трафик ему нужно забрасывать +на VPN, перенастраивать роутер не нужно. +На Linux клиенте проще всего будет выставлять dscp в `iptables` по номеру порта источника : + +`/etc/rc.local`: + +```sh +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' +``` + +```sh +/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' +``` + +```sh +/etc/init.d/firewall reload +``` + +На сервере: + +```sh +apt install miniupnpd +``` + +`/etc/miniupnpd/miniupnpd.conf`: + +```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 +``` + +```sh +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` diff --git a/docs/wireguard/wireguard_iproute_openwrt.txt b/docs/wireguard/wireguard_iproute_openwrt.txt deleted file mode 100644 index 6d36f91..0000000 --- a/docs/wireguard/wireguard_iproute_openwrt.txt +++ /dev/null @@ -1,645 +0,0 @@ -Данный мануал пишется не как копипастная инструкция, а как помощь уже соображающему. -Если вы не знаете основ сетей, linux, openwrt, а пытаетесь что-то скопипастить отсюда без малейшего -понимания смысла, то маловероятно, что у вас что-то заработает. Не тратье свое время напрасно. -Цель - донести принципы как это настраивается вообще, а не указать какую буковку где вписать. - - -Есть возможность поднять свой 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. - -Понятийно необходимо выполнить следующие шаги : -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. - ---- Если нет своего сервера --- - -Но есть конфиг от VPN провайдера или от друга "Васи", который захотел с вами поделиться. -Тогда вам не надо настраивать сервер, задача упрощается. Делается невозможным вариант настройки -без masquerade (см ниже). -Из конфига вытаскиваете приватный ключ своего пира и публичный ключ сервера, ip/host/port сервера, -используете их в настройках openwrt вместо сгенеренных самостоятельно. - ---- Поднятие сервера --- - -Wireguard был включен в ядро linux с версии 5.6. -Если у вас ядро >=5.6, то достаточно установить пакет wireguard-tools. Он содержит user-mode компоненты wireguard. -Посмотрите, возможно в вашем дистрибутиве ядро по умолчанию более старое, но в репозитории -имеются бэкпорты новых версий. Лучше будет обновить ядро из репозитория. - -В репозитории может быть пакет wireguard-dkms. Это автоматизированное средство сборки -wireguard с исходников, в том числе модуль ядра. Можно пользоваться им. - -Иначе вам придется собрать wireguard самому. Ядро должно быть не ниже 3.10. -На сервере должны быть установлены заголовки ядра (linux-headers-...) и компилятор gcc. - -# git clone --depth 1 https://git.zx2c4.com/wireguard-linux-compat -# cd wireguard-linux-compat/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-tools - -Добавляем записи в конфиги. - ---/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 сервера. - Конечно, оно скорее всего заработает и так, потому что первый пакет пойдет от клиента к серверу и тем самым создаст - запись в conntrack. Все дальнейшие пакеты в обе стороны подпадут под состояние ESTABLISHED и будут пропущены. - Запись будет поддерживаться за счет периодических запросов keep alive. Но если вы вдруг уберете keep alive или - выставите таймаут, превышающий udp таймаут в conntrack, то могут начаться ошибки, висы и переподключения. - Если же в фаерволе проткнута дырка, то пакеты от сервера не будут заблокированы ни при каких обстоятельствах. - -# /etc/init.d/firewall restart -# ifup wgvps -# ifconfig wgvps -# ping 192.168.254.1 - -Если все хорошо, должны ходить пинги. -С сервера не помешает : -# ping 192.168.254.3 - - ---- Подготовка zapret --- - -Выполните install_easy.sh. Он настроит режим обхода DPI. Если обход DPI не нужен - выберите MODE=filter. -Так же инсталятор заресолвит домены из ipset/zapret-hosts-user-ipban.txt и внесет крон-джоб для периодического обновления ip. - -Если вы используете в своих правилах ipset zapret, то он ресолвится и обновляется только, если выбран режим фильтрации обхода DPI по ipset. -По сути он вам нужен исключительно, если обход DPI не помогает. Например, удается как-то пробить http, но не удается пробить https. -И при этом вы хотите, чтобы на VPN направлялись только ip из скачанного ip листа, в добавок к заресолвленному ipset/zapret-hosts-user.txt. -Именно этот случай и рассмотрен в данном примере. Если это не так, то убирайте правила с портом 443 из нижеприведенных правил iptables/nftables. -Если не хотите ограничиваться листом, и хотите направлять все на порт 443, то уберите фильтры из правил iptables/nftables, -связанные с ipset/nfset "zapret". - -Фильтрация по именам доменов (MODE_FILTER=hostlist) невозможна средствами iptables/nftables. Она производится исключительно в tpws и nfqws -по результатам анализа протокола прикладного уровня, иногда достаточно сложного, связанного с дешифровкой пакета (QUIC). -Скачиваются листы с именами доменов, не ip адресами. ipset/zapret-hosts-user.txt не ресолвится, а используется как hostlist. -Потому вам нельзя расчитывать на ipset zapret. -Тем не менее при выборе этого режима фильтрации , либо вовсе при ее отсутствии (MODE_FILTER=none), ipset/zapret-hosts-user-ipban.txt -все равно ресолвится. Вы всегда можете расчитывать на ipset/nfset "ipban", "nozapret". - -"nozapret" - это ipset/nfset, связанный с системой исключения ip. Сюда загоняется все из ipset/zapret-hosts-user-exclude.txt после ресолвинга. -Его учет крайне желателен, чтобы вдруг из скачанного листа не просочились записи, например, 192.168.0.0/16 и не заставили лезть туда через VPN. -Хотя скрипты получения листов и пытаются отсечь IP локалок, но так будет намного надежнее. - ---- Маркировка трафика --- - -Завернем на vpn все из ipset zapret на tcp:443 и все из ipban. -OUTPUT относится к исходящим с роутера пакетам, PREROUTING - ко всем остальным. -Если с самого роутера ничего заруливать не надо, можно опустить часть, отвечающую за OUTPUT. - ---/etc/firewall.user---------------------------- -. /opt/zapret/init.d/openwrt/functions - -create_ipset no-update - -network_find_wan4_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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 - ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 -ipt PREROUTING -t mangle -i $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 ------------------------------------------------- - -# /etc/init.d/firewall restart - ---- Маркировка трафика nftables --- - -В новых openwrt по умолчанию установлен nftables, iptables отсутствует. -Есть вариант снести nftables + fw4 и заменить их на iptables + fw3. -Веб интерфейс luci понимает прозрачно и fw3, и fw4. Однако, при установке iptables и fw3 новые пакеты -будут устанавливаться без сжатия squashfs. Убедитесь, что у вас достаточно места. -Либо сразу настраивайте образ через image builder. - -Фаервол fw4 работает в одноименной nftable - "inet fw4". "inet" означает, что таблица принимает и ipv4, и ipv6. -Поскольку для маркировки трафика используется nfset, принадлежащий таблице zapret, цепочки необходимо помещать в ту же таблицу. -Для синхронизации лучше всего использовать хук -INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up" -Параметр нужно раскоментировать в /opt/zapret/config. Далее надо создать указанный файл и дать ему chmod 755. - ---/etc/firewall.zapret.hook.post_up---------------------------- -#!/bin/sh - -ZAPRET_NFT_TABLE=zapret - -cat << EOF | nft -f - 2>/dev/null - delete chain inet $ZAPRET_NFT_TABLE my_output - delete chain inet $ZAPRET_NFT_TABLE my_prerouting -EOF - -cat << EOF | nft -f - - add chain inet $ZAPRET_NFT_TABLE my_output { type route hook output priority mangle; } - flush chain inet $ZAPRET_NFT_TABLE my_output - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 - - add chain inet $ZAPRET_NFT_TABLE my_prerouting { type filter hook prerouting priority mangle; } - flush chain inet $ZAPRET_NFT_TABLE my_prerouting - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 -EOF ------------------------------------------------- - -# /etc/init.d/zapret restart_fw - -Проверка правил : -# /etc/init.d/zapret list_table -или -# nft -t list table inet zapret - -Должны быть цепочки my_prerouting и my_output. - -Проверка заполнения nfsets : -# nft list set inet zapret zapret -# nft list set inet zapret ipban -# nft list set inet zapret nozapret - -Проверка заполнения множеств lanif, wanif, wanif6, link_local : -# /etc/init.d/zapret list_ifsets - -Должны присутствовать имена интерфейсов во множествах lanif, wanif. -wanif6 заполняется только при включении ipv6. -link_local нужен только для tpws при включении ipv6. - ---- По поводу двойного NAT --- - -В описанной конфигурации nat выполняется дважды : на роутере-клиенте происходит замена адреса источника из LAN -на 192.168.254.3 и на сервере замена 192.168.254.3 на внешний адрес сервера в инете. -Зачем так делать ? Исключительно для простоты настройки. Или на случай, если сервер wireguard не находится под вашим контролем. -Делать для вас нижеописанные настройки никто не будет с вероятностью, близкой к 100%. -Если сервер wireguard - ваш, и вы готовы чуток еще поднапрячься и не хотите двойного 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, что и требовалось. - -Альтернативное решение - использовать на VPSке для проброса портов не только DNAT, но и SNAT/MASQUERADE. Тогда source address -будет заменен на 192.168.254.1. Он по таблице маршрутизации пойдет на wgvps. Но в этом случае клиентские программы, -на которые осуществляется проброс портов, не будут видеть реальный IP подключенца. - ---/etc/firewall.user---------------------------- -. /opt/zapret/init.d/openwrt/functions - -create_ipset no-update - -network_find_wan4_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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 - ipt OUTPUT -t mangle -o $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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 -m set ! --match-set nozapret dst -j MARK --set-mark 0x800/0x800 -ipt PREROUTING -t mangle -i $DEVICE -m set --match-set ipban dst -m set ! --match-set nozapret 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-mark 0x800/0x800 ------------------------------------------------- - -# /etc/init.d/firewall restart - -Вариант nftables : - ---/etc/firewall.zapret.hook.post_up---------------------------- -#!/bin/sh - -ZAPRET_NFT_TABLE=zapret -DEVICE=wgvps - -cat << EOF | nft -f - 2>/dev/null - delete chain inet $ZAPRET_NFT_TABLE my_output - delete chain inet $ZAPRET_NFT_TABLE my_prerouting - delete chain inet $ZAPRET_NFT_TABLE my_nat -EOF - -cat << EOF | nft -f - - add chain inet $ZAPRET_NFT_TABLE my_output { type route hook output priority mangle; } - flush chain inet $ZAPRET_NFT_TABLE my_output - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_output oifname @wanif meta mark set mark or 0x1000 - - add chain inet $ZAPRET_NFT_TABLE my_prerouting { type filter hook prerouting priority mangle; } - flush chain inet $ZAPRET_NFT_TABLE my_prerouting - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname $DEVICE ct state new ct mark set ct mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname != $DEVICE meta mark set ct mark and 0x800 - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif ip daddr @ipban ip daddr != @nozapret meta mark set mark or 0x800 - add rule inet $ZAPRET_NFT_TABLE my_prerouting iifname @lanif tcp dport 443 ip daddr @zapret ip daddr != @nozapret meta mark set mark or 0x800 - - add chain inet $ZAPRET_NFT_TABLE my_nat { type nat hook postrouting priority 100 ; } - flush chain inet $ZAPRET_NFT_TABLE my_nat - add rule inet $ZAPRET_NFT_TABLE my_nat oifname $DEVICE mark and 0x1000 == 0x1000 masquerade -EOF ------------------------------------------------- - -# /etc/init.d/zapret restart_fw - -К сожалению, здесь возможности nftables немного хромают. Полноценного эквивалента CONNMARK --restore-mark --nfmask -не существует. Оригинал iptables предполагал копирование одного бита 0x800 из connmark в mark. -Лучшее, что можно сделать в nftables, это копирование одного бита с занулением всех остальных. -Сложные выражения типа "meta mark set mark and ~0x800 or (ct mark and 0x800)" nft не понимает. -Об этом же говорит попытка перевода через iptables-translate. - -Сейчас уже можно с 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' ------------------------------------------------- - -# /etc/init.d/firewall restart -# /etc/init.d/zapret restart_fw - ---/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 PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2 - 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 PREROUTING -i eth0 -p udp -m multiport --dports 5001,5201 -j DNAT --to-destination 192.168.2.2 ----------------------------------------------- - -# 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' ------------------------------------------------- - -# /etc/init.d/firewall 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' ------------------------------------------------- - -/etc/init.d/firewall 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