├── init.d ├── sysv │ ├── custom.d │ │ └── .keep │ ├── zapret2 │ └── functions ├── openwrt │ ├── custom.d │ │ └── .keep │ ├── firewall.zapret2 │ ├── 90-zapret2 │ ├── zapret2 │ └── functions ├── s6 │ └── zapret2 │ │ ├── type │ │ ├── down │ │ └── up ├── runit │ └── zapret2 │ │ ├── finish │ │ └── run ├── windivert.filter.examples │ ├── windivert_part.wireguard.txt │ ├── windivert_part.stun.txt │ ├── windivert_part.quic_initial_ietf.txt │ ├── windivert_part.discord_media.txt │ └── README.txt ├── systemd │ ├── zapret2-list-update.service │ ├── zapret2-list-update.timer │ ├── zapret2.service │ └── nfqws2@.service ├── pfsense │ └── zapret2.sh ├── custom.d.examples.linux │ ├── 10-keenetic-udp-fix │ ├── 50-quic4all │ ├── 50-stun4all │ ├── 50-wg4all │ ├── 50-dht4all │ ├── 40-webserver │ ├── 50-discord-media │ ├── 20-fw-extra │ └── 50-nfqws-ipset └── openrc │ └── zapret2 ├── files └── fake │ ├── dns.bin │ ├── rdp.bin │ ├── stun.bin │ ├── dht_find_node.bin │ ├── dht_get_peers.bin │ ├── quic_short_header.bin │ ├── wireguard_response.bin │ ├── discord-ip-discovery-without-port.bin │ ├── quic_initial_vk_com.bin │ ├── wireguard_initiation.bin │ ├── dtls_clienthello_w3_org.bin │ ├── tls_clienthello_vk_com.bin │ ├── isakmp_initiator_request.bin │ ├── quic_initial_facebook_com.bin │ ├── quic_initial_rutracker_org.bin │ ├── tls_clienthello_iana_org.bin │ ├── quic_initial_www_google_com.bin │ ├── tls_clienthello_gosuslugi_ru.bin │ ├── tls_clienthello_sberbank_ru.bin │ ├── tls_clienthello_vk_com_kyber.bin │ ├── discord-ip-discovery-with-port.bin │ ├── tls_clienthello_www_google_com.bin │ ├── quic_initial_facebook_com_quiche.bin │ ├── tls_clienthello_iana_org_bigsize.bin │ ├── quic_initial_rutracker_org_kyber_1.bin │ ├── quic_initial_rutracker_org_kyber_2.bin │ ├── tls_clienthello_rutracker_org_kyber.bin │ ├── quic_initial_rr2---sn-gvnuxaxjvh-o8ge_googlevideo_com.bin │ ├── quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_1.bin │ ├── quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_2.bin │ ├── zero_256.bin │ ├── http_iana_org.bin │ ├── zero_512.bin │ ├── sip.bin │ └── zero_1024.bin ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── issue-warning.md └── workflows │ └── libnetfilter_queue-android.patch ├── docs ├── compile │ ├── openwrt │ │ └── package │ │ │ └── zapret │ │ │ ├── mdig │ │ │ ├── readme.txt │ │ │ └── Makefile │ │ │ ├── nfqws2 │ │ │ ├── readme.txt │ │ │ └── Makefile │ │ │ └── ip2net │ │ │ ├── readme.txt │ │ │ └── Makefile │ ├── build_howto_unix.txt │ ├── build_howto_windows.txt │ └── build_howto_openwrt.txt ├── changes_compat.txt ├── LICENSE.txt └── changes.txt ├── nfq2 ├── windows │ ├── res │ │ ├── 32 │ │ │ ├── winicon.o │ │ │ └── winmanifest.o │ │ └── 64 │ │ │ ├── winicon.o │ │ │ └── winmanifest.o │ └── windivert │ │ ├── libwindivert32.a │ │ └── libwindivert64.a ├── win.h ├── gzip.h ├── crypto │ ├── aes-gcm.h │ ├── aes-ctr.h │ ├── aes-gcm.c │ ├── sha-private.h │ ├── aes-ctr.c │ ├── aes.h │ └── usha.c ├── nfqws.h ├── ipset.h ├── desync.h ├── hostlist.h ├── BSDmakefile ├── packet_queue.h ├── checksum.h ├── conntrack_base.h ├── gzip.c ├── packet_queue.c ├── sec.h ├── win.c ├── Makefile ├── lua.h ├── conntrack.h ├── checksum.c └── helpers.h ├── .gitattributes ├── ipset ├── zapret-hosts-user-exclude.txt.default ├── get_user.sh ├── get_exclude.sh ├── get_ipban.sh ├── get_antifilter_ip.sh ├── get_antifilter_ipsum.sh ├── get_config.sh ├── clear_lists.sh ├── get_antifilter_allyouneed.sh ├── get_antifilter_ipresolve.sh ├── get_antifilter_ipsmart.sh ├── antifilter.helper ├── get_antizapret_domains.sh ├── get_refilter_ipsum.sh ├── get_refilter_domains.sh ├── get_reestr_resolvable_domains.sh ├── get_reestr_preresolved.sh ├── get_reestr_preresolved_smart.sh ├── get_reestr_hostlist.sh └── get_reestr_resolve.sh ├── blockcheck2.d ├── custom │ ├── list_quic.txt │ ├── list_http.txt │ ├── list_https_tls12.txt │ ├── list_https_tls13.txt │ ├── README.txt │ └── 10-list.sh └── standard │ ├── 10-http-basic.sh │ ├── def.inc │ ├── 15-misc.sh │ ├── 90-quic.sh │ ├── 24-syndata.sh │ ├── 20-multi.sh │ ├── 35-hostfake.sh │ ├── 30-faked.sh │ ├── 23-seqovl.sh │ ├── 60-fake-hostfake.sh │ └── 25-fake.sh ├── ip2net ├── qsort.h └── Makefile ├── .gitignore ├── common ├── elevate.sh ├── linux_iphelper.sh ├── linux_daemons.sh ├── custom.sh ├── virt.sh ├── fwtype.sh ├── dialog.sh ├── linux_fw.sh └── list.sh ├── mdig └── Makefile ├── install_prereq.sh ├── lua ├── zapret-pcap.lua └── zapret-wgobfs.lua ├── Makefile ├── uninstall_easy.sh ├── install_bin.sh └── config.default /init.d/sysv/custom.d/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /init.d/openwrt/custom.d/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /init.d/s6/zapret2/type: -------------------------------------------------------------------------------- 1 | oneshot 2 | -------------------------------------------------------------------------------- /files/fake/dns.bin: -------------------------------------------------------------------------------- 1 | 2Mupdate microsoftcom -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/mdig/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "mdig" folder here ! 2 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/nfqws2/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "nfq2" folder here ! 2 | -------------------------------------------------------------------------------- /init.d/runit/zapret2/finish: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /opt/zapret2/init.d/sysv/zapret2 stop 3 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/ip2net/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "ip2net" folder here ! 2 | -------------------------------------------------------------------------------- /files/fake/rdp.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/rdp.bin -------------------------------------------------------------------------------- /files/fake/stun.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/stun.bin -------------------------------------------------------------------------------- /init.d/s6/zapret2/down: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -P 2 | exec /opt/zapret2/init.d/sysv/zapret2 stop 3 | -------------------------------------------------------------------------------- /init.d/s6/zapret2/up: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -P 2 | exec /opt/zapret2/init.d/sysv/zapret2 start 3 | -------------------------------------------------------------------------------- /files/fake/dht_find_node.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/dht_find_node.bin -------------------------------------------------------------------------------- /files/fake/dht_get_peers.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/dht_get_peers.bin -------------------------------------------------------------------------------- /nfq2/windows/res/32/winicon.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/res/32/winicon.o -------------------------------------------------------------------------------- /nfq2/windows/res/64/winicon.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/res/64/winicon.o -------------------------------------------------------------------------------- /files/fake/quic_short_header.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_short_header.bin -------------------------------------------------------------------------------- /files/fake/wireguard_response.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/wireguard_response.bin -------------------------------------------------------------------------------- /nfq2/windows/res/32/winmanifest.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/res/32/winmanifest.o -------------------------------------------------------------------------------- /nfq2/windows/res/64/winmanifest.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/res/64/winmanifest.o -------------------------------------------------------------------------------- /files/fake/discord-ip-discovery-without-port.bin: -------------------------------------------------------------------------------- 1 | F̯ -------------------------------------------------------------------------------- /files/fake/quic_initial_vk_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_vk_com.bin -------------------------------------------------------------------------------- /files/fake/wireguard_initiation.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/wireguard_initiation.bin -------------------------------------------------------------------------------- /init.d/runit/zapret2/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /opt/zapret2/init.d/sysv/zapret2 start 3 | exec chpst -b zapret2 sleep infinity 4 | -------------------------------------------------------------------------------- /files/fake/dtls_clienthello_w3_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/dtls_clienthello_w3_org.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_vk_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_vk_com.bin -------------------------------------------------------------------------------- /files/fake/isakmp_initiator_request.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/isakmp_initiator_request.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_facebook_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_facebook_com.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rutracker_org.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_iana_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_iana_org.bin -------------------------------------------------------------------------------- /nfq2/windows/windivert/libwindivert32.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/windivert/libwindivert32.a -------------------------------------------------------------------------------- /nfq2/windows/windivert/libwindivert64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/nfq2/windows/windivert/libwindivert64.a -------------------------------------------------------------------------------- /files/fake/quic_initial_www_google_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_www_google_com.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_gosuslugi_ru.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_gosuslugi_ru.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_sberbank_ru.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_sberbank_ru.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_vk_com_kyber.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_vk_com_kyber.bin -------------------------------------------------------------------------------- /init.d/windivert.filter.examples/windivert_part.wireguard.txt: -------------------------------------------------------------------------------- 1 | outbound and 2 | udp.PayloadLength=148 and 3 | udp.Payload[0]=0x01 -------------------------------------------------------------------------------- /files/fake/discord-ip-discovery-with-port.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/discord-ip-discovery-with-port.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_www_google_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_www_google_com.bin -------------------------------------------------------------------------------- /nfq2/win.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __CYGWIN__ 4 | 5 | #include 6 | 7 | bool service_run(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | *.cmd eol=crlf 3 | *.bat eol=crlf 4 | init.d/windivert.filter.examples/** eol=crlf 5 | files/** binary 6 | -------------------------------------------------------------------------------- /files/fake/quic_initial_facebook_com_quiche.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_facebook_com_quiche.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_iana_org_bigsize.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_iana_org_bigsize.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org_kyber_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rutracker_org_kyber_1.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org_kyber_2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rutracker_org_kyber_2.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_rutracker_org_kyber.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/tls_clienthello_rutracker_org_kyber.bin -------------------------------------------------------------------------------- /init.d/windivert.filter.examples/windivert_part.stun.txt: -------------------------------------------------------------------------------- 1 | outbound and 2 | udp.PayloadLength>=20 and 3 | udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40 -------------------------------------------------------------------------------- /files/fake/quic_initial_rr2---sn-gvnuxaxjvh-o8ge_googlevideo_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rr2---sn-gvnuxaxjvh-o8ge_googlevideo_com.bin -------------------------------------------------------------------------------- /nfq2/gzip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int z_readfile(FILE *F,char **buf,size_t *size); 8 | bool is_gzip(FILE* F); 9 | -------------------------------------------------------------------------------- /ipset/zapret-hosts-user-exclude.txt.default: -------------------------------------------------------------------------------- 1 | 127.0.0.0/8 2 | 10.0.0.0/8 3 | 172.16.0.0/12 4 | 192.168.0.0/16 5 | 169.254.0.0/16 6 | 100.64.0.0/10 7 | ::1 8 | fc00::/7 9 | fe80::/10 10 | -------------------------------------------------------------------------------- /files/fake/quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_1.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bol-van/zapret2/HEAD/files/fake/quic_initial_rr1---sn-xguxaxjvh-n8me_googlevideo_com_kyber_2.bin -------------------------------------------------------------------------------- /blockcheck2.d/custom/list_quic.txt: -------------------------------------------------------------------------------- 1 | # write nfqws2 parameters here 2 | --payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=11 3 | --payload quic_initial --lua-desync=send:ipfrag --lua-desync=drop 4 | -------------------------------------------------------------------------------- /ipset/get_user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # resolve user host list 3 | 4 | IPSET_DIR="$(dirname "$0")" 5 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 6 | 7 | . "$IPSET_DIR/def.sh" 8 | 9 | getuser 10 | 11 | "$IPSET_DIR/create_ipset.sh" 12 | -------------------------------------------------------------------------------- /ipset/get_exclude.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # resolve user host list 3 | 4 | IPSET_DIR="$(dirname "$0")" 5 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 6 | 7 | . "$IPSET_DIR/def.sh" 8 | 9 | getexclude 10 | 11 | "$IPSET_DIR/create_ipset.sh" 12 | -------------------------------------------------------------------------------- /blockcheck2.d/custom/list_http.txt: -------------------------------------------------------------------------------- 1 | # write nfqws2 parameters here 2 | --payload=http_req --lua-desync=http_hostcase 3 | --payload=http_req --lua-desync=http_methodeol 4 | --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_ts=-1000 5 | -------------------------------------------------------------------------------- /init.d/windivert.filter.examples/windivert_part.quic_initial_ietf.txt: -------------------------------------------------------------------------------- 1 | outbound and 2 | udp.PayloadLength>=256 and 3 | udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and 4 | udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1 5 | -------------------------------------------------------------------------------- /ipset/get_ipban.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # resolve only ipban user host list 3 | 4 | IPSET_DIR="$(dirname "$0")" 5 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 6 | 7 | . "$IPSET_DIR/def.sh" 8 | 9 | getipban 10 | 11 | "$IPSET_DIR/create_ipset.sh" 12 | -------------------------------------------------------------------------------- /ip2net/qsort.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // GNU qsort is 2x faster than musl 4 | 5 | typedef int (*__gnu_compar_d_fn_t) (const void *, const void *, void *); 6 | void gnu_quicksort (void *const pbase, size_t total_elems, size_t size, __gnu_compar_d_fn_t cmp, void *arg); 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /config 2 | ip2net/ip2net 3 | mdig/mdig 4 | nfq2/dvtws2 5 | nfq2/nfqws2 6 | nfq2/winws2.exe 7 | nfq2/WinDivert* 8 | tpws/tpws 9 | binaries/my/ 10 | ipset/zapret-ip*.txt 11 | ipset/zapret-ip*.gz 12 | ipset/zapret-hosts*.txt 13 | ipset/zapret-hosts*.gz 14 | -------------------------------------------------------------------------------- /files/fake/zero_256.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /init.d/openwrt/firewall.zapret2: -------------------------------------------------------------------------------- 1 | SCRIPT=$(readlink /etc/init.d/zapret2) 2 | if [ -n "$SCRIPT" ]; then 3 | EXEDIR=$(dirname "$SCRIPT") 4 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 5 | else 6 | ZAPRET_BASE=/opt/zapret2 7 | fi 8 | 9 | . "$ZAPRET_BASE/init.d/openwrt/functions" 10 | 11 | zapret_apply_firewall 12 | -------------------------------------------------------------------------------- /init.d/systemd/zapret2-list-update.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=zapret2 ip/host list update 3 | 4 | [Service] 5 | Restart=no 6 | IgnoreSIGPIPE=no 7 | KillMode=control-group 8 | GuessMainPID=no 9 | RemainAfterExit=no 10 | ExecStart=/opt/zapret2/ipset/get_config.sh 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /init.d/systemd/zapret2-list-update.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=zapret2 ip/host list update timer 3 | 4 | [Timer] 5 | OnCalendar=*-*-2,4,6,8,10,12,14,16,18,20,22,24,26,28,30 00:00:00 6 | RandomizedDelaySec=86400 7 | Persistent=true 8 | Unit=zapret2-list-update.service 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /ipset/get_antifilter_ip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | getuser && { 9 | . "$IPSET_DIR/antifilter.helper" 10 | get_antifilter https://antifilter.download/list/ip.lst "$ZIPLIST" 11 | } 12 | 13 | "$IPSET_DIR/create_ipset.sh" 14 | -------------------------------------------------------------------------------- /ipset/get_antifilter_ipsum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | getuser && { 9 | . "$IPSET_DIR/antifilter.helper" 10 | get_antifilter https://antifilter.download/list/ipsum.lst "$ZIPLIST" 11 | } 12 | 13 | "$IPSET_DIR/create_ipset.sh" 14 | -------------------------------------------------------------------------------- /ipset/get_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # run script specified in config 3 | 4 | IPSET_DIR="$(dirname "$0")" 5 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 6 | 7 | [ -f "$IPSET_DIR/../config" ] && . "$IPSET_DIR/../config" 8 | 9 | [ -z "$GETLIST" ] && GETLIST=get_ipban.sh 10 | [ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST" 11 | -------------------------------------------------------------------------------- /blockcheck2.d/custom/list_https_tls12.txt: -------------------------------------------------------------------------------- 1 | # write nfqws2 parameters here 2 | --payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000 3 | --payload=tls_client_hello --lua-desync=fake:blob=0x00000000:tcp_md5:repeats=1 --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,dupsid:repeats=1 --lua-desync=multisplit:pos=2 4 | -------------------------------------------------------------------------------- /ipset/clear_lists.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | rm -f "$ZIPLIST"* "$ZIPLIST6"* "$ZIPLIST_USER" "$ZIPLIST_USER6" "$ZIPLIST_IPBAN"* "$ZIPLIST_IPBAN6"* "$ZIPLIST_USER_IPBAN" "$ZIPLIST_USER_IPBAN6" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6" "$ZHOSTLIST"* 9 | -------------------------------------------------------------------------------- /ipset/get_antifilter_allyouneed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | getuser && { 9 | . "$IPSET_DIR/antifilter.helper" 10 | get_antifilter https://antifilter.download/list/allyouneed.lst "$ZIPLIST" 11 | } 12 | 13 | "$IPSET_DIR/create_ipset.sh" 14 | -------------------------------------------------------------------------------- /ipset/get_antifilter_ipresolve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | getuser && { 9 | . "$IPSET_DIR/antifilter.helper" 10 | get_antifilter https://antifilter.download/list/ipresolve.lst "$ZIPLIST" 11 | } 12 | 13 | "$IPSET_DIR/create_ipset.sh" 14 | -------------------------------------------------------------------------------- /ipset/get_antifilter_ipsmart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | getuser && { 9 | . "$IPSET_DIR/antifilter.helper" 10 | get_antifilter https://antifilter.network/download/ipsmart.lst "$ZIPLIST" 11 | } 12 | 13 | "$IPSET_DIR/create_ipset.sh" 14 | -------------------------------------------------------------------------------- /nfq2/crypto/aes-gcm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "gcm.h" 4 | 5 | // mode : AES_ENCRYPT, AES_DECRYPT 6 | int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_length, const uint8_t *key, const size_t key_len, const uint8_t *iv, const size_t iv_len, const uint8_t *adata, size_t adata_len, uint8_t *atag, size_t atag_len); 7 | -------------------------------------------------------------------------------- /nfq2/nfqws.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __linux__ 6 | #define HAS_FILTER_SSID 1 7 | #endif 8 | 9 | #ifdef __CYGWIN__ 10 | extern bool bQuit; 11 | #endif 12 | int main(int argc, char *argv[]); 13 | 14 | // when something changes that can break LUA compatibility this version should be increased 15 | #define LUA_COMPAT_VER 3 16 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/10-http-basic.sh: -------------------------------------------------------------------------------- 1 | pktws_check_http() 2 | { 3 | # $1 - test function 4 | # $2 - domain 5 | local s 6 | 7 | [ "$NOTEST_BASIC_HTTP" = 1 ] && { echo "SKIPPED"; return; } 8 | 9 | for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol'; do 10 | pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s 11 | done 12 | } 13 | -------------------------------------------------------------------------------- /nfq2/crypto/aes-ctr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "aes.h" 5 | 6 | void aes_ctr_xcrypt_buffer(aes_context *ctx, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out); 7 | int aes_ctr_crypt(const uint8_t *key, unsigned int key_len, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out); 8 | void ctr_add(uint8_t *counter, uint64_t add); 9 | -------------------------------------------------------------------------------- /init.d/systemd/zapret2.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | After=network-online.target 3 | Wants=network-online.target 4 | 5 | [Service] 6 | Type=forking 7 | Restart=no 8 | TimeoutSec=30sec 9 | IgnoreSIGPIPE=no 10 | KillMode=none 11 | GuessMainPID=no 12 | RemainAfterExit=no 13 | ExecStart=/opt/zapret2/init.d/sysv/zapret2 start 14 | ExecStop=/opt/zapret2/init.d/sysv/zapret2 stop 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /docs/compile/build_howto_unix.txt: -------------------------------------------------------------------------------- 1 | debian,ubuntu : 2 | 3 | apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev libluajit2-5.1-dev 4 | make -C /opt/zapret2 systemd 5 | 6 | FreeBSD : 7 | 8 | pkg search luajit-2 9 | # see what's the version available 10 | pkg install luajit-2.1.0.20250728 11 | make -C /opt/zapret2 12 | 13 | OpenBSD : 14 | 15 | pkg_add luajit gmake bsd 16 | gmake -C /opt/zapret2 17 | -------------------------------------------------------------------------------- /blockcheck2.d/custom/list_https_tls13.txt: -------------------------------------------------------------------------------- 1 | # write nfqws2 parameters here 2 | --payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000 3 | --payload tls_client_hello --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop 4 | --payload tls_client_hello --lua-desync=luaexec:code="desync.pat=tls_mod(fake_default_tls,'rnd,rndsni,dupsid,padencap',desync.reasm_data)" --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop 5 | -------------------------------------------------------------------------------- /files/fake/http_iana_org.bin: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host: www.iana.org 3 | Connection: keep-alive 4 | Upgrade-Insecure-Requests: 1 5 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4300.0 Safari/537.36 6 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 7 | Accept-Encoding: gzip, deflate 8 | Accept-Language: en-US,en;q=0.9,ru;q=0.8 9 | 10 | -------------------------------------------------------------------------------- /files/fake/zero_512.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nfq2/ipset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "params.h" 6 | #include "pools.h" 7 | 8 | bool LoadAllIpsets(); 9 | bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6); 10 | struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename); 11 | void IpsetsDebug(); 12 | bool AppendIpsetItem(ipset *ips, char *ip); 13 | 14 | #define ResetAllIpsetModTime() ipset_files_reset_modtime(¶ms.ipsets) 15 | -------------------------------------------------------------------------------- /files/fake/sip.bin: -------------------------------------------------------------------------------- 1 | REGISTER sip:192.168.1.1 SIP/2.0 2 | Via: SIP/2.0/UDP 192.168.1.2:42931;rport;branch=z9hG4bKPj3fd2e8713ffcd90c43f6ce69f6c98461 3 | Max-Forwards: 50 4 | From: ;tag=ca565d7bd4e24a6d80c631d395ee117e 5 | To: 6 | Call-ID: dfec38302b8cea3d83c1452527c895c1 7 | CSeq: 26139 REGISTER 8 | User-Agent: MicroSIP/3.21.5 9 | Contact: 10 | Expires: 300 11 | Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS 12 | Content-Length: 0 13 | 14 | -------------------------------------------------------------------------------- /ipset/antifilter.helper: -------------------------------------------------------------------------------- 1 | get_antifilter() 2 | { 3 | # $1 - list url 4 | # $2 - target file 5 | local ZIPLISTTMP="$TMPDIR/zapret-ip.txt" 6 | 7 | [ "$DISABLE_IPV4" != "1" ] && { 8 | curl --fail --max-time 150 --connect-timeout 20 --max-filesize 41943040 -k -L "$1" | cut_local >"$ZIPLISTTMP" && 9 | { 10 | dlsize=$(LC_ALL=C LANG=C wc -c "$ZIPLISTTMP" | xargs | cut -f 1 -d ' ') 11 | if [ $dlsize -lt 102400 ]; then 12 | echo list file is too small. can be bad. 13 | exit 2 14 | fi 15 | ip2net4 <"$ZIPLISTTMP" | zz "$2" 16 | rm -f "$ZIPLISTTMP" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/def.inc: -------------------------------------------------------------------------------- 1 | FOOLINGS46_TCP=${FOOLINGS46_TCP:-"tcp_md5 badsum tcp_seq=-3000 tcp_seq=1000000 tcp_ack=-66000:tcp_ts_up tcp_ts=-1000 tcp_flags_unset=ACK tcp_flags_set=SYN"} 2 | FOOLINGS6_TCP=${FOOLINGS6_TCP:-"ip6_hopbyhop ip6_hopbyhop:ip6_hopbyhop2 ip6_destopt ip6_routing ip6_ah"} 3 | FOOLINGS_TCP="$FOOLINGS46_TCP" 4 | [ "$IPV" = 6 ] && FOOLINGS_TCP="$FOOLINGS_TCP $FOOLINGS6_TCP" 5 | FOOLINGS6_UDP="${FOOLINGS6_UDP:-$FOOLINGS6_TCP}" 6 | FOOLINGS_UDP="${FOOLINGS_UDP:-badsum}" 7 | [ "$IPV" = 6 ] && FOOLINGS_UDP="$FOOLINGS_UDP $FOOLINGS6_UDP" 8 | 9 | FAKE_REPEATS=${FAKE_REPEATS:-1} 10 | -------------------------------------------------------------------------------- /docs/changes_compat.txt: -------------------------------------------------------------------------------- 1 | Here listed all api breaking changes. 2 | When something changes capable of breaking things NFQWS2_COMPAT_VER increases. 3 | 4 | v2 5 | * removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request. 6 | every LUA relying on desync.l7payload should be revised. 7 | nfqws2 --payload option and init.d custom scripts must be updated. 8 | 9 | v3 10 | * restructured desync.track. pass positions in desync.track.pos.{client,server,direct,reverse} 11 | code relying on conntrack counters and sequence numbers must be rewritten 12 | -------------------------------------------------------------------------------- /nfq2/crypto/aes-gcm.c: -------------------------------------------------------------------------------- 1 | #include "aes-gcm.h" 2 | 3 | int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_length, const uint8_t *key, const size_t key_len, const uint8_t *iv, const size_t iv_len, const uint8_t *adata, size_t adata_len, uint8_t *atag, size_t atag_len) 4 | { 5 | int ret = 0; 6 | gcm_context ctx; 7 | 8 | gcm_initialize(); 9 | 10 | if (!(ret = gcm_setkey(&ctx, key, (const uint)key_len))) 11 | { 12 | ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len); 13 | gcm_zero_ctx(&ctx); 14 | } 15 | 16 | return ret; 17 | } 18 | -------------------------------------------------------------------------------- /nfq2/desync.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "darkmagic.h" 4 | 5 | #include 6 | #include 7 | 8 | #define __FAVOR_BSD 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __linux__ 15 | #define DPI_DESYNC_FWMARK_DEFAULT 0x40000000 16 | #elif defined(SO_USER_COOKIE) 17 | #define DPI_DESYNC_FWMARK_DEFAULT 512 18 | #else 19 | #define DPI_DESYNC_FWMARK_DEFAULT 0 20 | #endif 21 | 22 | uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt); 23 | -------------------------------------------------------------------------------- /common/elevate.sh: -------------------------------------------------------------------------------- 1 | require_root() 2 | { 3 | local exe preserve_env 4 | echo \* checking privileges 5 | [ $(id -u) -ne "0" ] && { 6 | echo root is required 7 | exe="$EXEDIR/$(basename "$0")" 8 | exists sudo && { 9 | echo elevating with sudo 10 | exec sudo -E sh "$exe" 11 | } 12 | exists su && { 13 | echo elevating with su 14 | case "$UNAME" in 15 | Linux) 16 | preserve_env="--preserve-environment" 17 | ;; 18 | FreeBSD|OpenBSD|Darwin) 19 | preserve_env="-m" 20 | ;; 21 | esac 22 | exec su $preserve_env root -c "sh \"$exe\"" 23 | } 24 | echo su or sudo not found 25 | exitp 2 26 | } 27 | HAVE_ROOT=1 28 | } 29 | -------------------------------------------------------------------------------- /common/linux_iphelper.sh: -------------------------------------------------------------------------------- 1 | get_uevent_devtype() 2 | { 3 | local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N 4 | [ -f "/sys/class/net/$1/uevent" ] && { 5 | . "/sys/class/net/$1/uevent" 6 | echo -n $DEVTYPE 7 | } 8 | } 9 | resolve_lower_devices() 10 | { 11 | # $1 - bridge interface name 12 | [ -d "/sys/class/net/$1" ] && { 13 | find "/sys/class/net/$1" -follow -maxdepth 1 -name "lower_*" | 14 | { 15 | local l lower lowers 16 | while read lower; do 17 | lower="$(basename "$lower")" 18 | l="${lower#lower_*}" 19 | [ "$l" != "$lower" ] && append_separator_list lowers ' ' '' "$l" 20 | done 21 | printf "$lowers" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /init.d/windivert.filter.examples/windivert_part.discord_media.txt: -------------------------------------------------------------------------------- 1 | outbound and ip and 2 | udp.DstPort>=50000 and udp.DstPort<=50099 and 3 | udp.PayloadLength=74 and 4 | udp.Payload32[0]=0x00010046 and 5 | udp.Payload32[2]=0 and 6 | udp.Payload32[3]=0 and 7 | udp.Payload32[4]=0 and 8 | udp.Payload32[5]=0 and 9 | udp.Payload32[6]=0 and 10 | udp.Payload32[7]=0 and 11 | udp.Payload32[8]=0 and 12 | udp.Payload32[9]=0 and 13 | udp.Payload32[10]=0 and 14 | udp.Payload32[11]=0 and 15 | udp.Payload32[12]=0 and 16 | udp.Payload32[13]=0 and 17 | udp.Payload32[14]=0 and 18 | udp.Payload32[15]=0 and 19 | udp.Payload32[16]=0 and 20 | udp.Payload32[17]=0 -------------------------------------------------------------------------------- /common/linux_daemons.sh: -------------------------------------------------------------------------------- 1 | standard_mode_nfqws() 2 | { 3 | # $1 - 1 - run, 0 - stop 4 | local opt 5 | [ "$NFQWS2_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS2_OPT" && { 6 | opt="--qnum=$QNUM $NFQWS2_OPT" 7 | filter_apply_hostlist_target opt 8 | do_nfqws $1 1 "$opt" 9 | } 10 | } 11 | standard_mode_daemons() 12 | { 13 | # $1 - 1 - run, 0 - stop 14 | 15 | standard_mode_nfqws $1 16 | } 17 | zapret_do_daemons() 18 | { 19 | # $1 - 1 - run, 0 - stop 20 | 21 | standard_mode_daemons $1 22 | custom_runner zapret_custom_daemons $1 23 | 24 | return 0 25 | } 26 | zapret_run_daemons() 27 | { 28 | zapret_do_daemons 1 "$@" 29 | } 30 | zapret_stop_daemons() 31 | { 32 | zapret_do_daemons 0 "$@" 33 | } 34 | -------------------------------------------------------------------------------- /common/custom.sh: -------------------------------------------------------------------------------- 1 | custom_runner() 2 | { 3 | # $1 - function name 4 | # $2+ - params 5 | 6 | [ "$DISABLE_CUSTOM" = 1 ] && return 0 7 | 8 | local n script FUNC=$1 9 | 10 | shift 11 | 12 | [ -d "$CUSTOM_DIR/custom.d" ] && { 13 | dir_is_not_empty "$CUSTOM_DIR/custom.d" && { 14 | for script in "$CUSTOM_DIR/custom.d/"*; do 15 | [ -f "$script" ] || continue 16 | unset -f $FUNC 17 | . "$script" 18 | existf $FUNC && $FUNC "$@" 19 | done 20 | } 21 | } 22 | } 23 | 24 | alloc_qnum() 25 | { 26 | # $1 - target var name 27 | alloc_num NUMPOOL_QNUM $1 65300 65399 28 | } 29 | alloc_dnum() 30 | { 31 | # alloc daemon number 32 | # $1 - target var name 33 | alloc_num NUMPOOL_DNUM $1 2000 2999 34 | } 35 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/mdig/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | 3 | include $(TOPDIR)/rules.mk 4 | 5 | PKG_NAME:=mdig 6 | PKG_RELEASE:=1 7 | 8 | include $(INCLUDE_DIR)/package.mk 9 | 10 | define Package/mdig 11 | SECTION:=net 12 | CATEGORY:=Network 13 | TITLE:=mdig 14 | SUBMENU:=Zapret 15 | endef 16 | 17 | define Build/Prepare 18 | mkdir -p $(PKG_BUILD_DIR) 19 | $(CP) ./mdig/* $(PKG_BUILD_DIR)/ 20 | endef 21 | 22 | define Build/Compile 23 | $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) 24 | endef 25 | 26 | define Package/mdig/install 27 | $(INSTALL_DIR) $(1)/opt/zapret2/binaries/my 28 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret2/binaries/my 29 | endef 30 | 31 | $(eval $(call BuildPackage,mdig)) 32 | 33 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/ip2net/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | 3 | include $(TOPDIR)/rules.mk 4 | 5 | PKG_NAME:=ip2net 6 | PKG_RELEASE:=1 7 | 8 | include $(INCLUDE_DIR)/package.mk 9 | 10 | define Package/ip2net 11 | SECTION:=net 12 | CATEGORY:=Network 13 | TITLE:=ip2net 14 | SUBMENU:=Zapret 15 | endef 16 | 17 | define Build/Prepare 18 | mkdir -p $(PKG_BUILD_DIR) 19 | $(CP) ./ip2net/* $(PKG_BUILD_DIR)/ 20 | endef 21 | 22 | define Build/Compile 23 | $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) 24 | endef 25 | 26 | define Package/ip2net/install 27 | $(INSTALL_DIR) $(1)/opt/zapret2/binaries/my 28 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret2/binaries/my 29 | endef 30 | 31 | $(eval $(call BuildPackage,ip2net)) 32 | 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-warning.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: bugs 3 | about: do not write lame questions 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | Issues - это место для обращений к разработчику. 11 | Discussions - место для обсуждения вопросов между пользователями. 12 | 13 | Все, что выходит за рамки багов и технически грамотных предложений, идей, 14 | вопросы типа "как мне это запустить", "что нажать", "что вписать" - будет безжалостно удаляться. 15 | Идите в дискуссии, не захламляйте issues. 16 | 17 | Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions. 18 | There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions. 19 | -------------------------------------------------------------------------------- /blockcheck2.d/custom/README.txt: -------------------------------------------------------------------------------- 1 | Простой тестер стратегий по списку из файла. 2 | Скопируйте эту директорию под другим именем в blockcheck2.d, отредактируйте list файлы, впишите туда свои стратегии. 3 | В диалоге blockcheck2.sh выберите тест с названием вашей директории. 4 | Можно комментировать строки символом '#' в начале строки. 5 | Альтернативный путь до файлов стратегий можно задать переменными LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC. 6 | 7 | This is simple strategy tester from a file. 8 | Copy this folder, write your strategies into list files and select your test in blockcheck2 dialog. 9 | Lines can be commented using the '#' symbol at the line start. 10 | Strategy list files paths can be overriden in env variables : LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC. 11 | -------------------------------------------------------------------------------- /nfq2/hostlist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "pools.h" 5 | #include "params.h" 6 | 7 | bool AppendHostlistItem(hostlist_pool **hostlist, char *s); 8 | bool AppendHostList(hostlist_pool **hostlist, const char *filename); 9 | bool LoadAllHostLists(); 10 | bool NonEmptyHostlist(hostlist_pool **hostlist); 11 | // return : true = apply fooling, false = do not apply 12 | bool HostlistCheck(const struct desync_profile *dp,const char *host, bool no_match_subdomains, bool *excluded, bool bSkipReloadCheck); 13 | struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename); 14 | bool HostlistsReloadCheckForProfile(const struct desync_profile *dp); 15 | void HostlistsDebug(); 16 | 17 | #define ResetAllHostlistsModTime() hostlist_files_reset_modtime(¶ms.hostlists) 18 | -------------------------------------------------------------------------------- /init.d/pfsense/zapret2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # this file should be placed to /usr/local/etc/rc.d and chmod 755 4 | 5 | # copy 'lua' dir there 6 | ZDIR=/usr/local/etc/zapret2 7 | 8 | # prepare system 9 | 10 | kldload ipfw 11 | kldload ipdivert 12 | 13 | # for older pfsense versions. newer do not have these sysctls 14 | sysctl net.inet.ip.pfil.outbound=ipfw,pf 15 | sysctl net.inet.ip.pfil.inbound=ipfw,pf 16 | sysctl net.inet6.ip6.pfil.outbound=ipfw,pf 17 | sysctl net.inet6.ip6.pfil.inbound=ipfw,pf 18 | 19 | # required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state 20 | pfctl -d ; pfctl -e 21 | 22 | # add ipfw rules and start daemon 23 | 24 | ipfw delete 100 25 | ipfw add 100 divert 990 tcp from any to any 80,443 out not diverted not sockarg 26 | pkill ^dvtws2$ 27 | dvtws2 --daemon --port 990 --lua-init=@$ZDIR/zapret-lib.lua --lua-init=@$ZDIR/zapret-antidpi.lua --lua-desync=multisplit 28 | -------------------------------------------------------------------------------- /ipset/get_antizapret_domains.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | # useful in case ipban set is used in custom scripts 9 | FAIL= 10 | getipban || FAIL=1 11 | "$IPSET_DIR/create_ipset.sh" 12 | [ -n "$FAIL" ] && exit 13 | 14 | ZURL=https://antizapret.prostovpn.org:8443/domains-export.txt 15 | ZDOM="$TMPDIR/zapret.txt" 16 | 17 | 18 | curl -H "Accept-Encoding: gzip" -k --fail --max-time 600 --connect-timeout 5 --retry 3 --max-filesize 251658240 "$ZURL" | gunzip - >"$ZDOM" || 19 | { 20 | echo domain list download failed 21 | exit 2 22 | } 23 | 24 | dlsize=$(LC_ALL=C LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ') 25 | if test $dlsize -lt 102400; then 26 | echo list file is too small. can be bad. 27 | exit 2 28 | fi 29 | 30 | sort -u "$ZDOM" | zz "$ZHOSTLIST" 31 | 32 | rm -f "$ZDOM" 33 | 34 | hup_zapret_daemons 35 | 36 | exit 0 37 | -------------------------------------------------------------------------------- /nfq2/BSDmakefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | OPTIMIZE ?= -Os 3 | CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member 4 | LIBS = -lz -lm 5 | SRC_FILES = *.c crypto/*.c 6 | 7 | LUA_JIT ?= 1 8 | 9 | .if "${LUA_JIT}" == "1" 10 | 11 | LUAJIT_VER?=2.1 12 | LUA_VER?=5.1 13 | LUA_PKG:=luajit 14 | 15 | .else 16 | 17 | LUA_VER ?= 5.4 18 | LUA_VER_UNDOTTED!= echo $(LUA_VER) | sed 's/\.//g' 19 | 20 | OSNAME!=uname 21 | .if ${OSNAME} == "OpenBSD" 22 | LUA_PKG ?= lua$(LUA_VER_UNDOTTED) 23 | .elif ${OSNAME} == "FreeBSD" 24 | LUA_PKG ?= lua-$(LUA_VER) 25 | .endif 26 | 27 | .endif 28 | 29 | LUA_LIB!= pkg-config --libs $(LUA_PKG) 30 | LUA_CFLAGS!= pkg-config --cflags $(LUA_PKG) 31 | 32 | .if "${LUA_JIT}" == "1" 33 | LUA_CFLAGS+=-DLUAJIT 34 | .endif 35 | 36 | all: dvtws2 37 | 38 | dvtws2: $(SRC_FILES) 39 | $(CC) $(CFLAGS) $(LUA_CFLAGS) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LDFLAGS) 40 | 41 | clean: 42 | rm -f dvtws2 43 | -------------------------------------------------------------------------------- /nfq2/crypto/sha-private.h: -------------------------------------------------------------------------------- 1 | /************************ sha-private.h ************************/ 2 | /***************** See RFC 6234 for details. *******************/ 3 | #pragma once 4 | /* 5 | * These definitions are defined in FIPS 180-3, section 4.1. 6 | * Ch() and Maj() are defined identically in sections 4.1.1, 7 | * 4.1.2, and 4.1.3. 8 | * 9 | * The definitions used in FIPS 180-3 are as follows: 10 | */ 11 | 12 | #ifndef USE_MODIFIED_MACROS 13 | #define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 14 | #define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 15 | #else /* USE_MODIFIED_MACROS */ 16 | /* 17 | * The following definitions are equivalent and potentially faster. 18 | */ 19 | 20 | #define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z)) 21 | #define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z))) 22 | 23 | #endif /* USE_MODIFIED_MACROS */ 24 | 25 | #define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z)) 26 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/10-keenetic-udp-fix: -------------------------------------------------------------------------------- 1 | # This script fixes keenetic issue with nfqws generated udp packets 2 | # Keenetic uses proprietary ndmmark and does not masquerade without this mark 3 | # If not masqueraded packets go to WAN with LAN IP and get dropped by ISP 4 | 5 | # It's advised to set IFACE_WAN in config 6 | 7 | zapret_custom_firewall() 8 | { 9 | # $1 - 1 - add, 0 - stop 10 | 11 | local wan wanif rule 12 | 13 | [ "$DISABLE_IPV4" = "1" ] || { 14 | # use IFACE_WAN if defined. if not - search for interfaces with default route. 15 | wanif=${IFACE_WAN:-$(sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs)} 16 | for wan in $wanif; do 17 | rule="-o $wan -p udp -m mark --mark $DESYNC_MARK/$DESYNC_MARK" 18 | ipt_print_op $1 "$rule" "keenetic udp fix" 19 | ipt_add_del $1 POSTROUTING -t nat $rule -j MASQUERADE 20 | done 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ipset/get_refilter_ipsum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | TMPLIST="$TMPDIR/list.txt" 9 | 10 | URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/ipsum.lst" 11 | 12 | dl() 13 | { 14 | # $1 - url 15 | # $2 - file 16 | # $3 - minsize 17 | # $4 - maxsize 18 | curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" || 19 | { 20 | echo list download failed : $1 21 | exit 2 22 | } 23 | dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') 24 | if test $dlsize -lt $3; then 25 | echo list is too small : $dlsize bytes. can be bad. 26 | exit 2 27 | fi 28 | zzcopy "$TMPLIST" "$2" 29 | rm -f "$TMPLIST" 30 | } 31 | 32 | getuser && { 33 | [ "$DISABLE_IPV4" != "1" ] && { 34 | dl "$URL" "$ZIPLIST" 32768 4194304 35 | } 36 | } 37 | 38 | "$IPSET_DIR/create_ipset.sh" 39 | -------------------------------------------------------------------------------- /ip2net/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | OPTIMIZE ?= -Os 3 | CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto 4 | CFLAGS_BSD = -Wno-address-of-packed-member 5 | CFLAGS_WIN = -static 6 | LIBS = 7 | LIBS_WIN = -lws2_32 8 | SRC_FILES = ip2net.c qsort.c 9 | 10 | all: ip2net 11 | 12 | ip2net: $(SRC_FILES) 13 | $(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS) 14 | 15 | systemd: ip2net 16 | 17 | android: ip2net 18 | 19 | bsd: $(SRC_FILES) 20 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS) 21 | 22 | mac: $(SRC_FILES) 23 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2neta $(SRC_FILES) -target arm64-apple-macos10.8 $(LIBS) $(LDFLAGS) 24 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2netx $(SRC_FILES) -target x86_64-apple-macos10.8 $(LIBS) $(LDFLAGS) 25 | strip ip2neta ip2netx 26 | lipo -create -output ip2net ip2netx ip2neta 27 | rm -f ip2netx ip2neta 28 | 29 | win: $(SRC_FILES) 30 | $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o ip2net $(SRC_FILES) $(LIBS_WIN) $(LDFLAGS) 31 | 32 | clean: 33 | rm -f ip2net *.o 34 | -------------------------------------------------------------------------------- /files/fake/zero_1024.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mdig/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | OPTIMIZE ?= -Os 3 | CFLAGS += -std=gnu99 $(OPTIMIZE) 4 | CFLAGS_BSD = -Wno-address-of-packed-member 5 | CFLAGS_WIN = -static 6 | LIBS = -lpthread 7 | LIBS_ANDROID = 8 | LIBS_WIN = -lws2_32 9 | SRC_FILES = *.c 10 | 11 | all: mdig 12 | 13 | mdig: $(SRC_FILES) 14 | $(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS) 15 | 16 | systemd: mdig 17 | 18 | android: $(SRC_FILES) 19 | $(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS) 20 | 21 | bsd: $(SRC_FILES) 22 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS) 23 | 24 | mac: $(SRC_FILES) 25 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdiga $(SRC_FILES) -target arm64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) 26 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdigx $(SRC_FILES) -target x86_64-apple-macos10.8 $(LIBS_BSD) $(LDFLAGS) 27 | strip mdiga mdigx 28 | lipo -create -output mdig mdigx mdiga 29 | rm -f mdigx mdiga 30 | 31 | win: $(SRC_FILES) 32 | $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o mdig $(SRC_FILES) $(LIBS_WIN) $(LDFLAGS) 33 | 34 | clean: 35 | rm -f mdig *.o 36 | -------------------------------------------------------------------------------- /ipset/get_refilter_domains.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | TMPLIST="$TMPDIR/list.txt" 9 | 10 | URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/domains_all.lst" 11 | 12 | dl() 13 | { 14 | # $1 - url 15 | # $2 - file 16 | # $3 - minsize 17 | # $4 - maxsize 18 | curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" || 19 | { 20 | echo list download failed : $1 21 | exit 2 22 | } 23 | dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') 24 | if test $dlsize -lt $3; then 25 | echo list is too small : $dlsize bytes. can be bad. 26 | exit 2 27 | fi 28 | zzcopy "$TMPLIST" "$2" 29 | rm -f "$TMPLIST" 30 | } 31 | 32 | # useful in case ipban set is used in custom scripts 33 | FAIL= 34 | getipban || FAIL=1 35 | "$IPSET_DIR/create_ipset.sh" 36 | [ -n "$FAIL" ] && exit 37 | 38 | dl "$URL" "$ZHOSTLIST" 32768 4194304 39 | 40 | hup_zapret_daemons 41 | 42 | exit 0 43 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/50-quic4all: -------------------------------------------------------------------------------- 1 | # this custom script runs desync to all IETF QUIC initials 2 | # NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22) 3 | 4 | # can override in config : 5 | NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}" 6 | 7 | alloc_dnum DNUM_QUIC4ALL 8 | alloc_qnum QNUM_QUIC4ALL 9 | 10 | zapret_custom_daemons() 11 | { 12 | # $1 - 1 - add, 0 - stop 13 | 14 | local opt="--qnum=$QNUM_QUIC4ALL $NFQWS_OPT_DESYNC_QUIC" 15 | do_nfqws $1 $DNUM_QUIC4ALL "$opt" 16 | } 17 | zapret_custom_firewall() 18 | { 19 | # $1 - 1 - run, 0 - stop 20 | 21 | local f='-p udp -m u32 --u32' 22 | fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=264:65535&&0>>22&0x3C@8>>28=0xC&&0>>22&0x3C@9=0x00000001" "$f 44>>16=264:65535&&48>>28=0xC&&49=0x00000001" $QNUM_QUIC4ALL 23 | } 24 | zapret_custom_firewall_nft() 25 | { 26 | # stop logic is not required 27 | 28 | local f="udp length >= 264 @ih,0,4 0xC @ih,8,32 0x00000001" 29 | nft_fw_nfqws_post "$f" "$f" $QNUM_QUIC4ALL 30 | } 31 | -------------------------------------------------------------------------------- /common/virt.sh: -------------------------------------------------------------------------------- 1 | get_virt() 2 | { 3 | local vm s v UNAME 4 | UNAME=$(uname) 5 | case "$UNAME" in 6 | Linux) 7 | if exists systemd-detect-virt; then 8 | vm=$(systemd-detect-virt --vm) 9 | elif [ -f /sys/class/dmi/id/product_name ]; then 10 | read s >22&0x3C@4>>16=28:65535&&0>>22&0x3C@12=0x2112A442&&0>>22&0x3C@8&0xC0000003=0" "$f 44>>16=28:65535&&52=0x2112A442&&48&0xC0000003=0" $QNUM_STUN4ALL 23 | } 24 | zapret_custom_firewall_nft() 25 | { 26 | # stop logic is not required 27 | 28 | local f="udp length >= 28 @ih,32,32 0x2112A442 @ih,0,2 0 @ih,30,2 0" 29 | nft_fw_nfqws_post "$f" "$f" $QNUM_STUN4ALL 30 | } 31 | -------------------------------------------------------------------------------- /docs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016-2025 bol-van 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /nfq2/packet_queue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "conntrack_base.h" 10 | 11 | struct rawpacket 12 | { 13 | struct sockaddr_storage dst; 14 | char ifin[IFNAMSIZ], ifout[IFNAMSIZ]; 15 | uint32_t fwmark_orig; 16 | uint32_t fwmark; 17 | size_t len, len_payload; 18 | uint8_t *packet; 19 | t_ctrack_positions tpos; 20 | bool tpos_present; 21 | TAILQ_ENTRY(rawpacket) next; 22 | }; 23 | TAILQ_HEAD(rawpacket_tailhead, rawpacket); 24 | 25 | void rawpacket_queue_init(struct rawpacket_tailhead *q); 26 | void rawpacket_queue_destroy(struct rawpacket_tailhead *q); 27 | bool rawpacket_queue_empty(const struct rawpacket_tailhead *q); 28 | unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q); 29 | struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos); 30 | struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q); 31 | void rawpacket_free(struct rawpacket *rp); 32 | -------------------------------------------------------------------------------- /.github/workflows/libnetfilter_queue-android.patch: -------------------------------------------------------------------------------- 1 | --- a/src/extra/pktbuff.c 2 | +++ b/src/extra/pktbuff.c 3 | @@ -14,7 +14,7 @@ 4 | #include /* for memcpy */ 5 | #include 6 | 7 | -#include 8 | +#include 9 | #include 10 | #include 11 | 12 | --- a/src/nlmsg.c 13 | +++ b/src/nlmsg.c 14 | @@ -21,7 +21,7 @@ 15 | 16 | #include 17 | 18 | -#include 19 | +// #include 20 | 21 | #include "internal.h" 22 | 23 | --- a/src/extra/tcp.c 24 | +++ b/src/extra/tcp.c 25 | @@ -139,12 +139,16 @@ void nfq_tcp_compute_checksum_ipv6(struc 26 | * (union is compatible to any of its members) 27 | * This means this part of the code is -fstrict-aliasing safe now. 28 | */ 29 | +#ifndef __ANDROID__ 30 | union tcp_word_hdr { 31 | struct tcphdr hdr; 32 | uint32_t words[5]; 33 | }; 34 | +#endif 35 | 36 | +#ifndef tcp_flag_word 37 | #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words[3]) 38 | +#endif 39 | 40 | /** 41 | * nfq_pkt_snprintf_tcp_hdr - print tcp header into one buffer in a humnan 42 | -------------------------------------------------------------------------------- /init.d/openwrt/90-zapret2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ZAPRET=/etc/init.d/zapret2 4 | 5 | check_lan() 6 | { 7 | IS_LAN= 8 | [ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan 9 | for lan in $OPENWRT_LAN; do 10 | [ "$INTERFACE" = "$lan" ] && { 11 | IS_LAN=1 12 | break 13 | } 14 | done 15 | } 16 | 17 | 18 | [ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && { 19 | SCRIPT=$(readlink "$ZAPRET") 20 | if [ -n "$SCRIPT" ]; then 21 | EXEDIR=$(dirname "$SCRIPT") 22 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 23 | else 24 | ZAPRET_BASE=/opt/zapret2 25 | fi 26 | ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"} 27 | ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} 28 | CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt" 29 | . "$ZAPRET_CONFIG" 30 | . "$ZAPRET_BASE/common/base.sh" 31 | . "$ZAPRET_BASE/common/fwtype.sh" 32 | 33 | linux_fwtype 34 | case "$FWTYPE" in 35 | nftables) 36 | logger -t zapret reloading nftables ifsets due to $ACTION of $INTERFACE 37 | "$ZAPRET" reload_ifsets 38 | ;; 39 | iptables) 40 | openwrt_fw3 || { 41 | logger -t zapret reloading iptables due to $ACTION of $INTERFACE 42 | "$ZAPRET" restart_fw 43 | } 44 | ;; 45 | esac 46 | } 47 | -------------------------------------------------------------------------------- /common/fwtype.sh: -------------------------------------------------------------------------------- 1 | linux_ipt_avail() 2 | { 3 | exists iptables && exists ip6tables 4 | } 5 | linux_maybe_iptables_fwtype() 6 | { 7 | linux_ipt_avail && FWTYPE=iptables 8 | } 9 | linux_nft_avail() 10 | { 11 | exists nft 12 | } 13 | linux_fwtype() 14 | { 15 | [ -n "$FWTYPE" ] && return 16 | 17 | FWTYPE=unsupported 18 | 19 | linux_get_subsys 20 | if [ "$SUBSYS" = openwrt ] ; then 21 | # linux kernel is new enough if fw4 is there 22 | if [ -x /sbin/fw4 ] && linux_nft_avail ; then 23 | FWTYPE=nftables 24 | else 25 | linux_maybe_iptables_fwtype 26 | fi 27 | else 28 | SUBSYS= 29 | # generic linux 30 | # flowtable is implemented since kernel 4.16 31 | if linux_nft_avail && linux_min_version 4 16; then 32 | FWTYPE=nftables 33 | else 34 | linux_maybe_iptables_fwtype 35 | fi 36 | fi 37 | 38 | export FWTYPE 39 | } 40 | 41 | get_fwtype() 42 | { 43 | [ -n "$FWTYPE" ] && return 44 | 45 | local UNAME="$(uname)" 46 | 47 | case "$UNAME" in 48 | Linux) 49 | linux_fwtype 50 | ;; 51 | FreeBSD) 52 | if exists ipfw ; then 53 | FWTYPE=ipfw 54 | else 55 | FWTYPE=unsupported 56 | fi 57 | ;; 58 | *) 59 | FWTYPE=unsupported 60 | ;; 61 | esac 62 | 63 | export FWTYPE 64 | } 65 | -------------------------------------------------------------------------------- /docs/compile/build_howto_windows.txt: -------------------------------------------------------------------------------- 1 | Windows x64 2 | 3 | 1) Download latest cygwin for windows 7 4 | 5 | curl -O https://www.cygwin.com/setup-x86_64.exe 6 | setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215 7 | 8 | 2) During setup install packages : make gcc-core zlib-devel 9 | 10 | 3) Run Cygwin.bat 11 | 12 | 4) install and compile luajit from here : https://github.com/openresty/luajit2 13 | 14 | download latest releast, unpack, cd to it's directory 15 | 16 | make BUILDMODE=static CFLAGS="-Os" 17 | make install 18 | 19 | 5) cd to %ZAPRET_BASE%/nfq2 20 | 21 | cd C:/Users/user/Downloads/zapret2/nfq2 22 | 23 | 6) Compile nfqws2 24 | 25 | make cygwin64 26 | 27 | use winws2.exe 28 | 29 | 7) Take windivert.dll and windivert64.sys here : https://reqrypt.org/download 30 | Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7. 31 | 32 | 8) Copy cygwin1.dll, winws2.exe, windivert.dll and windivert64.sys to one folder. 33 | 34 | 9) Run winws2.exe from cmd.exe running as administrator. 35 | winws will not run from cygwin shell with cygwin1.dll copy in it's folder. 36 | winws will not run without cygwin1.dll outside of cygwin shell. 37 | -------------------------------------------------------------------------------- /init.d/windivert.filter.examples/README.txt: -------------------------------------------------------------------------------- 1 | Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws. 2 | Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp. 3 | Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики. 4 | Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку. 5 | Дофильтрация производится силами winws. 6 | 7 | Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language 8 | Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake` 9 | 10 | 11 | These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp. 12 | Filters are kernel mode and save great amount of CPU. 13 | However windivert cannot filter by bit fields, lacks shift and bitwise logic operations. 14 | Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws. 15 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/15-misc.sh: -------------------------------------------------------------------------------- 1 | . "$TESTDIR/def.inc" 2 | 3 | pktws_check_http() 4 | { 5 | # $1 - test function 6 | # $2 - domain 7 | 8 | local PAYLOAD="--payload http_req" repeats ok 9 | 10 | for repeats in 1 20 100 260; do 11 | # send starting bytes of original payload 12 | pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,method+2:ip_id=rnd:repeats=$repeats && ok=1 13 | pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=$repeats && ok=1 14 | [ "$ok" = 1 -a "$SCANLEVEL" != force ] && break 15 | done 16 | } 17 | 18 | pktws_check_https_tls12() 19 | { 20 | # $1 - test function 21 | # $2 - domain 22 | 23 | local PAYLOAD="--payload tls_client_hello" repeats ok 24 | 25 | for repeats in 1 20 100 260; do 26 | # send starting bytes of original payload 27 | pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,1:ip_id=rnd:repeats=$repeats && ok=1 28 | pktws_curl_test_update "$1" "$2" $PAYLOAD --lua-desync=tcpseg:pos=0,midsld:ip_id=rnd:repeats=$repeats && ok=1 29 | [ "$ok" = 1 -a "$SCANLEVEL" != force ] && break 30 | done 31 | } 32 | 33 | pktws_check_https_tls13() 34 | { 35 | # $1 - test function 36 | # $2 - domain 37 | pktws_check_https_tls12 "$1" "$2" 38 | } 39 | -------------------------------------------------------------------------------- /ipset/get_reestr_resolvable_domains.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | TMPLIST="$TMPDIR/list_nethub.txt" 9 | 10 | BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main" 11 | URL="$BASEURL/reestr_hostname_resolvable.txt" 12 | IPB4="$BASEURL/reestr_ipban4.txt" 13 | IPB6="$BASEURL/reestr_ipban6.txt" 14 | 15 | dl() 16 | { 17 | # $1 - url 18 | # $2 - file 19 | # $3 - minsize 20 | # $4 - maxsize 21 | curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" || 22 | { 23 | echo list download failed : $1 24 | exit 2 25 | } 26 | dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') 27 | if test $dlsize -lt $3; then 28 | echo list is too small : $dlsize bytes. can be bad. 29 | exit 2 30 | fi 31 | zzcopy "$TMPLIST" "$2" 32 | rm -f "$TMPLIST" 33 | } 34 | 35 | dl "$URL" "$ZHOSTLIST" 65536 67108864 36 | 37 | hup_zapret_daemons 38 | 39 | [ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576 40 | [ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576 41 | 42 | getipban 43 | "$IPSET_DIR/create_ipset.sh" 44 | 45 | exit 0 46 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/50-wg4all: -------------------------------------------------------------------------------- 1 | # this custom script runs desync to all wireguard handshake initiation packets 2 | # NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray 3 | # NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22) 4 | 5 | # can override in config : 6 | NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}" 7 | 8 | alloc_dnum DNUM_WG4ALL 9 | alloc_qnum QNUM_WG4ALL 10 | 11 | zapret_custom_daemons() 12 | { 13 | # $1 - 1 - add, 0 - stop 14 | 15 | local opt="--qnum=$QNUM_WG4ALL $NFQWS_OPT_DESYNC_WG" 16 | do_nfqws $1 $DNUM_WG4ALL "$opt" 17 | } 18 | # size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000 19 | zapret_custom_firewall() 20 | { 21 | # $1 - 1 - run, 0 - stop 22 | 23 | local f='-p udp -m u32 --u32' 24 | fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $QNUM_WG4ALL 25 | } 26 | zapret_custom_firewall_nft() 27 | { 28 | # stop logic is not required 29 | 30 | local f="udp length 156 @ih,0,32 0x01000000" 31 | nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL 32 | } 33 | -------------------------------------------------------------------------------- /install_prereq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # install prerequisites 4 | 5 | EXEDIR="$(dirname "$0")" 6 | EXEDIR="$(cd "$EXEDIR"; pwd)" 7 | ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"} 8 | ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"} 9 | ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} 10 | ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default" 11 | 12 | [ -f "$ZAPRET_CONFIG" ] || { 13 | ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")" 14 | [ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR" 15 | cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG" 16 | } 17 | 18 | . "$ZAPRET_CONFIG" 19 | . "$ZAPRET_BASE/common/base.sh" 20 | . "$ZAPRET_BASE/common/elevate.sh" 21 | . "$ZAPRET_BASE/common/fwtype.sh" 22 | . "$ZAPRET_BASE/common/dialog.sh" 23 | . "$ZAPRET_BASE/common/installer.sh" 24 | . "$ZAPRET_BASE/common/ipt.sh" 25 | 26 | umask 0022 27 | fix_sbin_path 28 | fsleep_setup 29 | check_system accept_unknown_rc 30 | [ $UNAME = "Linux" ] || { 31 | echo no prerequisites required for $UNAME 32 | exitp 0 33 | } 34 | require_root 35 | 36 | case $UNAME in 37 | Linux) 38 | select_fwtype 39 | case $SYSTEM in 40 | openwrt) 41 | select_ipv6 42 | check_prerequisites_openwrt 43 | ;; 44 | *) 45 | check_prerequisites_linux 46 | ;; 47 | esac 48 | ;; 49 | esac 50 | 51 | exitp 0 52 | -------------------------------------------------------------------------------- /blockcheck2.d/custom/10-list.sh: -------------------------------------------------------------------------------- 1 | LIST_HTTP="${LIST_HTTP:-$TESTDIR/list_http.txt}" 2 | LIST_HTTPS_TLS12="${LIST_HTTPS_TLS12:-$TESTDIR/list_https_tls12.txt}" 3 | LIST_HTTPS_TLS13="${LIST_HTTPS_TLS13:-$TESTDIR/list_https_tls13.txt}" 4 | LIST_QUIC="${LIST_QUIC:-$TESTDIR/list_quic.txt}" 5 | 6 | check_list() 7 | { 8 | # $1 - test function 9 | # $2 - domain 10 | # $3 - file 11 | 12 | local line ok=0 13 | [ -f "$3" ] || { 14 | echo "no strategy file '$3'" 15 | return 1 16 | } 17 | while IFS= read -r line; do 18 | case "$line" in 19 | ""|\#*) continue ;; 20 | esac 21 | line=$(echo "$line" | tr -d "\r\n") 22 | eval pktws_curl_test_update "$1" "$2" $line && ok=1 23 | done < "$3" 24 | 25 | [ "$ok" = 1 ] 26 | } 27 | 28 | pktws_check_http() 29 | { 30 | # $1 - test function 31 | # $2 - domain 32 | 33 | check_list "$1" "$2" "$LIST_HTTP" 34 | } 35 | 36 | pktws_check_https_tls12() 37 | { 38 | # $1 - test function 39 | # $2 - domain 40 | 41 | check_list "$1" "$2" "$LIST_HTTPS_TLS12" 42 | } 43 | 44 | pktws_check_https_tls13() 45 | { 46 | # $1 - test function 47 | # $2 - domain 48 | 49 | check_list "$1" "$2" "$LIST_HTTPS_TLS13" 50 | } 51 | 52 | pktws_check_http3() 53 | { 54 | # $1 - test function 55 | # $2 - domain 56 | 57 | check_list "$1" "$2" "$LIST_QUIC" 58 | } 59 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/nfqws2/Makefile: -------------------------------------------------------------------------------- 1 | include $(TOPDIR)/rules.mk 2 | 3 | PKG_NAME:=nfqws2 4 | PKG_RELEASE:=1 5 | 6 | LUA_JIT?=1 7 | 8 | ifeq ($(LUA_JIT),1) 9 | LUAJIT_VER?=2.1 10 | LUA_VER?=5.1 11 | LUA_DEP:=luajit 12 | #LUA_DEP:=luajit2 13 | LUA_INCLUDE:=-I$(STAGING_DIR)/usr/include/luajit-$(LUAJIT_VER) 14 | LUA_LIBRARY:=-L$(STAGING_DIR)/usr/lib -lluajit-$(LUA_VER) 15 | else 16 | LUA_VER?=5.3 17 | LUA_DEP:=lua$(LUA_VER) 18 | LUA_INCLUDE:=-I$(STAGING_DIR)/usr/include/lua$(LUA_VER) 19 | LUA_LIBRARY:=-L$(STAGING_DIR)/usr/lib -llua$(LUA_VER) 20 | endif 21 | 22 | include $(INCLUDE_DIR)/package.mk 23 | 24 | define Package/nfqws2 25 | SECTION:=net 26 | CATEGORY:=Network 27 | TITLE:=nfqws2 28 | SUBMENU:=Zapret 29 | DEPENDS:=+libnetfilter-queue +lmnl +libcap +zlib +$(LUA_DEP) 30 | endef 31 | 32 | define Build/Prepare 33 | mkdir -p $(PKG_BUILD_DIR) 34 | $(CP) ./nfq2/* $(PKG_BUILD_DIR)/ 35 | endef 36 | 37 | define Build/Compile 38 | $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) LUA_CFLAGS="$(LUA_INCLUDE)" LUA_LIB="$(LUA_LIBRARY)" 39 | endef 40 | 41 | define Package/nfqws2/install 42 | $(INSTALL_DIR) $(1)/opt/zapret2/binaries/my 43 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws2 $(1)/opt/zapret2/binaries/my 44 | endef 45 | 46 | $(eval $(call BuildPackage,nfqws2)) 47 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/90-quic.sh: -------------------------------------------------------------------------------- 1 | . "$TESTDIR/def.inc" 2 | 3 | pktws_check_http3() 4 | { 5 | # $1 - test function 6 | # $2 - domain 7 | 8 | [ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; } 9 | 10 | local repeats fake pos fool 11 | local PAYLOAD="--payload quic_initial" 12 | 13 | if [ -n "$FAKE_QUIC" ]; then 14 | fake=fake_quic 15 | else 16 | fake=fake_default_quic 17 | fi 18 | 19 | for repeats in 1 2 5 10 20; do 20 | pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break 21 | done 22 | 23 | [ "$IPV" = 6 ] && { 24 | for fool in ip6_hopbyhop ip6_destopt ip6_hopbyhop:ip6_destopt; do 25 | pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:$fool --lua-desync=drop 26 | done 27 | } 28 | 29 | for pos in 8 16 32 64; do 30 | pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break 31 | done 32 | 33 | for pos in 8 16 32 64; do 34 | pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$FAKE_REPEATS --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break 35 | done 36 | } 37 | -------------------------------------------------------------------------------- /ipset/get_reestr_preresolved.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | TMPLIST="$TMPDIR/list.txt" 9 | 10 | BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main" 11 | URL4="$BASEURL/reestr_resolved4.txt" 12 | URL6="$BASEURL/reestr_resolved6.txt" 13 | IPB4="$BASEURL/reestr_ipban4.txt" 14 | IPB6="$BASEURL/reestr_ipban6.txt" 15 | 16 | dl() 17 | { 18 | # $1 - url 19 | # $2 - file 20 | # $3 - minsize 21 | # $4 - maxsize 22 | curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" || 23 | { 24 | echo list download failed : $1 25 | exit 2 26 | } 27 | dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') 28 | if test $dlsize -lt $3; then 29 | echo list is too small : $dlsize bytes. can be bad. 30 | exit 2 31 | fi 32 | zzcopy "$TMPLIST" "$2" 33 | rm -f "$TMPLIST" 34 | } 35 | 36 | getuser && { 37 | [ "$DISABLE_IPV4" != "1" ] && { 38 | dl "$URL4" "$ZIPLIST" 32768 4194304 39 | dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576 40 | } 41 | [ "$DISABLE_IPV6" != "1" ] && { 42 | dl "$URL6" "$ZIPLIST6" 8192 4194304 43 | dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576 44 | } 45 | } 46 | 47 | "$IPSET_DIR/create_ipset.sh" 48 | -------------------------------------------------------------------------------- /ipset/get_reestr_preresolved_smart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | TMPLIST="$TMPDIR/list.txt" 9 | 10 | BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main" 11 | URL4="$BASEURL/reestr_smart4.txt" 12 | URL6="$BASEURL/reestr_smart6.txt" 13 | IPB4="$BASEURL/reestr_ipban4.txt" 14 | IPB6="$BASEURL/reestr_ipban6.txt" 15 | 16 | dl() 17 | { 18 | # $1 - url 19 | # $2 - file 20 | # $3 - minsize 21 | # $4 - maxsize 22 | curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" || 23 | { 24 | echo list download failed : $1 25 | exit 2 26 | } 27 | dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ') 28 | if test $dlsize -lt $3; then 29 | echo list is too small : $dlsize bytes. can be bad. 30 | exit 2 31 | fi 32 | zzcopy "$TMPLIST" "$2" 33 | rm -f "$TMPLIST" 34 | } 35 | 36 | getuser && { 37 | [ "$DISABLE_IPV4" != "1" ] && { 38 | dl "$URL4" "$ZIPLIST" 32768 4194304 39 | dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576 40 | } 41 | [ "$DISABLE_IPV6" != "1" ] && { 42 | dl "$URL6" "$ZIPLIST6" 8192 4194304 43 | dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576 44 | } 45 | } 46 | 47 | "$IPSET_DIR/create_ipset.sh" 48 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/50-dht4all: -------------------------------------------------------------------------------- 1 | # this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering 2 | # NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22) 3 | 4 | # can override in config : 5 | NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}" 6 | 7 | alloc_dnum DNUM_DHT4ALL 8 | alloc_qnum QNUM_DHT4ALL 9 | 10 | zapret_custom_daemons() 11 | { 12 | # $1 - 1 - add, 0 - stop 13 | 14 | local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT" 15 | do_nfqws $1 $DNUM_DHT4ALL "$opt" 16 | } 17 | zapret_custom_firewall() 18 | { 19 | # $1 - 1 - run, 0 - stop 20 | 21 | local f uf4 uf6 22 | local first_packet_only="$ipt_connbytes 1:1" 23 | 24 | f='-p udp -m length --length 109:407 -m u32 --u32' 25 | uf4='0>>22&0x3C@8>>16=0x6431' 26 | uf6='48>>16=0x6431' 27 | fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL 28 | } 29 | zapret_custom_firewall_nft() 30 | { 31 | # stop logic is not required 32 | 33 | local f 34 | local first_packet_only="$nft_connbytes 1" 35 | 36 | f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431" 37 | nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL 38 | } 39 | -------------------------------------------------------------------------------- /nfq2/checksum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define __FAVOR_BSD 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | uint16_t csum_partial(const void *buff, size_t len); 15 | uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum); 16 | uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum); 17 | 18 | uint16_t ip4_compute_csum(const void *buff, size_t len); 19 | void ip4_fix_checksum(struct ip *ip); 20 | 21 | void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr); 22 | void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr); 23 | void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr); 24 | 25 | void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr); 26 | void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr); 27 | void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr); 28 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/40-webserver: -------------------------------------------------------------------------------- 1 | # this custom script runs nfqws2 in server mode for typical webserver 2 | 3 | WEBSERVER_DEFAULT_STRATEGY=" 4 | --server 5 | --payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit 6 | --payload empty --lua-desync=synack_split" 7 | 8 | # can override in config : 9 | NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}" 10 | WEBSERVER_PORTS="${WEBSERVER_PORTS:-80,443}" 11 | WEBSERVER_PKT_OUT="${WEBSERVER_PKT_OUT:-15}" 12 | 13 | alloc_dnum DNUM_WEBSERVER 14 | alloc_qnum QNUM_WEBSERVER 15 | 16 | zapret_custom_daemons() 17 | { 18 | # $1 - 1 - add, 0 - stop 19 | 20 | local opt="--qnum=$QNUM_WEBSERVER $NFQWS_OPT_DESYNC_WEBSERVER" 21 | do_nfqws $1 $DNUM_WEBSERVER "$opt" 22 | } 23 | zapret_custom_firewall() 24 | { 25 | # $1 - 1 - run, 0 - stop 26 | 27 | local PORTS=$(replace_char - : $WEBSERVER_PORTS) 28 | local first_packets=$(ipt_first_packets $WEBSERVER_PKT_OUT) 29 | local f="-p tcp -m multiport --sports $PORTS $first_packets" 30 | fw_nfqws_post $1 "$f" "$f" $QNUM_WEBSERVER 31 | } 32 | zapret_custom_firewall_nft() 33 | { 34 | # stop logic is not required 35 | 36 | local first_packets=$(nft_first_packets $WEBSERVER_PKT_OUT) 37 | local f="tcp sport {$WEBSERVER_PORTS} $first_packets" 38 | nft_fw_nfqws_post "$f" "$f" $QNUM_WEBSERVER 39 | } 40 | -------------------------------------------------------------------------------- /common/dialog.sh: -------------------------------------------------------------------------------- 1 | read_yes_no() 2 | { 3 | # $1 - default (Y/N) 4 | local A 5 | read A 6 | [ -z "$A" ] || ([ "$A" != "Y" ] && [ "$A" != "y" ] && [ "$A" != "N" ] && [ "$A" != "n" ]) && A=$1 7 | [ "$A" = "Y" ] || [ "$A" = "y" ] || [ "$A" = "1" ] 8 | } 9 | ask_yes_no() 10 | { 11 | # $1 - default (Y/N or 0/1) 12 | # $2 - text 13 | local DEFAULT=$1 14 | [ "$1" = "1" ] && DEFAULT=Y 15 | [ "$1" = "0" ] && DEFAULT=N 16 | [ -z "$DEFAULT" ] && DEFAULT=N 17 | printf "$2 (default : $DEFAULT) (Y/N) ? " 18 | read_yes_no $DEFAULT 19 | } 20 | ask_yes_no_var() 21 | { 22 | # $1 - variable name for answer : 0/1 23 | # $2 - text 24 | local DEFAULT 25 | eval DEFAULT="\$$1" 26 | if ask_yes_no "$DEFAULT" "$2"; then 27 | eval $1=1 28 | else 29 | eval $1=0 30 | fi 31 | } 32 | ask_list() 33 | { 34 | # $1 - mode var 35 | # $2 - space separated value list 36 | # $3 - (optional) default value 37 | local M_DEFAULT 38 | eval M_DEFAULT="\$$1" 39 | local M_ALL=$M_DEFAULT 40 | local M="" 41 | local m 42 | 43 | [ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;} 44 | 45 | n=1 46 | for m in $2; do 47 | echo $n : $m 48 | n=$(($n+1)) 49 | done 50 | printf "your choice (default : $M_DEFAULT) : " 51 | read m 52 | [ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null) 53 | [ -z "$M" ] && M="$M_DEFAULT" 54 | echo selected : $M 55 | eval $1="\"$M\"" 56 | 57 | [ "$M" != "$M_OLD" ] 58 | } 59 | -------------------------------------------------------------------------------- /common/linux_fw.sh: -------------------------------------------------------------------------------- 1 | set_conntrack_liberal_mode() 2 | { 3 | [ -n "$SKIP_CONNTRACK_LIBERAL_MODE" ] || sysctl -w net.netfilter.nf_conntrack_tcp_be_liberal=$1 4 | } 5 | zapret_do_firewall() 6 | { 7 | linux_fwtype 8 | 9 | [ "$1" = 1 -a -n "$INIT_FW_PRE_UP_HOOK" ] && $INIT_FW_PRE_UP_HOOK 10 | [ "$1" = 0 -a -n "$INIT_FW_PRE_DOWN_HOOK" ] && $INIT_FW_PRE_DOWN_HOOK 11 | 12 | case "$FWTYPE" in 13 | iptables) 14 | zapret_do_firewall_ipt "$@" 15 | ;; 16 | nftables) 17 | zapret_do_firewall_nft "$@" 18 | ;; 19 | esac 20 | 21 | # russian DPI sends RST,ACK with wrong ACK. 22 | # this is sometimes treated by conntrack as invalid and connbytes fw rules do not pass RST packet to nfqws. 23 | # switch on liberal mode on zapret firewall start and switch off on zapret firewall stop 24 | # this is only required for processing incoming bad RSTs. incoming rules are only applied in autohostlist mode 25 | # calling this after firewall because conntrack module can be not loaded before applying conntrack firewall rules 26 | [ "$MODE_FILTER" = "autohostlist" ] && set_conntrack_liberal_mode $1 27 | 28 | [ "$1" = 1 -a -n "$INIT_FW_POST_UP_HOOK" ] && $INIT_FW_POST_UP_HOOK 29 | [ "$1" = 0 -a -n "$INIT_FW_POST_DOWN_HOOK" ] && $INIT_FW_POST_DOWN_HOOK 30 | 31 | return 0 32 | } 33 | zapret_apply_firewall() 34 | { 35 | zapret_do_firewall 1 "$@" 36 | } 37 | zapret_unapply_firewall() 38 | { 39 | zapret_do_firewall 0 "$@" 40 | } 41 | -------------------------------------------------------------------------------- /nfq2/conntrack_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define CTRACK_T_SYN 60 6 | #define CTRACK_T_FIN 60 7 | #define CTRACK_T_EST 300 8 | #define CTRACK_T_UDP 60 9 | 10 | // SYN - SYN or SYN/ACK received 11 | // ESTABLISHED - any except SYN or SYN/ACK received 12 | // FIN - FIN or RST received 13 | typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate; 14 | 15 | typedef struct 16 | { 17 | uint64_t pcounter; // packet counter 18 | uint64_t pdcounter; // data packet counter (with payload) 19 | uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq. 20 | 21 | // tcp only state, not used in udp 22 | uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current 23 | uint32_t uppos; // max seen position. useful to detect retransmissions 24 | uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions 25 | uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current 26 | uint32_t seq0; // starting seq and ack 27 | uint16_t winsize; // last seen window size 28 | uint16_t mss; 29 | uint32_t winsize_calc; // calculated window size 30 | uint8_t scale; // last seen window scale factor. SCALE_NONE if none 31 | bool rseq_over_2G; 32 | } t_ctrack_position; 33 | 34 | typedef struct 35 | { 36 | struct timespec t_last; 37 | t_connstate state; 38 | t_ctrack_position client, server; 39 | } 40 | t_ctrack_positions; 41 | -------------------------------------------------------------------------------- /lua/zapret-pcap.lua: -------------------------------------------------------------------------------- 1 | function pcap_write_header(file) 2 | -- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0x4000 (16384), 0x65 - l3 packets without l2 3 | file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x65") 4 | end 5 | function pcap_write_packet(file, raw) 6 | local sec, nsec = clock_gettime(); 7 | file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw)) 8 | file:write(raw) 9 | file:close() 10 | end 11 | function pcap_write(file, raw) 12 | local pos = file:seek() 13 | if (pos==0) then 14 | pcap_write_header(file) 15 | end 16 | pcap_write_packet(file, raw) 17 | end 18 | 19 | -- test case : --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap 20 | -- arg : file= - file for storing pcap data. if --writeable is specified and filename is relative - append filename to writeable path 21 | -- arg : keep - do not overwrite file, append packets to existing 22 | function pcap(ctx, desync) 23 | if not desync.arg.file or #desync.arg.file==0 then 24 | error("pcap requires 'file' parameter") 25 | end 26 | local fn_cache_name = desync.func_instance.."_fn" 27 | if not _G[fn_cache_name] then 28 | _G[fn_cache_name] = writeable_file_name(desync.arg.file) 29 | if not desync.arg.keep then 30 | -- overwrite file 31 | os.remove(_G[fn_cache_name]) 32 | end 33 | end 34 | local f = io.open(_G[fn_cache_name], "a") 35 | if not f then 36 | error("pcap: could not write to '".._G[fn_cache_name].."'") 37 | end 38 | pcap_write(f, raw_packet(ctx)) 39 | end 40 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/50-discord-media: -------------------------------------------------------------------------------- 1 | # this custom script runs desync to all discord media packets 2 | # NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22) 3 | 4 | # can override in config : 5 | NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}" 6 | DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}" 7 | 8 | alloc_dnum DNUM_DISCORD_MEDIA 9 | alloc_qnum QNUM_DISCORD_MEDIA 10 | 11 | zapret_custom_daemons() 12 | { 13 | # $1 - 1 - add, 0 - stop 14 | 15 | local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA" 16 | do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt" 17 | } 18 | zapret_custom_firewall() 19 | { 20 | # $1 - 1 - run, 0 - stop 21 | 22 | local DISABLE_IPV6=1 23 | local port_range=$(replace_char - : $DISCORD_MEDIA_PORT_RANGE) 24 | local f="-p udp --dport $port_range -m u32 --u32" 25 | # this is simplified test to skip writing monstrous rule. instead of checking 64 bytes for zeroes only check 2 dwords for zero 26 | fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x52&&0>>22&0x3C@8=0x00010046&&0>>22&0x3C@16=0&&0>>22&0x3C@76=0" '' $QNUM_DISCORD_MEDIA 27 | } 28 | zapret_custom_firewall_nft() 29 | { 30 | # stop logic is not required 31 | 32 | local DISABLE_IPV6=1 33 | local f="udp dport $DISCORD_MEDIA_PORT_RANGE udp length == 82 @ih,0,32 0x00010046 @ih,64,128 0x00000000000000000000000000000000 @ih,192,128 0x00000000000000000000000000000000 @ih,320,128 0x00000000000000000000000000000000 @ih,448,128 0x00000000000000000000000000000000" 34 | nft_fw_nfqws_post "$f" '' $QNUM_DISCORD_MEDIA 35 | } 36 | -------------------------------------------------------------------------------- /init.d/systemd/nfqws2@.service: -------------------------------------------------------------------------------- 1 | # Example systemd service unit for nfqws. Adjust for your installation. 2 | 3 | # WARNING ! This unit requires to compile nfqws using `make systemd` 4 | # WARNING ! This makefile target enables special systemd notify support. 5 | 6 | # PREPARE 7 | # install build depends 8 | # make -C /opt/zapret2 systemd 9 | # cp nfqws2\@.service /lib/systemd/system 10 | # systemctl daemon-reload 11 | 12 | # MANAGE INSTANCE 13 | # prepare /etc/zapret2/nfqws1.conf with nfqws parameters 14 | # systemctl start nfqws2@nfqws1 15 | # systemctl status nfqws2@nfqws1 16 | # systemctl restart nfqws2@nfqws1 17 | # systemctl enable nfqws2@nfqws1 18 | # systemctl disable nfqws2@nfqws1 19 | # systemctl stop nfqws2@nfqws1 20 | 21 | # DELETE 22 | # rm /lib/systemd/system/nfqws@.service 23 | # systemctl daemon-reload 24 | 25 | 26 | [Unit] 27 | After=network.target 28 | 29 | [Service] 30 | Type=notify 31 | Restart=on-failure 32 | 33 | ExecSearchPath=/opt/zapret2/nfq2 34 | ExecStart=nfqws2 @${CONFIG_DIR}/${INSTANCE}.conf 35 | Environment=CONFIG_DIR=/etc/zapret2 36 | Environment=INSTANCE=%i 37 | 38 | RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET 39 | 40 | LockPersonality=true 41 | MemoryDenyWriteExecute=true 42 | PrivateDevices=true 43 | PrivateMounts=true 44 | PrivateTmp=true 45 | ProcSubset=pid 46 | ProtectClock=true 47 | ProtectControlGroups=true 48 | ProtectHome=true 49 | ProtectHostname=true 50 | ProtectKernelLogs=true 51 | ProtectKernelModules=true 52 | ProtectKernelTunables=true 53 | ProtectProc=invisible 54 | ProtectSystem=full 55 | RemoveIPC=true 56 | RestrictNamespaces=true 57 | RestrictRealtime=true 58 | RestrictSUIDSGID=true 59 | UMask=0077 60 | 61 | [Install] 62 | WantedBy=multi-user.target 63 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/24-syndata.sh: -------------------------------------------------------------------------------- 1 | . "$TESTDIR/def.inc" 2 | 3 | pktws_check_http() 4 | { 5 | # $1 - test function 6 | # $2 - domain 7 | 8 | local PAYLOAD="--payload http_req" split 9 | 10 | for split in '' multisplit multidisorder; do 11 | pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} 12 | pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split} 13 | done 14 | } 15 | 16 | pktws_check_https_tls() 17 | { 18 | # $1 - test function 19 | # $2 - domain 20 | # $3 - PRE args for nfqws2 21 | 22 | local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split 23 | 24 | for split in '' multisplit multidisorder; do 25 | pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1 26 | pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1 27 | pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,rndsni ${split:+$PAYLOAD --lua-desync=$split} && ok=1 28 | pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,sni=google.com ${split:+$PAYLOAD --lua-desync=$split} && ok=1 29 | done 30 | 31 | [ "$ok" = 1 ] 32 | } 33 | 34 | pktws_check_https_tls12() 35 | { 36 | # $1 - test function 37 | # $2 - domain 38 | 39 | pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return 40 | pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6 41 | } 42 | 43 | pktws_check_https_tls13() 44 | { 45 | # $1 - test function 46 | # $2 - domain 47 | 48 | pktws_check_https_tls "$1" "$2" 49 | } 50 | -------------------------------------------------------------------------------- /init.d/sysv/zapret2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: zapret 4 | # Required-Start: $local_fs $network 5 | # Required-Stop: $local_fs $network 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | ### END INIT INFO 9 | 10 | SCRIPT=$(readlink -f "$0") 11 | EXEDIR=$(dirname "$SCRIPT") 12 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 13 | . "$EXEDIR/functions" 14 | 15 | NAME=zapret 16 | DESC=anti-zapret 17 | 18 | do_start() 19 | { 20 | zapret_run_daemons 21 | [ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; } 22 | } 23 | do_stop() 24 | { 25 | zapret_stop_daemons 26 | [ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall 27 | } 28 | 29 | case "$1" in 30 | start) 31 | do_start 32 | ;; 33 | 34 | stop) 35 | do_stop 36 | ;; 37 | 38 | restart) 39 | do_stop 40 | do_start 41 | ;; 42 | 43 | start-fw|start_fw) 44 | zapret_apply_firewall 45 | ;; 46 | stop-fw|stop_fw) 47 | zapret_unapply_firewall 48 | ;; 49 | 50 | restart-fw|restart_fw) 51 | zapret_unapply_firewall 52 | zapret_apply_firewall 53 | ;; 54 | 55 | start-daemons|start_daemons) 56 | zapret_run_daemons 57 | ;; 58 | stop-daemons|stop_daemons) 59 | zapret_stop_daemons 60 | ;; 61 | restart-daemons|restart_daemons) 62 | zapret_stop_daemons 63 | zapret_run_daemons 64 | ;; 65 | 66 | reload-ifsets|reload_ifsets) 67 | zapret_reload_ifsets 68 | ;; 69 | list-ifsets|list_ifsets) 70 | zapret_list_ifsets 71 | ;; 72 | list-table|list_table) 73 | zapret_list_table 74 | ;; 75 | 76 | *) 77 | echo "Usage: $SCRIPT {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2 78 | exit 1 79 | ;; 80 | esac 81 | 82 | exit 0 83 | -------------------------------------------------------------------------------- /nfq2/gzip.c: -------------------------------------------------------------------------------- 1 | #include "gzip.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #define ZCHUNK 16384 7 | #define BUFMIN 128 8 | #define BUFCHUNK (1024*128) 9 | 10 | int z_readfile(FILE *F, char **buf, size_t *size) 11 | { 12 | z_stream zs; 13 | int r; 14 | unsigned char in[ZCHUNK]; 15 | size_t bufsize; 16 | void *newbuf; 17 | 18 | memset(&zs, 0, sizeof(zs)); 19 | 20 | *buf = NULL; 21 | bufsize = *size = 0; 22 | 23 | r = inflateInit2(&zs, 47); 24 | if (r != Z_OK) return r; 25 | 26 | do 27 | { 28 | zs.avail_in = fread(in, 1, sizeof(in), F); 29 | if (ferror(F)) 30 | { 31 | r = Z_ERRNO; 32 | goto zerr; 33 | } 34 | if (!zs.avail_in) break; 35 | zs.next_in = in; 36 | do 37 | { 38 | if ((bufsize - *size) < BUFMIN) 39 | { 40 | bufsize += BUFCHUNK; 41 | newbuf = *buf ? realloc(*buf, bufsize) : malloc(bufsize); 42 | if (!newbuf) 43 | { 44 | r = Z_MEM_ERROR; 45 | goto zerr; 46 | } 47 | *buf = newbuf; 48 | } 49 | zs.avail_out = bufsize - *size; 50 | zs.next_out = (unsigned char*)(*buf + *size); 51 | r = inflate(&zs, Z_NO_FLUSH); 52 | if (r != Z_OK && r != Z_STREAM_END) goto zerr; 53 | *size = bufsize - zs.avail_out; 54 | } while (r == Z_OK && zs.avail_in); 55 | } while (r == Z_OK); 56 | 57 | if (*size < bufsize) 58 | { 59 | // free extra space 60 | if ((newbuf = realloc(*buf, *size))) *buf = newbuf; 61 | } 62 | 63 | inflateEnd(&zs); 64 | return Z_OK; 65 | 66 | zerr: 67 | inflateEnd(&zs); 68 | free(*buf); 69 | *buf = NULL; 70 | return r; 71 | } 72 | 73 | bool is_gzip(FILE* F) 74 | { 75 | unsigned char magic[2]; 76 | bool b = !fseek(F, 0, SEEK_SET) && fread(magic, 1, 2, F) == 2 && magic[0] == 0x1F && magic[1] == 0x8B; 77 | fseek(F, 0, SEEK_SET); 78 | return b; 79 | } 80 | -------------------------------------------------------------------------------- /init.d/openrc/zapret2: -------------------------------------------------------------------------------- 1 | #!/sbin/openrc-run 2 | 3 | # zapret openrc to sysv adapter 4 | # on some systems (alpine) for unknown reason non-openrc-run scripts are not started from /etc/init.d 5 | 6 | EXEDIR=$(dirname "$RC_SERVICE") 7 | EXEDIR="$(cd "$EXEDIR"; pwd)" 8 | ZAPRET_BASE="$EXEDIR/../.." 9 | ZAPRET_INIT="$ZAPRET_BASE/init.d/sysv/zapret2" 10 | 11 | extra_commands="start_fw stop_fw restart_fw start_daemons stop_daemons restart_daemons reload_ifsets list_ifsets list_table" 12 | description="extra commands :" 13 | description_stop_fw="Stop zapret firewall" 14 | description_start_fw="Start zapret firewall" 15 | description_restart_fw="Restart zapret firewall" 16 | description_reload_ifsets="Reload interface lists (nftables only)" 17 | description_list_ifsets="Display interface lists (nftables only)" 18 | description_list_table="Display zapret nftable (nftables only)" 19 | description_stop_daemons="Stop zapret daemons only" 20 | description_start_daemons="Start zapret daemons only" 21 | description_restart_daemons="Restart zapret firewall only" 22 | 23 | depend() { 24 | rc-service -e networking && need networking 25 | } 26 | start() 27 | { 28 | "$ZAPRET_INIT" start 29 | } 30 | stop() 31 | { 32 | "$ZAPRET_INIT" stop 33 | } 34 | start_fw() 35 | { 36 | "$ZAPRET_INIT" start_fw 37 | } 38 | stop_fw() 39 | { 40 | "$ZAPRET_INIT" stop_fw 41 | } 42 | restart_fw() 43 | { 44 | "$ZAPRET_INIT" restart_fw 45 | } 46 | start_daemons() 47 | { 48 | "$ZAPRET_INIT" start_daemons 49 | } 50 | stop_daemons() 51 | { 52 | "$ZAPRET_INIT" stop_daemons 53 | } 54 | restart_daemons() 55 | { 56 | "$ZAPRET_INIT" restart_daemons 57 | } 58 | reload_ifsets() 59 | { 60 | "$ZAPRET_INIT" reload_ifsets 61 | } 62 | list_ifsets() 63 | { 64 | "$ZAPRET_INIT" list_ifsets 65 | } 66 | list_table() 67 | { 68 | "$ZAPRET_INIT" list_table 69 | } 70 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DIRS := nfq2 ip2net mdig 2 | TGT := binaries/my 3 | 4 | all: clean 5 | @mkdir -p "$(TGT)"; \ 6 | for dir in $(DIRS); do \ 7 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 8 | $(MAKE) -C "$$dir" || exit; \ 9 | for exe in "$$dir/"*; do \ 10 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 11 | mv -f "$$exe" "${TGT}" ; \ 12 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 13 | fi \ 14 | done \ 15 | done 16 | 17 | systemd: clean 18 | @mkdir -p "$(TGT)"; \ 19 | for dir in $(DIRS); do \ 20 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 21 | $(MAKE) -C "$$dir" systemd || exit; \ 22 | for exe in "$$dir/"*; do \ 23 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 24 | mv -f "$$exe" "${TGT}" ; \ 25 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 26 | fi \ 27 | done \ 28 | done 29 | 30 | android: clean 31 | @mkdir -p "$(TGT)"; \ 32 | for dir in $(DIRS); do \ 33 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 34 | $(MAKE) -C "$$dir" android || exit; \ 35 | for exe in "$$dir/"*; do \ 36 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 37 | mv -f "$$exe" "${TGT}" ; \ 38 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 39 | fi \ 40 | done \ 41 | done 42 | 43 | bsd: clean 44 | @mkdir -p "$(TGT)"; \ 45 | for dir in $(DIRS); do \ 46 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 47 | $(MAKE) -C "$$dir" bsd || exit; \ 48 | for exe in "$$dir/"*; do \ 49 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 50 | mv -f "$$exe" "${TGT}" ; \ 51 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 52 | fi \ 53 | done \ 54 | done 55 | 56 | clean: 57 | @[ -d "$(TGT)" ] && rm -rf "$(TGT)" ; \ 58 | for dir in $(DIRS); do \ 59 | $(MAKE) -C "$$dir" clean; \ 60 | done 61 | -------------------------------------------------------------------------------- /ipset/get_reestr_hostlist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | ZREESTR="$TMPDIR/zapret.txt.gz" 9 | IPB="$TMPDIR/ipb.txt" 10 | ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz 11 | 12 | dl_checked() 13 | { 14 | # $1 - url 15 | # $2 - file 16 | # $3 - minsize 17 | # $4 - maxsize 18 | # $5 - maxtime 19 | curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" || 20 | { 21 | echo list download failed : $1 22 | return 2 23 | } 24 | dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ') 25 | if test $dlsize -lt $3; then 26 | echo list is too small : $dlsize bytes. can be bad. 27 | return 2 28 | fi 29 | return 0 30 | } 31 | 32 | reestr_list() 33 | { 34 | LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }' 35 | } 36 | reestr_extract_ip() 37 | { 38 | LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}' 39 | } 40 | 41 | ipban_fin() 42 | { 43 | getipban 44 | "$IPSET_DIR/create_ipset.sh" 45 | } 46 | 47 | dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || { 48 | ipban_fin 49 | exit 2 50 | } 51 | 52 | reestr_list | sort -u | zz "$ZHOSTLIST" 53 | 54 | reestr_extract_ip <"$ZREESTR" >"$IPB" 55 | 56 | rm -f "$ZREESTR" 57 | [ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN" 58 | [ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6" 59 | rm -f "$IPB" 60 | 61 | hup_zapret_daemons 62 | 63 | ipban_fin 64 | 65 | exit 0 66 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/20-multi.sh: -------------------------------------------------------------------------------- 1 | pktws_simple_split_tests() 2 | { 3 | # $1 - test function 4 | # $2 - domain/uri 5 | # $3 - splits 6 | # $4 - PRE args for nfqws2 7 | local pos ok ok_any pre="$4" 8 | local splitf splitfs="multisplit multidisorder" 9 | 10 | ok_any=0 11 | for splitf in multisplit multidisorder; do 12 | eval need_$splitf=0 13 | ok=0 14 | for pos in $3; do 15 | pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$splitf:pos=$pos && ok=1 16 | done 17 | [ "$ok" = 1 -a "$SCANLEVEL" != force ] || eval need_$splitf=1 18 | [ "$ok" = 1 ] && ok_any=1 19 | done 20 | [ "$ok_any" = 1 ] 21 | } 22 | 23 | 24 | pktws_check_http() 25 | { 26 | # $1 - test function 27 | # $2 - domain 28 | local splits_http='method+2 midsld method+2,midsld' 29 | local PAYLOAD="--payload http_req" 30 | 31 | [ "$NOTEST_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return; } 32 | 33 | pktws_simple_split_tests "$1" "$2" "$splits_http" 34 | } 35 | 36 | pktws_check_https_tls() 37 | { 38 | # $1 - test function 39 | # $2 - domain 40 | # $3 - PRE args for nfqws2 41 | local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1360 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1' 42 | local PAYLOAD="--payload tls_client_hello" 43 | 44 | [ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; } 45 | 46 | pktws_simple_split_tests "$1" "$2" "$splits_tls" "$3" 47 | } 48 | 49 | pktws_check_https_tls12() 50 | { 51 | # $1 - test function 52 | # $2 - domain 53 | pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return 54 | 55 | # do not use 'need' values obtained with wssize 56 | local need_multisplit_save=$need_multisplit need_multidisorder_save=$need_multidisorder 57 | pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6 58 | need_multisplit=$need_multisplit_save; need_multidisorder=$need_multidisorder_save 59 | } 60 | 61 | pktws_check_https_tls13() 62 | { 63 | # $1 - test function 64 | # $2 - domain 65 | pktws_check_https_tls "$1" "$2" 66 | } 67 | -------------------------------------------------------------------------------- /nfq2/packet_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "packet_queue.h" 6 | 7 | void rawpacket_queue_init(struct rawpacket_tailhead *q) 8 | { 9 | TAILQ_INIT(q); 10 | } 11 | void rawpacket_free(struct rawpacket *rp) 12 | { 13 | if (rp) free(rp->packet); 14 | free(rp); 15 | } 16 | struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q) 17 | { 18 | struct rawpacket *rp; 19 | rp = TAILQ_FIRST(q); 20 | if (rp) TAILQ_REMOVE(q, rp, next); 21 | return rp; 22 | } 23 | void rawpacket_queue_destroy(struct rawpacket_tailhead *q) 24 | { 25 | struct rawpacket *rp; 26 | while((rp = rawpacket_dequeue(q))) rawpacket_free(rp); 27 | } 28 | 29 | struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos) 30 | { 31 | struct rawpacket *rp = malloc(sizeof(struct rawpacket)); 32 | if (!rp) return NULL; 33 | 34 | rp->packet = malloc(len); 35 | if (!rp->packet) 36 | { 37 | free(rp); 38 | return NULL; 39 | } 40 | 41 | rp->dst = *dst; 42 | rp->fwmark_orig = fwmark_orig; 43 | rp->fwmark = fwmark; 44 | if (ifin) 45 | snprintf(rp->ifin,sizeof(rp->ifin),"%s",ifin); 46 | else 47 | *rp->ifin = 0; 48 | if (ifout) 49 | snprintf(rp->ifout,sizeof(rp->ifout),"%s",ifout); 50 | else 51 | *rp->ifout = 0; 52 | memcpy(rp->packet,data,len); 53 | rp->len=len; 54 | rp->len_payload=len_payload; 55 | 56 | // make a copy for replay 57 | if (tpos) 58 | { 59 | rp->tpos = *tpos; 60 | rp->tpos_present = true; 61 | } 62 | else 63 | rp->tpos_present = false; 64 | 65 | TAILQ_INSERT_TAIL(q, rp, next); 66 | 67 | return rp; 68 | } 69 | 70 | unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q) 71 | { 72 | const struct rawpacket *rp; 73 | unsigned int ct=0; 74 | TAILQ_FOREACH(rp, q, next) ct++; 75 | return ct; 76 | } 77 | bool rawpacket_queue_empty(const struct rawpacket_tailhead *q) 78 | { 79 | return !TAILQ_FIRST(q); 80 | } 81 | -------------------------------------------------------------------------------- /nfq2/sec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef __linux__ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | bool checkpcap(uint64_t caps); 13 | bool setpcap(uint64_t caps); 14 | int getmaxcap(void); 15 | bool dropcaps(void); 16 | 17 | #define syscall_nr (offsetof(struct seccomp_data, nr)) 18 | #define arch_nr (offsetof(struct seccomp_data, arch)) 19 | #define syscall_arg(x) (offsetof(struct seccomp_data, args[x])) 20 | 21 | #if defined(__aarch64__) 22 | 23 | # define ARCH_NR AUDIT_ARCH_AARCH64 24 | 25 | #elif defined(__amd64__) 26 | 27 | # define ARCH_NR AUDIT_ARCH_X86_64 28 | 29 | #elif defined(__arm__) && (defined(__ARM_EABI__) || defined(__thumb__)) 30 | 31 | # if __BYTE_ORDER == __LITTLE_ENDIAN 32 | # define ARCH_NR AUDIT_ARCH_ARM 33 | # else 34 | # define ARCH_NR AUDIT_ARCH_ARMEB 35 | # endif 36 | 37 | #elif defined(__i386__) 38 | 39 | # define ARCH_NR AUDIT_ARCH_I386 40 | 41 | #elif defined(__mips__) 42 | 43 | #if _MIPS_SIM == _MIPS_SIM_ABI32 44 | # if __BYTE_ORDER == __LITTLE_ENDIAN 45 | # define ARCH_NR AUDIT_ARCH_MIPSEL 46 | # else 47 | # define ARCH_NR AUDIT_ARCH_MIPS 48 | # endif 49 | #elif _MIPS_SIM == _MIPS_SIM_ABI64 50 | # if __BYTE_ORDER == __LITTLE_ENDIAN 51 | # define ARCH_NR AUDIT_ARCH_MIPSEL64 52 | # else 53 | # define ARCH_NR AUDIT_ARCH_MIPS64 54 | # endif 55 | #else 56 | # error "Unsupported mips abi" 57 | #endif 58 | 59 | #elif defined(__PPC64__) 60 | 61 | # if __BYTE_ORDER == __LITTLE_ENDIAN 62 | # define ARCH_NR AUDIT_ARCH_PPC64LE 63 | # else 64 | # define ARCH_NR AUDIT_ARCH_PPC64 65 | # endif 66 | 67 | #elif defined(__PPC__) 68 | 69 | # define ARCH_NR AUDIT_ARCH_PPC 70 | 71 | #elif __riscv && __riscv_xlen == 64 72 | 73 | # define ARCH_NR AUDIT_ARCH_RISCV64 74 | 75 | #else 76 | 77 | # error "Platform does not support seccomp filter yet" 78 | 79 | #endif 80 | 81 | #endif 82 | 83 | 84 | #ifndef __CYGWIN__ 85 | bool sec_harden(void); 86 | bool can_drop_root(void); 87 | bool droproot(uid_t uid, const char *user, const gid_t *gid, int gid_count); 88 | void print_id(void); 89 | #endif 90 | 91 | void daemonize(void); 92 | bool writepid(const char *filename); 93 | -------------------------------------------------------------------------------- /nfq2/crypto/aes-ctr.c: -------------------------------------------------------------------------------- 1 | #include "aes-ctr.h" 2 | #include 3 | 4 | #define AES_BLOCKLEN 16 5 | 6 | 7 | // add 64-bit value to 16-byte big endian counter 8 | #if defined(__GNUC__) && !defined(__llvm__) 9 | __attribute__((optimize ("no-strict-aliasing"))) 10 | #endif 11 | void ctr_add(uint8_t *counter, uint64_t add) 12 | { 13 | #ifndef __BYTE_ORDER__ 14 | #error "__BYTE_ORDER__ not defined" 15 | #endif 16 | uint64_t *c = (uint64_t*)counter; 17 | 18 | #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ 19 | uint64_t sum = c[1] + add; 20 | if (sum < c[1]) // overflow 21 | c[0]++; 22 | c[1] = sum; 23 | #else 24 | uint64_t lsw = __builtin_bswap64(c[1]); 25 | uint64_t sum = lsw + add; 26 | if (sum < lsw) // overflow 27 | c[0] = __builtin_bswap64(__builtin_bswap64(c[0]) + 1); 28 | c[1] = __builtin_bswap64(sum); 29 | #endif 30 | } 31 | 32 | // increment 16-byte big endian counter 33 | static inline void ctr_increment(uint8_t *counter) 34 | { 35 | for (int8_t bi = (AES_BLOCKLEN - 1); (bi >= 0) && !++counter[bi]; bi--); 36 | } 37 | 38 | #if defined(__GNUC__) && !defined(__llvm__) 39 | __attribute__((optimize ("no-strict-aliasing"))) 40 | #endif 41 | void aes_ctr_xcrypt_buffer(aes_context *ctx, const uint8_t *iv, const uint8_t *in, size_t length, uint8_t *out) 42 | { 43 | uint8_t bi, ivc[AES_BLOCKLEN], buffer[AES_BLOCKLEN]; 44 | size_t i, l16 = length & ~0xF; 45 | 46 | memcpy(ivc, iv, AES_BLOCKLEN); 47 | 48 | for (i = 0; i < l16; i += 16) 49 | { 50 | aes_cipher(ctx, ivc, buffer); 51 | ctr_increment(ivc); 52 | *((uint64_t*)(out + i)) = *((uint64_t*)(in + i)) ^ ((uint64_t*)buffer)[0]; 53 | *((uint64_t*)(out + i + 8)) = *((uint64_t*)(in + i + 8)) ^ ((uint64_t*)buffer)[1]; 54 | } 55 | 56 | if (i 4 | 5 | #include "win.h" 6 | #include "nfqws.h" 7 | #include "params.h" 8 | 9 | #define SERVICE_NAME "winws2" 10 | 11 | static SERVICE_STATUS ServiceStatus; 12 | static SERVICE_STATUS_HANDLE hStatus = NULL; 13 | static int service_argc = 0; 14 | static char **service_argv = NULL; 15 | 16 | void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))); 17 | 18 | bool service_run(int argc, char *argv[]) 19 | { 20 | SERVICE_TABLE_ENTRY ServiceTable[] = { 21 | {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main}, 22 | {NULL, NULL} 23 | }; 24 | 25 | service_argc = argc; 26 | service_argv = argv; 27 | 28 | return StartServiceCtrlDispatcherA(ServiceTable); 29 | } 30 | 31 | static void service_set_status(DWORD state) 32 | { 33 | ServiceStatus.dwCurrentState = state; 34 | SetServiceStatus(hStatus, &ServiceStatus); 35 | } 36 | 37 | // Control handler function 38 | void service_controlhandler(DWORD request) 39 | { 40 | switch (request) 41 | { 42 | case SERVICE_CONTROL_STOP: 43 | case SERVICE_CONTROL_SHUTDOWN: 44 | bQuit = true; 45 | ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; 46 | break; 47 | } 48 | SetServiceStatus(hStatus, &ServiceStatus); 49 | } 50 | 51 | void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) 52 | { 53 | ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 54 | ServiceStatus.dwCurrentState = SERVICE_RUNNING; 55 | ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 56 | ServiceStatus.dwWin32ExitCode = 0; 57 | ServiceStatus.dwServiceSpecificExitCode = 0; 58 | ServiceStatus.dwCheckPoint = 1; 59 | ServiceStatus.dwWaitHint = 0; 60 | 61 | hStatus = RegisterServiceCtrlHandlerA( 62 | SERVICE_NAME, 63 | (LPHANDLER_FUNCTION)service_controlhandler); 64 | if (hStatus == (SERVICE_STATUS_HANDLE)0) 65 | { 66 | // Registering Control Handler failed 67 | return; 68 | } 69 | 70 | SetServiceStatus(hStatus, &ServiceStatus); 71 | 72 | // Calling main with saved argc & argv 73 | ServiceStatus.dwWin32ExitCode = (DWORD)main(service_argc, service_argv); 74 | 75 | ServiceStatus.dwCurrentState = SERVICE_STOPPED; 76 | SetServiceStatus(hStatus, &ServiceStatus); 77 | return; 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /uninstall_easy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # automated script for easy uninstalling zapret 4 | 5 | EXEDIR="$(dirname "$0")" 6 | EXEDIR="$(cd "$EXEDIR"; pwd)" 7 | ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"} 8 | ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"} 9 | ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} 10 | ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default" 11 | IPSET_DIR="$ZAPRET_BASE/ipset" 12 | 13 | [ -f "$ZAPRET_CONFIG" ] || { 14 | ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")" 15 | [ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR" 16 | cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG" 17 | } 18 | 19 | . "$ZAPRET_CONFIG" 20 | . "$ZAPRET_BASE/common/base.sh" 21 | . "$ZAPRET_BASE/common/elevate.sh" 22 | . "$ZAPRET_BASE/common/fwtype.sh" 23 | . "$ZAPRET_BASE/common/dialog.sh" 24 | . "$ZAPRET_BASE/common/ipt.sh" 25 | . "$ZAPRET_BASE/common/nft.sh" 26 | . "$ZAPRET_BASE/common/installer.sh" 27 | 28 | remove_systemd() 29 | { 30 | clear_ipset 31 | service_stop_systemd 32 | service_remove_systemd 33 | timer_remove_systemd 34 | nft_del_table 35 | crontab_del 36 | } 37 | 38 | remove_openrc() 39 | { 40 | clear_ipset 41 | service_remove_openrc 42 | nft_del_table 43 | crontab_del 44 | } 45 | 46 | remove_linux() 47 | { 48 | INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2" 49 | 50 | clear_ipset 51 | 52 | echo \* executing sysv init stop 53 | "$INIT_SCRIPT_SRC" stop 54 | 55 | nft_del_table 56 | crontab_del 57 | 58 | echo 59 | echo '!!! WARNING. YOUR UNINSTALL IS INCOMPLETE !!!' 60 | echo 'you must manually remove zapret auto start from your system' 61 | } 62 | 63 | remove_openwrt() 64 | { 65 | OPENWRT_FW_INCLUDE=/etc/firewall.zapret2 66 | 67 | clear_ipset 68 | service_remove_sysv 69 | remove_openwrt_firewall 70 | remove_openwrt_iface_hook 71 | nft_del_table 72 | restart_openwrt_firewall 73 | crontab_del 74 | remove_extra_pkgs_openwrt 75 | echo 76 | echo to fully remove zapret : rm -r \"$ZAPRET_BASE\" 77 | } 78 | 79 | fix_sbin_path 80 | check_system 81 | require_root 82 | 83 | case $SYSTEM in 84 | systemd) 85 | remove_systemd 86 | ;; 87 | openrc) 88 | remove_openrc 89 | ;; 90 | linux) 91 | remove_linux 92 | ;; 93 | openwrt) 94 | remove_openwrt 95 | ;; 96 | esac 97 | 98 | 99 | exitp 0 100 | -------------------------------------------------------------------------------- /init.d/custom.d.examples.linux/20-fw-extra: -------------------------------------------------------------------------------- 1 | # this custom script runs standard mode with extra firewall rules 2 | 3 | # config: use TPWS_ENABLE_OVERRIDE, NFQWS_ENABLE_OVERRIDE to enable standard mode daemons 4 | # standard and override switches cannot be enabled simultaneously ! 5 | 6 | TPWS_ENABLE_OVERRIDE=${TPWS_ENABLE_OVERRIDE:-0} 7 | NFQWS_ENABLE_OVERRIDE=${NFQWS_ENABLE_OVERRIDE:-0} 8 | 9 | # config: some if these values must be set in config. not setting any of these makes this script meaningless. 10 | # pre vars put ipt/nft code to the rule beginning 11 | #FW_EXTRA_PRE_TPWS_IPT= 12 | #FW_EXTRA_PRE_TPWS_NFT= 13 | #FW_EXTRA_PRE_NFQWS_IPT="-m mark --mark 0x10000000/0x10000000" 14 | #FW_EXTRA_PRE_NFQWS_NFT="mark and 0x10000000 != 0" 15 | # post vars put ipt/nft code to the rule end 16 | #FW_EXTRA_POST_TPWS_IPT= 17 | #FW_EXTRA_POST_TPWS_NFT= 18 | #FW_EXTRA_POST_NFQWS_IPT= 19 | #FW_EXTRA_POST_NFQWS_NFT= 20 | 21 | check_std_intersect() 22 | { 23 | [ "$TPWS_ENABLE_OVERRIDE" = 1 -a "$TPWS_ENABLE" = 1 ] && { 24 | echo "ERROR ! both TPWS_ENABLE_OVERRIDE and TPWS_ENABLE are enabled" 25 | return 1 26 | } 27 | [ "$NFQWS_ENABLE_OVERRIDE" = 1 -a "$NFQWS_ENABLE" = 1 ] && { 28 | echo "ERROR ! both NFQWS_ENABLE_OVERRIDE and NFQWS_ENABLE are enabled" 29 | return 1 30 | } 31 | return 0 32 | } 33 | 34 | zapret_custom_daemons() 35 | { 36 | # $1 - 1 - add, 0 - stop 37 | 38 | check_std_intersect || return 39 | 40 | local TPWS_SOCKS_ENABLE=0 TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE 41 | standard_mode_daemons "$1" 42 | } 43 | zapret_custom_firewall() 44 | { 45 | # $1 - 1 - run, 0 - stop 46 | 47 | check_std_intersect || return 48 | 49 | local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE 50 | FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_IPT" 51 | zapret_do_firewall_standard_tpws_rules_ipt $1 52 | FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_IPT" 53 | zapret_do_firewall_standard_nfqws_rules_ipt $1 54 | } 55 | zapret_custom_firewall_nft() 56 | { 57 | # stop logic is not required 58 | 59 | check_std_intersect || return 60 | 61 | local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE 62 | FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_NFT" 63 | zapret_apply_firewall_standard_tpws_rules_nft 64 | FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_NFT" 65 | zapret_apply_firewall_standard_nfqws_rules_nft 66 | } 67 | -------------------------------------------------------------------------------- /ipset/get_reestr_resolve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | IPSET_DIR="$(dirname "$0")" 4 | IPSET_DIR="$(cd "$IPSET_DIR"; pwd)" 5 | 6 | . "$IPSET_DIR/def.sh" 7 | 8 | ZREESTR="$TMPDIR/zapret.txt.gz" 9 | ZDIG="$TMPDIR/zapret-dig.txt" 10 | IPB="$TMPDIR/ipb.txt" 11 | ZIPLISTTMP="$TMPDIR/zapret-ip.txt" 12 | #ZURL=https://reestr.rublacklist.net/api/current 13 | ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz 14 | 15 | dl_checked() 16 | { 17 | # $1 - url 18 | # $2 - file 19 | # $3 - minsize 20 | # $4 - maxsize 21 | # $5 - maxtime 22 | curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" || 23 | { 24 | echo list download failed : $1 25 | return 2 26 | } 27 | dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ') 28 | if test $dlsize -lt $3; then 29 | echo list is too small : $dlsize bytes. can be bad. 30 | return 2 31 | fi 32 | return 0 33 | } 34 | 35 | reestr_list() 36 | { 37 | LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }' 38 | } 39 | reestr_extract_ip() 40 | { 41 | LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}' 42 | } 43 | 44 | getuser && { 45 | # both disabled 46 | [ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && exit 0 47 | 48 | dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || exit 2 49 | 50 | echo preparing ipban list .. 51 | 52 | reestr_extract_ip <"$ZREESTR" >"$IPB" 53 | [ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN" 54 | [ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6" 55 | rm -f "$IPB" 56 | 57 | echo preparing dig list .. 58 | reestr_list | sort -u >"$ZDIG" 59 | 60 | rm -f "$ZREESTR" 61 | 62 | echo digging started. this can take long ... 63 | 64 | [ "$DISABLE_IPV4" != "1" ] && { 65 | filedigger "$ZDIG" 4 | cut_local >"$ZIPLISTTMP" || { 66 | rm -f "$ZDIG" 67 | exit 1 68 | } 69 | ip2net4 <"$ZIPLISTTMP" | zz "$ZIPLIST" 70 | rm -f "$ZIPLISTTMP" 71 | } 72 | [ "$DISABLE_IPV6" != "1" ] && { 73 | filedigger "$ZDIG" 6 | cut_local6 >"$ZIPLISTTMP" || { 74 | rm -f "$ZDIG" 75 | exit 1 76 | } 77 | ip2net6 <"$ZIPLISTTMP" | zz "$ZIPLIST6" 78 | rm -f "$ZIPLISTTMP" 79 | } 80 | rm -f "$ZDIG" 81 | } 82 | 83 | "$IPSET_DIR/create_ipset.sh" 84 | -------------------------------------------------------------------------------- /common/list.sh: -------------------------------------------------------------------------------- 1 | HOSTLIST_MARKER="" 2 | HOSTLIST_NOAUTO_MARKER="" 3 | 4 | find_hostlists() 5 | { 6 | [ -n "$HOSTLIST_BASE" ] || HOSTLIST_BASE="$ZAPRET_BASE/ipset" 7 | 8 | HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt.gz" 9 | [ -f "$HOSTLIST" ] || HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt" 10 | [ -f "$HOSTLIST" ] || HOSTLIST= 11 | 12 | HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt.gz" 13 | [ -f "$HOSTLIST_USER" ] || HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt" 14 | [ -f "$HOSTLIST_USER" ] || HOSTLIST_USER= 15 | 16 | HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt.gz" 17 | [ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt" 18 | [ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE= 19 | 20 | HOSTLIST_AUTO="$HOSTLIST_BASE/zapret-hosts-auto.txt" 21 | HOSTLIST_AUTO_DEBUGLOG="$HOSTLIST_BASE/zapret-hosts-auto-debug.log" 22 | } 23 | 24 | filter_apply_hostlist_target() 25 | { 26 | # $1 - var name of nfqws params 27 | 28 | local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parmNA 29 | eval v="\$$1" 30 | if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then 31 | [ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] && 32 | { 33 | find_hostlists 34 | parm1="${HOSTLIST_USER:+--hostlist=$HOSTLIST_USER}" 35 | parm2="${HOSTLIST:+--hostlist=$HOSTLIST}" 36 | parm3="${HOSTLIST_EXCLUDE:+--hostlist-exclude=$HOSTLIST_EXCLUDE}" 37 | [ "$MODE_FILTER" = autohostlist ] && 38 | { 39 | parm4="--hostlist-auto=$HOSTLIST_AUTO" 40 | parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}" 41 | parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}" 42 | parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}" 43 | parm8="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}" 44 | parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}" 45 | parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}" 46 | parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}" 47 | parm12="--hostlist=$HOSTLIST_AUTO" 48 | } 49 | parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}" 50 | parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}" 51 | } 52 | v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")" 53 | v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")" 54 | [ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && { 55 | v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG" 56 | } 57 | eval $1=\""$v"\" 58 | fi 59 | } 60 | -------------------------------------------------------------------------------- /lua/zapret-wgobfs.lua: -------------------------------------------------------------------------------- 1 | -- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword 2 | -- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size 3 | -- do not encrypt data messages and keepalives 4 | -- wgobfs adds maximum of 30+padmax bytes to udp size 5 | -- reduce MTU of wireguard interface to avoid ip fragmentation ! 6 | -- without knowing the secret encrypted packets should be crypto strong white noise with no signature 7 | -- arg : secret - shared secret. any string. must be the same on both peers 8 | -- arg : padmin - min random garbage bytes. 0 by default 9 | -- arg : padmax - max random garbage bytes. 16 by default 10 | function wgobfs(ctx, desync) 11 | local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0 12 | local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16 13 | local function genkey() 14 | -- cache key in a global var bound to instance name 15 | local key_cache_name = desync.func_instance.."_key" 16 | key = _G[key_cache_name] 17 | if not key then 18 | key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16) 19 | _G[key_cache_name] = key 20 | end 21 | return key 22 | end 23 | local function maybe_encrypted_payload(payload) 24 | for k,plsize in pairs({2+12+16+148, 2+12+16+92, 2+12+16+64}) do 25 | if #payload>=(plsize+padmin) and #payload<=(plsize+padmax) then 26 | return true 27 | end 28 | end 29 | return false 30 | end 31 | local function wg_payload_from_size(payload) 32 | if #payload==148 then return "wireguard_initiation" 33 | elseif #payload==92 then return "wireguard_response" 34 | elseif #payload==64 then return "wireguard_cookie" 35 | else return nil 36 | end 37 | end 38 | 39 | if not desync.dis.udp then 40 | instance_cutoff(ctx) 41 | return 42 | end 43 | if not desync.arg.secret or #desync.arg.secret==0 then 44 | error("wgobfs requires secret") 45 | end 46 | if padmin>padmax then 47 | error("wgobfs: padmin>padmax") 48 | end 49 | if desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie" and #desync.dis.payload<65506 then 50 | DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload) 51 | local key = genkey() 52 | -- in aes-gcm every message require it's own crypto secure random iv 53 | -- encrypting more than one message with the same iv is considered catastrophic failure 54 | -- iv must be sent with encrypted message 55 | local iv = bcryptorandom(12) 56 | local encrypted, atag = aes_gcm(true, key, iv, bu16(#desync.dis.payload)..desync.dis.payload..brandom(math.random(padmin,padmax)), nil) 57 | desync.dis.payload = iv..atag..encrypted 58 | return VERDICT_MODIFY 59 | end 60 | 61 | if desync.l7payload=="unknown" and maybe_encrypted_payload(desync.dis.payload) then 62 | local key = genkey() 63 | local iv = string.sub(desync.dis.payload,1,12) 64 | local atag = string.sub(desync.dis.payload,13,28) 65 | local decrypted, atag2 = aes_gcm(false, key, iv, string.sub(desync.dis.payload,29)) 66 | if atag==atag2 then 67 | local plen = u16(decrypted) 68 | if plen>(#decrypted-2) then 69 | DLOG("wgobfs: bad decrypted payload data") 70 | else 71 | desync.dis.payload = string.sub(decrypted, 3, 3+plen-1) 72 | if b_debug then DLOG("wgobfs: decrypted '"..(wg_payload_from_size(desync.dis.payload) or "unknown").."' message. size "..plen) end 73 | return VERDICT_MODIFY 74 | end 75 | else 76 | DLOG("wgobfs: decrypt auth tag mismatch") 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /nfq2/crypto/aes.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL 4 | * 5 | * This is a simple and straightforward implementation of the AES Rijndael 6 | * 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus 7 | * of this work was correctness & accuracy. It is written in 'C' without any 8 | * particular focus upon optimization or speed. It should be endian (memory 9 | * byte order) neutral since the few places that care are handled explicitly. 10 | * 11 | * This implementation of Rijndael was created by Steven M. Gibson of GRC.com. 12 | * 13 | * It is intended for general purpose use, but was written in support of GRC's 14 | * reference implementation of the SQRL (Secure Quick Reliable Login) client. 15 | * 16 | * See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html 17 | * 18 | * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE 19 | * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK. 20 | * 21 | *******************************************************************************/ 22 | 23 | #pragma once 24 | 25 | /******************************************************************************/ 26 | #define AES_DECRYPTION 1 // whether AES decryption is supported 27 | /******************************************************************************/ 28 | 29 | #include 30 | 31 | #define AES_ENCRYPT 1 // specify whether we're encrypting 32 | #define AES_DECRYPT 0 // or decrypting 33 | 34 | #if defined(_MSC_VER) 35 | #include 36 | typedef UINT32 uint32_t; 37 | #else 38 | #include 39 | #endif 40 | 41 | typedef unsigned char uchar; // add some convienent shorter types 42 | typedef unsigned int uint; 43 | 44 | 45 | /****************************************************************************** 46 | * AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use 47 | ******************************************************************************/ 48 | void aes_init_keygen_tables(void); 49 | 50 | 51 | /****************************************************************************** 52 | * AES_CONTEXT : cipher context / holds inter-call data 53 | ******************************************************************************/ 54 | typedef struct { 55 | int mode; // 1 for Encryption, 0 for Decryption 56 | int rounds; // keysize-based rounds count 57 | uint32_t *rk; // pointer to current round key 58 | uint32_t buf[68]; // key expansion buffer 59 | } aes_context; 60 | 61 | 62 | /****************************************************************************** 63 | * AES_SETKEY : called to expand the key for encryption or decryption 64 | ******************************************************************************/ 65 | int aes_setkey(aes_context *ctx, // pointer to context 66 | int mode, // 1 or 0 for Encrypt/Decrypt 67 | const uchar *key, // AES input key 68 | uint keysize); // size in bytes (must be 16, 24, 32 for 69 | // 128, 192 or 256-bit keys respectively) 70 | // returns 0 for success 71 | 72 | /****************************************************************************** 73 | * AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data 74 | ******************************************************************************/ 75 | int aes_cipher(aes_context *ctx, // pointer to context 76 | const uchar input[16], // 128-bit block to en/decipher 77 | uchar output[16]); // 128-bit output result block 78 | // returns 0 for success 79 | -------------------------------------------------------------------------------- /init.d/openwrt/zapret2: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | USE_PROCD=1 4 | # after network 5 | START=21 6 | 7 | my_extra_command() { 8 | local cmd="$1" 9 | local help="$2" 10 | 11 | local extra="$(printf "%-16s%s" "${cmd}" "${help}")" 12 | EXTRA_HELP="${EXTRA_HELP} ${extra} 13 | " 14 | EXTRA_COMMANDS="${EXTRA_COMMANDS} ${cmd}" 15 | } 16 | my_extra_command stop_fw "Stop zapret firewall (noop in iptables+fw3 case)" 17 | my_extra_command start_fw "Start zapret firewall (noop in iptables+fw3 case)" 18 | my_extra_command restart_fw "Restart zapret firewall (noop in iptables+fw3 case)" 19 | my_extra_command reload_ifsets "Reload interface lists (nftables only)" 20 | my_extra_command list_ifsets "Display interface lists (nftables only)" 21 | my_extra_command list_table "Display zapret nftable (nftables only)" 22 | my_extra_command stop_daemons "Stop zapret daemons only (=stop in iptables+fw3 case)" 23 | my_extra_command start_daemons "Start zapret daemons only (=start in iptables+fw3 case)" 24 | my_extra_command restart_daemons "Restart zapret firewall only (=restart in iptables+fw3 case)" 25 | 26 | SCRIPT=$(readlink /etc/init.d/zapret2) 27 | if [ -n "$SCRIPT" ]; then 28 | EXEDIR=$(dirname "$SCRIPT") 29 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 30 | else 31 | ZAPRET_BASE=/opt/zapret2 32 | fi 33 | 34 | . "$ZAPRET_BASE/init.d/openwrt/functions" 35 | 36 | 37 | # !!!!! in old openwrt 21.x- with iptables firewall rules are configured separately 38 | # !!!!! in new openwrt >21.x with nftables firewall is configured here 39 | 40 | PIDDIR=/var/run 41 | 42 | USEROPT="--user=$WS_USER" 43 | NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}" 44 | LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua" 45 | NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT" 46 | 47 | run_daemon() 48 | { 49 | # $1 - daemon string id or number. can use 1,2,3,... 50 | # $2 - daemon 51 | # $3 - daemon args 52 | # use $PIDDIR/$DAEMONBASE$1.pid as pidfile 53 | local DAEMONBASE="$(basename "$2")" 54 | echo "Starting daemon $1: $2 $3" 55 | procd_open_instance 56 | procd_set_param command $2 $3 57 | procd_set_param pidfile $PIDDIR/${DAEMONBASE}_$1.pid 58 | procd_close_instance 59 | } 60 | 61 | run_nfqws() 62 | { 63 | run_daemon $1 "$NFQWS2" "$NFQWS2_OPT_BASE $2" 64 | } 65 | do_nfqws() 66 | { 67 | [ "$1" = 0 ] || { shift; run_nfqws "$@"; } 68 | } 69 | 70 | start_daemons_procd() 71 | { 72 | standard_mode_daemons 1 73 | custom_runner zapret_custom_daemons 1 74 | 75 | return 0 76 | } 77 | start_daemons() 78 | { 79 | rc_procd start_daemons_procd "$@" 80 | } 81 | stop_daemons() 82 | { 83 | local svc="$(basename ${basescript:-$initscript})" 84 | procd_running "$svc" "$1" && procd_kill "$svc" "$1" 85 | } 86 | restart_daemons() 87 | { 88 | stop_daemons 89 | start_daemons 90 | } 91 | 92 | start_fw() 93 | { 94 | zapret_apply_firewall 95 | } 96 | stop_fw() 97 | { 98 | zapret_unapply_firewall 99 | } 100 | restart_fw() 101 | { 102 | stop_fw 103 | start_fw 104 | } 105 | reload_ifsets() 106 | { 107 | zapret_reload_ifsets 108 | } 109 | list_ifsets() 110 | { 111 | zapret_list_ifsets 112 | } 113 | list_table() 114 | { 115 | zapret_list_table 116 | } 117 | 118 | start_service() 119 | { 120 | start_daemons_procd 121 | [ "$INIT_APPLY_FW" != "1" ] || { 122 | linux_fwtype 123 | openwrt_fw3_integration || start_fw 124 | } 125 | } 126 | 127 | stop_service() 128 | { 129 | # this procedure is called from stop() 130 | # stop() already stop daemons 131 | [ "$INIT_APPLY_FW" != "1" ] || { 132 | linux_fwtype 133 | openwrt_fw3_integration || stop_fw 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /docs/compile/build_howto_openwrt.txt: -------------------------------------------------------------------------------- 1 | How to compile native programs for use in openwrt 2 | ------------------------------------------------- 3 | 4 | 1) Install required packages to the host system : 5 | 6 | debian,ubuntu : apt install build-essential patch libncurses-dev python3-distutils unzip gawk wget git 7 | fedora: dnf install make patch gcc g++ ncurses-devel git perl 8 | 9 | Other packages may be required on your distribution. Look for the errors. 10 | 11 | 2) Download latest SDK for your target platform from https://downloads.openwrt.org 12 | 13 | examples : 14 | 15 | curl -o - https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz | tar -Jxv 16 | cd openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64 17 | 18 | curl -o - https://downloads.openwrt.org/snapshots/targets/x86/64/openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst | tar --zstd -xv 19 | cd openwrt-sdk-x86-64_gcc-13.3.0_musl.Linux-x86_64 20 | 21 | 3) Install required libs 22 | 23 | ./scripts/feeds update base packages 24 | ./scripts/feeds install libnetfilter-queue zlib libcap luajit 25 | 26 | 4) If you need static build edit `feeds/packages/lang/luajit/Makefile` 27 | 28 | change BUILDMODE from "dynamic" to "mixed" 29 | 30 | add '$(CP) $(PKG_INSTALL_DIR)/usr/lib/*a $(1)/usr/lib/' 31 | after '$(CP) $(PKG_INSTALL_DIR)/usr/lib/*so* $(1)/usr/lib/' 32 | 33 | should look like : 34 | 35 | define Build/Compile 36 | $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ 37 | HOST_CC="$(HOSTCC) $(HOST_CFLAGS) $(HOST_BITS)" \ 38 | CROSS="$(TARGET_CROSS)" \ 39 | DPREFIX=$(PKG_INSTALL_DIR)/usr \ 40 | PREFIX=/usr \ 41 | TARGET_SYS=Linux \ 42 | TARGET_CFLAGS="$(TARGET_CFLAGS)" \ 43 | BUILDMODE=mixed 44 | rm -rf $(PKG_INSTALL_DIR) 45 | mkdir -p $(PKG_INSTALL_DIR) 46 | $(MAKE) -C $(PKG_BUILD_DIR) \ 47 | DPREFIX=$(PKG_INSTALL_DIR)/usr \ 48 | PREFIX=/usr \ 49 | TARGET_SYS=Linux \ 50 | install 51 | endef 52 | 53 | define Build/InstallDev 54 | $(INSTALL_DIR) $(1)/usr/include/luajit-2.1 55 | $(CP) $(PKG_INSTALL_DIR)/usr/include/luajit-2.1/*.{h,hpp} $(1)/usr/include/luajit-2.1 56 | $(INSTALL_DIR) $(1)/usr/lib 57 | $(CP) $(PKG_INSTALL_DIR)/usr/lib/*so* $(1)/usr/lib/ 58 | $(CP) $(PKG_INSTALL_DIR)/usr/lib/*a $(1)/usr/lib/ 59 | $(INSTALL_DIR) $(1)/usr/lib/pkgconfig 60 | $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/luajit.pc $(1)/usr/lib/pkgconfig/ 61 | $(CP) $(PKG_INSTALL_DIR)/usr/bin/luajit-$(PKG_VERSION) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME) 62 | endef 63 | 64 | 5) Prepare openwrt package definitions 65 | 66 | cp -R /opt/zapret2/docs/compile/openwrt/. . 67 | cp -R /opt/zapret2/nfq2 package/zapret/nfqws2 68 | cp -R /opt/zapret2/mdig package/zapret/mdig 69 | cp -R /opt/zapret2/ip2net package/zapret/ip2net 70 | 71 | 6) Prepare .config 72 | 73 | make defconfig 74 | 75 | If you only need bins without packages comment 'CONFIG_AUTOREMOVE=y' line in .config 76 | Change 'y' to 'n' in Config.in 77 | 78 | should look like : 79 | 80 | config AUTOREMOVE 81 | bool "Automatic removal of build directories" 82 | default n 83 | 84 | and in Config-build.in 85 | should look like : 86 | 87 | config AUTOREMOVE 88 | bool 89 | default n 90 | 91 | 7) Compile 92 | 93 | dynamic build : make package/{nfqws2,mdig,ip2net}/compile 94 | static build : make CFLAGS=-static LDFLAGS=-lgcc_eh package/{nfqws2,mdig,ip2net}/compile 95 | 96 | 8) Get result 97 | 98 | executables only : build_dir/target/ 99 | ipk or apk packages : bin/packages/*/base 100 | 101 | 9) Installing to openwrt to use with zapret 102 | 103 | zapret with or without binaries should be already installed in /opt/zapret2. 104 | Install ipk's or apk's with all compiled progs using opkg or apk. 105 | Bins are placed to /opt/zapret2/binaries/my. 106 | Or copy binaries there manually and set chmod 755 to them. 107 | Run install_bin.sh or install_easy.sh. They will use bins in 'my' folder. 108 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/35-hostfake.sh: -------------------------------------------------------------------------------- 1 | . "$TESTDIR/def.inc" 2 | 3 | 4 | pktws_hostfake_vary_() 5 | { 6 | local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder 7 | shift; shift; shift 8 | 9 | for disorder in '' 'disorder_after:'; do 10 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 11 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 12 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 13 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 14 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake1:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 15 | pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=hostfakesplit:${HOSTFAKE:+host=${HOSTFAKE}:}${disorder}nofake2:midhost=midsld:$fooling:repeats=$FAKE_REPEATS $post && ok_any=1 16 | done 17 | [ "$ok_any" = 1 ] && ok=1 18 | } 19 | pktws_hostfake_vary() 20 | { 21 | local ok_any=0 fooling="$3" 22 | pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1 23 | # duplicate SYN with MD5 24 | contains "$fooling" tcp_md5 && \ 25 | pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range= threshold 100 | * nfqws2: reduced default retrans maxseq to 32768 101 | * nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+ 102 | 103 | v0.7.2 104 | 105 | * zapret-lib: fix broken is_retransmission() 106 | * zapret-auto: add success detector logic 107 | * nfqws2: clean lua cutoff on profile change 108 | * zapret-auto: separate hostkey function 109 | 110 | v0.7.4 111 | 112 | * nfqws2, zapret-lib : check tcp sequence range overflow 113 | * zapret-lib: seq compare functions 114 | * nfqws2: add l3_len, l4_len to dissect 115 | * nfqws2: fix broken l7proto profile rediscovery 116 | * winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change 117 | 118 | v0.7.5 119 | 120 | * zapret-auto : orchestrator "repeater" 121 | * blockcheck2: check http3 with ipv6 exthdr 122 | * github actions: separate target arm-old with LUA classic, not JIT 123 | -------------------------------------------------------------------------------- /nfq2/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | OPTIMIZE ?= -Os 3 | CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto 4 | CFLAGS_SYSTEMD = -DUSE_SYSTEMD 5 | CFLAGS_BSD = -Wno-address-of-packed-member 6 | CFLAGS_CYGWIN = -Wno-address-of-packed-member -static 7 | LDFLAGS_ANDROID = -llog 8 | LIBS = 9 | LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm 10 | LIBS_SYSTEMD = -lsystemd 11 | LIBS_BSD = -lz -lm 12 | LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 13 | LIBS_CYGWIN32 = -lwindivert32 14 | LIBS_CYGWIN64 = -lwindivert64 15 | RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o 16 | RES_CYGWIN64 = windows/res/64/winmanifest.o windows/res/64/winicon.o 17 | SRC_FILES = *.c crypto/*.c 18 | 19 | 20 | LUA_JIT?=1 21 | 22 | ifeq ($(LUA_JIT),1) 23 | 24 | LUAJIT_VER?=2.1 25 | LUAJIT_LUA_VER?=5.1 26 | LUA_PKG:=luajit 27 | 28 | $(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER)) 29 | 30 | LUA_LIB_NAME= 31 | ifeq ($(LUA_CFLAGS),) 32 | LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null) 33 | ifeq ($(LUA_CFLAGS),) 34 | LUA_CFLAGS := -I/usr/local/include/luajit-$(LUAJIT_VER) -I/usr/include/luajit-$(LUAJIT_VER) 35 | endif 36 | endif 37 | ifeq ($(LUA_LIB),) 38 | LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null) 39 | LUA_LIB_DIR := 40 | 41 | ifeq ($(LUA_LIB),) 42 | ifneq ($(wildcard /usr/local/lib/libluajit-$(LUAJIT_LUA_VER).*),) 43 | LUA_LIB_NAME:=luajit-$(LUAJIT_LUA_VER) 44 | LUA_LIB_DIR:=/usr/local/lib 45 | else ifneq ($(wildcard /usr/lib/libluajit-$(LUAJIT_LUA_VER).*),) 46 | LUA_LIB_NAME:=luajit-$(LUAJIT_LUA_VER) 47 | endif 48 | ifeq ($(LUA_LIB_NAME),) 49 | $(info could not find luajit lib name) 50 | LUA_LIB:= 51 | LUA_CFLAGS:= 52 | else 53 | ifneq ($(LUA_LIB_DIR),) 54 | LUA_LIB = -L$(LUA_LIB_DIR) 55 | endif 56 | LUA_LIB += -l$(LUA_LIB_NAME) 57 | endif 58 | endif 59 | endif 60 | 61 | LUA_CFL := -DLUAJIT 62 | 63 | else 64 | 65 | LUA_CFL := 66 | 67 | endif 68 | 69 | 70 | 71 | ifeq ($(LUA_LIB),) 72 | 73 | # no success with luajit 74 | 75 | LUA_VER?=5.4 76 | LUA_VER_UNDOTTED:=$(shell echo $(LUA_VER) | sed 's/\.//g') 77 | 78 | LUA_CFL := 79 | 80 | $(info trying lua $(LUA_VER)) 81 | 82 | OSNAME := $(shell uname) 83 | ifeq ($(OSNAME),FreeBSD) 84 | LUA_PKG:=lua-$(LUA_VER) 85 | else 86 | LUA_PKG:=lua$(LUA_VER_UNDOTTED) 87 | endif 88 | 89 | ifeq ($(LUA_CFLAGS),) 90 | LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null) 91 | ifeq ($(LUA_CFLAGS),) 92 | LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER) 93 | endif 94 | endif 95 | ifeq ($(LUA_LIB),) 96 | LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null) 97 | LUA_LIB_DIR := 98 | ifeq ($(LUA_LIB),) 99 | ifneq ($(wildcard /usr/local/lib/liblua-$(LUA_VER).*),) 100 | LUA_LIB_NAME:=lua-$(LUA_VER) 101 | LUA_LIB_DIR:=/usr/local/lib 102 | else ifneq ($(wildcard /usr/local/lib/liblua$(LUA_VER).*),) 103 | LUA_LIB_NAME:=lua$(LUA_VER) 104 | LUA_LIB_DIR:=/usr/local/lib 105 | else ifneq ($(wildcard /usr/local/lib/liblua.*),) 106 | LUA_LIB_NAME:=lua 107 | LUA_LIB_DIR:=/usr/local/lib 108 | else ifneq ($(wildcard /usr/lib/liblua-$(LUA_VER).*),) 109 | LUA_LIB_NAME:=lua-$(LUA_VER) 110 | else ifneq ($(wildcard /usr/lib/liblua$(LUA_VER).*),) 111 | LUA_LIB_NAME:=lua$(LUA_VER) 112 | else ifneq ($(wildcard /usr/lib/liblua.*),) 113 | LUA_LIB_NAME:=lua 114 | endif 115 | ifeq ($(LUA_LIB_NAME),) 116 | $(error could not find lua lib name) 117 | endif 118 | ifneq ($(LUA_LIB_DIR),) 119 | LUA_LIB = -L$(LUA_LIB_DIR) 120 | endif 121 | LUA_LIB += -l$(LUA_LIB_NAME) 122 | endif 123 | endif 124 | 125 | endif 126 | 127 | 128 | LUA_CFL += $(LUA_CFLAGS) 129 | 130 | 131 | all: nfqws2 132 | 133 | nfqws2: $(SRC_FILES) 134 | $(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) 135 | 136 | systemd: $(SRC_FILES) 137 | $(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS) 138 | 139 | android: $(SRC_FILES) 140 | $(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID) 141 | 142 | bsd: $(SRC_FILES) 143 | $(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS) 144 | 145 | cygwin64: 146 | $(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS) 147 | cygwin32: 148 | $(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS) 149 | cygwin: cygwin64 150 | 151 | clean: 152 | rm -f nfqws2 dvtws2 winws2.exe 153 | -------------------------------------------------------------------------------- /nfq2/lua.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef LUAJIT 7 | #include "luajit.h" 8 | #else 9 | #include 10 | #endif 11 | #include 12 | #include 13 | 14 | #include "pools.h" 15 | #include "conntrack.h" 16 | #include "darkmagic.h" 17 | 18 | #if LUA_VERSION_NUM < 503 19 | #define lua_isinteger lua_isnumber 20 | #endif 21 | #ifndef LUA_UNSIGNED 22 | #define LUA_UNSIGNED uint64_t 23 | #endif 24 | 25 | // in old lua integer is 32 bit on 32 bit platforms and 64 bit on 64 bit platforms 26 | #if LUA_VERSION_NUM < 503 && __SIZEOF_POINTER__==4 27 | #define lua_pushlint lua_pushnumber 28 | #define lua_tolint lua_tonumber 29 | #define luaL_checklint luaL_checknumber 30 | #else 31 | #define lua_pushlint lua_pushinteger 32 | #define luaL_checklint luaL_checkinteger 33 | #define lua_tolint lua_tointeger 34 | #endif 35 | 36 | // pushing and not popping inside luacall cause memory leak 37 | // these macros ensure correct stack position or throw error if not 38 | #define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L); 39 | #define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure"); 40 | #define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N; 41 | 42 | 43 | void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size); 44 | 45 | 46 | bool lua_test_init_script_files(void); 47 | bool lua_init(void); 48 | void lua_shutdown(void); 49 | void lua_dlog_error(void); 50 | void lua_do_gc(void); 51 | 52 | #if LUA_VERSION_NUM < 502 53 | int lua_absindex(lua_State *L, int idx); 54 | #define lua_rawlen lua_objlen 55 | #endif 56 | 57 | // push - create object and push to the stack 58 | // pushf - create object and set it as a named field of a table already present on the stack 59 | // pushi - create object and set it as a index field of a table already present on the stack 60 | void lua_pushf_nil(const char *field); 61 | void lua_pushi_nil(lua_Integer idx); 62 | void lua_pushf_bool(const char *field, bool b); 63 | void lua_pushi_bool(lua_Integer idx, bool b); 64 | void lua_pushf_str(const char *field, const char *str); 65 | void lua_pushi_str(lua_Integer idx, const char *str); 66 | void lua_pushf_lstr(const char *field, const char *str, size_t len); 67 | void lua_pushi_lstr(lua_Integer idx, const char *str, size_t len); 68 | void lua_pushf_int(const char *field, lua_Integer v); 69 | void lua_pushi_int(lua_Integer idx, lua_Integer v); 70 | void lua_pushf_lint(const char *field, int64_t v); 71 | void lua_pushi_lint(lua_Integer idx, int64_t v); 72 | void lua_pushf_number(const char *field, lua_Number v); 73 | void lua_pushi_number(lua_Integer idx, lua_Number v); 74 | void lua_push_raw(const void *v, size_t l); 75 | void lua_pushf_raw(const char *field, const void *v, size_t l); 76 | void lua_pushi_raw(lua_Integer idx, const void *v, size_t l); 77 | void lua_pushf_reg(const char *field, int ref); 78 | void lua_pushf_lud(const char *field, void *p); 79 | void lua_pushf_table(const char *field); 80 | void lua_pushi_table(lua_Integer idx); 81 | 82 | void lua_push_blob(int idx_desync, const char *blob); 83 | void lua_pushf_blob(int idx_desync, const char *field, const char *blob); 84 | 85 | void lua_pushf_tcphdr_options(const struct tcphdr *tcp, size_t len); 86 | void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len); 87 | void lua_pushf_udphdr(const struct udphdr *udp, size_t len); 88 | void lua_pushf_iphdr(const struct ip *ip, size_t len); 89 | void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len); 90 | void lua_push_dissect(const struct dissect *dis); 91 | void lua_pushf_dissect(const struct dissect *dis); 92 | void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming); 93 | void lua_pushf_args(const struct str2_list_head *args, int idx_desync, bool subst_prefix); 94 | void lua_pushf_pos(const char *name, const struct packet_pos *pos); 95 | void lua_pushf_range(const char *name, const struct packet_range *range); 96 | void lua_pushf_global(const char *field, const char *global); 97 | 98 | bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next); 99 | bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len); 100 | bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len); 101 | bool lua_reconstruct_udphdr(int idx, struct udphdr *udp); 102 | bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next); 103 | 104 | #define MAGIC_CTX 0xE73DC935 105 | typedef struct { 106 | uint32_t magic; 107 | unsigned int func_n; 108 | const char *func, *instance; 109 | const struct desync_profile *dp; 110 | const struct dissect *dis; 111 | t_ctrack *ctrack; 112 | bool incoming,cancel; 113 | } t_lua_desync_context; 114 | 115 | bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn); 116 | -------------------------------------------------------------------------------- /nfq2/conntrack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // this conntrack is not bullet-proof 5 | // its designed to satisfy dpi desync needs only 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define __FAVOR_BSD 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "conntrack_base.h" 20 | #include "packet_queue.h" 21 | #include "protocol.h" 22 | 23 | //#define HASH_BLOOM 20 24 | #define HASH_NONFATAL_OOM 1 25 | #undef HASH_FUNCTION 26 | #define HASH_FUNCTION HASH_BER 27 | #include "uthash.h" 28 | 29 | #define RETRANS_COUNTER_STOP ((uint8_t)-1) 30 | 31 | typedef union { 32 | struct in_addr ip; 33 | struct in6_addr ip6; 34 | } t_addr; 35 | typedef struct 36 | { 37 | t_addr src, dst; 38 | uint16_t sport,dport; 39 | uint8_t l3proto; // IPPROTO_IP, IPPROTO_IPV6 40 | uint8_t l4proto; // IPPROTO_TCP, IPPROTO_UDP 41 | } t_conn; 42 | 43 | // this structure helps to reassemble continuous packets streams. it does not support out-of-orders 44 | typedef struct { 45 | uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size. 46 | uint32_t seq; // current seq number. if a packet comes with unsupported seq overlap - it fails reassemble session. 47 | size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet' 48 | size_t size_present; // how many bytes already stored in 'packet' 49 | } t_reassemble; 50 | 51 | 52 | typedef struct 53 | { 54 | bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache 55 | uint8_t ipproto; 56 | 57 | struct timespec t_start; 58 | 59 | // this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay 60 | t_ctrack_positions pos; 61 | 62 | struct desync_profile *dp; // desync profile cache 63 | bool dp_search_complete; 64 | 65 | uint8_t req_retrans_counter; // number of request retransmissions 66 | bool failure_detect_finalized; 67 | 68 | uint8_t incoming_ttl; 69 | 70 | bool b_cutoff; // mark for deletion 71 | bool b_lua_in_cutoff,b_lua_out_cutoff; 72 | 73 | t_l7proto l7proto; 74 | bool l7proto_discovered; 75 | char *hostname; 76 | bool hostname_is_ip; 77 | bool hostname_discovered; 78 | bool hostname_ah_check; // should perform autohostlist checks 79 | 80 | int lua_state; // registry index of associated LUA object 81 | int lua_instance_cutoff; // registry index of per connection function instance cutoff table 82 | 83 | t_reassemble reasm_client; 84 | struct rawpacket_tailhead delayed; 85 | } t_ctrack; 86 | 87 | typedef struct 88 | { 89 | t_ctrack track; 90 | UT_hash_handle hh; // makes this structure hashable 91 | t_conn conn; // key 92 | } t_conntrack_pool; 93 | typedef struct 94 | { 95 | // inactivity time to purge an entry in each connection state 96 | uint32_t timeout_syn,timeout_established,timeout_fin,timeout_udp; 97 | time_t t_purge_interval, t_last_purge; 98 | t_conntrack_pool *pool; 99 | } t_conntrack; 100 | 101 | void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp); 102 | void ConntrackPoolDestroy(t_conntrack *p); 103 | bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse); 104 | // do not create, do not update. only find existing 105 | bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse); 106 | bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); 107 | void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); 108 | void ConntrackPoolDump(const t_conntrack *p); 109 | void ConntrackPoolPurge(t_conntrack *p); 110 | void ConntrackClearHostname(t_ctrack *track); 111 | 112 | bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start); 113 | bool ReasmResize(t_reassemble *reasm, size_t new_size); 114 | void ReasmClear(t_reassemble *reasm); 115 | // false means reassemble session has failed and we should ReasmClear() it 116 | bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len); 117 | // check if it has enough space to buffer 'len' bytes 118 | bool ReasmHasSpace(t_reassemble *reasm, size_t len); 119 | inline static bool ReasmIsEmpty(t_reassemble *reasm) {return !reasm->size;} 120 | inline static bool ReasmIsFull(t_reassemble *reasm) {return !ReasmIsEmpty(reasm) && (reasm->size==reasm->size_present);} 121 | -------------------------------------------------------------------------------- /init.d/sysv/functions: -------------------------------------------------------------------------------- 1 | # init script functions library for desktop linux systems 2 | 3 | ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2} 4 | ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"} 5 | ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} 6 | . "$ZAPRET_CONFIG" 7 | . "$ZAPRET_BASE/common/base.sh" 8 | . "$ZAPRET_BASE/common/fwtype.sh" 9 | . "$ZAPRET_BASE/common/linux_iphelper.sh" 10 | . "$ZAPRET_BASE/common/ipt.sh" 11 | . "$ZAPRET_BASE/common/nft.sh" 12 | . "$ZAPRET_BASE/common/linux_fw.sh" 13 | . "$ZAPRET_BASE/common/linux_daemons.sh" 14 | . "$ZAPRET_BASE/common/list.sh" 15 | . "$ZAPRET_BASE/common/custom.sh" 16 | CUSTOM_DIR="$ZAPRET_RW/init.d/sysv" 17 | 18 | 19 | user_exists() 20 | { 21 | id -u $1 >/dev/null 2>/dev/null 22 | } 23 | useradd_compat() 24 | { 25 | # $1 - username 26 | # skip for readonly systems 27 | [ -w "/etc" ] && { 28 | if exists useradd ; then 29 | useradd --no-create-home --system --shell /bin/false $1 30 | elif is_linked_to_busybox adduser ; then 31 | # some systems may miss nogroup group in /etc/group 32 | # adduser fails if it's absent and no group is specified 33 | addgroup nogroup 2>/dev/null 34 | # busybox has special adduser syntax 35 | adduser -S -H -D $1 36 | elif exists adduser; then 37 | adduser --no-create-home --system --disabled-login $1 38 | fi 39 | } 40 | user_exists $1 41 | } 42 | prepare_user() 43 | { 44 | user_exists $WS_USER || { 45 | # fallback to daemon if we cant add WS_USER 46 | useradd_compat $WS_USER || { 47 | for user in daemon nobody; do 48 | user_exists $user && { 49 | WS_USER=$user 50 | return 0 51 | } 52 | done 53 | return 1 54 | } 55 | } 56 | } 57 | 58 | # this complex user selection allows to survive in any locked/readonly/minimalistic environment 59 | [ -n "$WS_USER" ] || WS_USER=tpws 60 | if prepare_user; then 61 | USEROPT="--user=$WS_USER" 62 | else 63 | WS_USER=1 64 | USEROPT="--uid $WS_USER:$WS_USER" 65 | fi 66 | 67 | PIDDIR=/var/run 68 | IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh" 69 | 70 | DESYNC_MARK=${DESYNC_MARK:-0x40000000} 71 | DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000} 72 | 73 | QNUM=${QNUM:-300} 74 | NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}" 75 | LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua" 76 | NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT" 77 | 78 | 79 | fw_nfqws_post4() 80 | { 81 | _fw_nfqws_post4 $1 "$2" $3 "$IFACE_WAN" 82 | } 83 | fw_nfqws_post6() 84 | { 85 | _fw_nfqws_post6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}" 86 | } 87 | fw_nfqws_pre4() 88 | { 89 | _fw_nfqws_pre4 $1 "$2" $3 "$IFACE_WAN" 90 | } 91 | fw_nfqws_pre6() 92 | { 93 | _fw_nfqws_pre6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}" 94 | } 95 | nft_fw_nfqws_post4() 96 | { 97 | _nft_fw_nfqws_post4 "$1" $2 "$IFACE_WAN" 98 | } 99 | nft_fw_nfqws_post6() 100 | { 101 | _nft_fw_nfqws_post6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}" 102 | } 103 | nft_fw_nfqws_pre4() 104 | { 105 | _nft_fw_nfqws_pre4 "$1" $2 "$IFACE_WAN" 106 | } 107 | nft_fw_nfqws_pre6() 108 | { 109 | _nft_fw_nfqws_pre6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}" 110 | } 111 | 112 | nft_wanif_filter_present() 113 | { 114 | [ -n "$IFACE_WAN" ] 115 | } 116 | nft_wanif6_filter_present() 117 | { 118 | [ -n "${IFACE_WAN6:-$IFACE_WAN}" ] 119 | } 120 | nft_fill_ifsets_overload() 121 | { 122 | nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN" 123 | } 124 | 125 | 126 | run_daemon() 127 | { 128 | # $1 - daemon number : 1,2,3,... 129 | # $2 - daemon 130 | # $3 - daemon args 131 | # use $PIDDIR/$DAEMONBASE$1.pid as pidfile 132 | 133 | local DAEMONBASE="$(basename "$2")" 134 | local PID= PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid 135 | echo "Starting daemon $1: $2 $3" 136 | 137 | [ -f "$PIDFILE" ] && { 138 | read PID <"$PIDFILE" 139 | [ -d "/proc/$PID" ] || PID= 140 | } 141 | 142 | if [ -n "$PID" ]; then 143 | echo already running 144 | else 145 | "$2" $3 >/dev/null & 146 | PID=$! 147 | if [ -n "$PID" ]; then 148 | echo $PID >$PIDFILE 149 | else 150 | echo could not start daemon $1 : $2 $3 151 | false 152 | fi 153 | fi 154 | } 155 | stop_daemon() 156 | { 157 | # $1 - daemon number : 1,2,3,... 158 | # $2 - daemon 159 | # use $PIDDIR/$DAEMONBASE$1.pid as pidfile 160 | local DAEMONBASE="$(basename "$2")" 161 | local PID PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid 162 | echo "Stopping daemon $1: $2" 163 | if [ -f "$PIDFILE" ]; then 164 | read PID <"$PIDFILE" 165 | kill $PID 166 | rm -f "$PIDFILE" 167 | else 168 | echo no pidfile : $PIDFILE 169 | fi 170 | } 171 | do_daemon() 172 | { 173 | # $1 - 1 - run, 0 - stop 174 | on_off_function run_daemon stop_daemon "$@" 175 | } 176 | 177 | do_nfqws() 178 | { 179 | # $1 : 1 - run, 0 - stop 180 | # $2 : daemon number 181 | # $3 : daemon args 182 | 183 | do_daemon $1 $2 "$NFQWS2" "$NFQWS2_OPT_BASE $3" 184 | } 185 | 186 | 187 | create_ipset() 188 | { 189 | echo "Creating ip list table (firewall type $FWTYPE)" 190 | "$IPSET_CR" "$@" 191 | } 192 | -------------------------------------------------------------------------------- /nfq2/checksum.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "checksum.h" 3 | #include 4 | 5 | //#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) 6 | //#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) 7 | 8 | static uint16_t from64to16(uint64_t x) 9 | { 10 | uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48); 11 | return (uint16_t)u + (uint16_t)(u>>16); 12 | } 13 | 14 | // this function preserves data alignment requirements (otherwise it will be damn slow on mips arch) 15 | // and uses 64-bit arithmetics to improve speed 16 | // taken from linux source code 17 | static uint16_t do_csum(const uint8_t * buff, size_t len) 18 | { 19 | uint8_t odd; 20 | size_t count; 21 | uint64_t result,w,carry=0; 22 | uint16_t u16; 23 | 24 | if (!len) return 0; 25 | odd = (uint8_t)(1 & (size_t)buff); 26 | if (odd) 27 | { 28 | // any endian compatible 29 | u16 = 0; 30 | *((uint8_t*)&u16+1) = *buff; 31 | result = u16; 32 | len--; 33 | buff++; 34 | } 35 | else 36 | result = 0; 37 | count = len >> 1; /* nr of 16-bit words.. */ 38 | if (count) 39 | { 40 | if (2 & (size_t) buff) 41 | { 42 | result += *(uint16_t *) buff; 43 | count--; 44 | len -= 2; 45 | buff += 2; 46 | } 47 | count >>= 1; /* nr of 32-bit words.. */ 48 | if (count) 49 | { 50 | if (4 & (size_t) buff) 51 | { 52 | result += *(uint32_t *) buff; 53 | count--; 54 | len -= 4; 55 | buff += 4; 56 | } 57 | count >>= 1; /* nr of 64-bit words.. */ 58 | if (count) 59 | { 60 | do 61 | { 62 | w = *(uint64_t *) buff; 63 | count--; 64 | buff += 8; 65 | result += carry; 66 | result += w; 67 | carry = (w > result); 68 | } while (count); 69 | result += carry; 70 | result = (result & 0xffffffff) + (result >> 32); 71 | } 72 | if (len & 4) 73 | { 74 | result += *(uint32_t *) buff; 75 | buff += 4; 76 | } 77 | } 78 | if (len & 2) 79 | { 80 | result += *(uint16_t *) buff; 81 | buff += 2; 82 | } 83 | } 84 | if (len & 1) 85 | { 86 | // any endian compatible 87 | u16 = 0; 88 | *(uint8_t*)&u16 = *buff; 89 | result += u16; 90 | } 91 | u16 = from64to16(result); 92 | if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8); 93 | return u16; 94 | } 95 | 96 | uint16_t csum_partial(const void *buff, size_t len) 97 | { 98 | return do_csum(buff,len); 99 | } 100 | 101 | uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum) 102 | { 103 | return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto)); 104 | } 105 | 106 | uint16_t ip4_compute_csum(const void *buff, size_t len) 107 | { 108 | return ~from64to16(do_csum(buff,len)); 109 | } 110 | void ip4_fix_checksum(struct ip *ip) 111 | { 112 | ip->ip_sum = 0; 113 | ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl<<2); 114 | } 115 | 116 | uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum) 117 | { 118 | uint64_t a = (uint64_t)sum + htonl(len+proto) + 119 | *(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) + 120 | *(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3); 121 | return ~from64to16(a); 122 | } 123 | 124 | 125 | void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr) 126 | { 127 | tcp->th_sum = 0; 128 | tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_TCP,csum_partial(tcp,len)); 129 | } 130 | void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr) 131 | { 132 | tcp->th_sum = 0; 133 | tcp->th_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp,len)); 134 | } 135 | void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr) 136 | { 137 | if (ip) 138 | tcp4_fix_checksum(tcp, len, &ip->ip_src, &ip->ip_dst); 139 | else if (ip6hdr) 140 | tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst); 141 | } 142 | 143 | void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr) 144 | { 145 | udp->uh_sum = 0; 146 | udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_UDP,csum_partial(udp,len)); 147 | } 148 | void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr) 149 | { 150 | udp->uh_sum = 0; 151 | udp->uh_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_UDP,csum_partial(udp,len)); 152 | } 153 | void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr) 154 | { 155 | if (ip) 156 | udp4_fix_checksum(udp, len, &ip->ip_src, &ip->ip_dst); 157 | else if (ip6hdr) 158 | udp6_fix_checksum(udp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst); 159 | } 160 | -------------------------------------------------------------------------------- /nfq2/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define UNARY_PLUS(v) (v>0 ? "+" : "") 14 | 15 | // this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes. 16 | typedef union 17 | { 18 | struct sockaddr_in sa4; // size 16 19 | struct sockaddr_in6 sa6; // size 28 20 | char _align[32]; // force 16-byte alignment for ip6_and int128 ops 21 | } sockaddr_in46; 22 | 23 | int unique_size_t(size_t *pu, int ct); 24 | int unique_ssize_t(ssize_t *pu, int ct); 25 | void qsort_size_t(size_t *array, int ct); 26 | void qsort_ssize_t(ssize_t *array, int ct); 27 | 28 | int str_index(const char **strs, int count, const char *str); 29 | void rtrim(char *s); 30 | void replace_char(char *s, char from, char to); 31 | char *strncasestr(const char *s,const char *find, size_t slen); 32 | // [a-zA-z][a-zA-Z0-9]* 33 | bool is_identifier(const char *p); 34 | 35 | bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size); 36 | bool load_file_nonempty(const char *filename, off_t offset, void *buffer, size_t *buffer_size); 37 | bool save_file(const char *filename, const void *buffer, size_t buffer_size); 38 | bool append_to_list_file(const char *filename, const char *s); 39 | 40 | void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen); 41 | 42 | bool strip_host_to_ip(char *host); 43 | 44 | void print_sockaddr(const struct sockaddr *sa); 45 | void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6,char *str, size_t len); 46 | void ntop46(const struct sockaddr *sa, char *str, size_t len); 47 | void ntop46_port(const struct sockaddr *sa, char *str, size_t len); 48 | bool pton4_port(const char *s, struct sockaddr_in *sa); 49 | bool pton6_port(const char *s, struct sockaddr_in6 *sa); 50 | 51 | uint16_t saport(const struct sockaddr *sa); 52 | bool sa_has_addr(const struct sockaddr *sa); 53 | 54 | bool seq_within(uint32_t s, uint32_t s1, uint32_t s2); 55 | 56 | bool ipv6_addr_is_zero(const struct in6_addr *a); 57 | 58 | uint16_t pntoh16(const uint8_t *p); 59 | void phton16(uint8_t *p, uint16_t v); 60 | uint32_t pntoh24(const uint8_t *p); 61 | void phton24(uint8_t *p, uint32_t v); 62 | uint32_t pntoh32(const uint8_t *p); 63 | void phton32(uint8_t *p, uint32_t v); 64 | uint64_t pntoh64(const uint8_t *p); 65 | void phton64(uint8_t *p, uint64_t v); 66 | 67 | bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); 68 | char hex_digit(uint8_t v); 69 | 70 | int fprint_localtime(FILE *F); 71 | 72 | typedef struct 73 | { 74 | time_t mod_time; 75 | off_t size; 76 | } file_mod_sig; 77 | #define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size)) 78 | #define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig)) 79 | bool file_mod_signature(const char *filename, file_mod_sig *ms); 80 | time_t file_mod_time(const char *filename); 81 | bool file_size(const char *filename, off_t *size); 82 | bool file_open_test(const char *filename, int flags); 83 | 84 | typedef struct 85 | { 86 | uint16_t from,to; 87 | bool neg; 88 | } port_filter; 89 | bool pf_in_range(uint16_t port, const port_filter *pf); 90 | bool pf_parse(const char *s, port_filter *pf); 91 | bool pf_is_empty(const port_filter *pf); 92 | 93 | struct packet_pos 94 | { 95 | char mode; // n - packets, d - data packets, s - relative sequence 96 | unsigned int pos; 97 | }; 98 | struct packet_range 99 | { 100 | struct packet_pos from, to; 101 | bool upper_cutoff; // true - do not include upper limit, false - include upper limit 102 | }; 103 | #define PACKET_POS_NEVER (struct packet_pos){'x',0} 104 | #define PACKET_POS_ALWAYS (struct packet_pos){'a',0} 105 | #define PACKET_RANGE_NEVER (struct packet_range){PACKET_POS_NEVER,PACKET_POS_NEVER} 106 | #define PACKET_RANGE_ALWAYS (struct packet_range){PACKET_POS_ALWAYS,PACKET_POS_ALWAYS} 107 | bool packet_range_parse(const char *s, struct packet_range *range); 108 | 109 | void fill_random_bytes(uint8_t *p,size_t sz); 110 | void fill_random_az(uint8_t *p,size_t sz); 111 | void fill_random_az09(uint8_t *p,size_t sz); 112 | bool fill_crypto_random_bytes(uint8_t *p,size_t sz); 113 | 114 | void set_console_io_buffering(void); 115 | bool set_env_exedir(const char *argv0); 116 | 117 | 118 | struct cidr4 119 | { 120 | struct in_addr addr; 121 | uint8_t preflen; 122 | }; 123 | struct cidr6 124 | { 125 | struct in6_addr addr; 126 | uint8_t preflen; 127 | }; 128 | void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr); 129 | void print_cidr4(const struct cidr4 *cidr); 130 | void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr); 131 | void print_cidr6(const struct cidr6 *cidr); 132 | bool parse_cidr4(char *s, struct cidr4 *cidr); 133 | bool parse_cidr6(char *s, struct cidr6 *cidr); 134 | 135 | bool parse_int16(const char *p, int16_t *v); 136 | 137 | static inline uint32_t mask_from_preflen(uint32_t preflen) 138 | { 139 | return preflen ? preflen<32 ? ~((1 << (32-preflen)) - 1) : 0xFFFFFFFF : 0; 140 | } 141 | void ip6_and(const struct in6_addr * restrict a, const struct in6_addr * restrict b, struct in6_addr * restrict result); 142 | extern struct in6_addr ip6_mask[129]; 143 | void mask_from_preflen6_prepare(void); 144 | static inline const struct in6_addr *mask_from_preflen6(uint8_t preflen) 145 | { 146 | return ip6_mask+preflen; 147 | } 148 | -------------------------------------------------------------------------------- /nfq2/crypto/usha.c: -------------------------------------------------------------------------------- 1 | /**************************** usha.c ***************************/ 2 | /***************** See RFC 6234 for details. *******************/ 3 | /* Copyright (c) 2011 IETF Trust and the persons identified as */ 4 | /* authors of the code. All rights reserved. */ 5 | /* See sha.h for terms of use and redistribution. */ 6 | 7 | /* 8 | * Description: 9 | * This file implements a unified interface to the SHA algorithms. 10 | */ 11 | 12 | #include "sha.h" 13 | 14 | /* 15 | * USHAReset 16 | * 17 | * Description: 18 | * This function will initialize the SHA Context in preparation 19 | * for computing a new SHA message digest. 20 | * 21 | * Parameters: 22 | * context: [in/out] 23 | * The context to reset. 24 | * whichSha: [in] 25 | * Selects which SHA reset to call 26 | * 27 | * Returns: 28 | * sha Error Code. 29 | * 30 | */ 31 | int USHAReset(USHAContext *context, enum SHAversion whichSha) 32 | { 33 | if (!context) return shaNull; 34 | context->whichSha = whichSha; 35 | switch (whichSha) { 36 | case SHA224: return SHA224Reset((SHA224Context*)&context->ctx); 37 | case SHA256: return SHA256Reset((SHA256Context*)&context->ctx); 38 | default: return shaBadParam; 39 | } 40 | } 41 | 42 | /* 43 | * USHAInput 44 | * 45 | * Description: 46 | * This function accepts an array of octets as the next portion 47 | * of the message. 48 | * 49 | * Parameters: 50 | * context: [in/out] 51 | * The SHA context to update. 52 | * message_array: [in] 53 | * An array of octets representing the next portion of 54 | * the message. 55 | * length: [in] 56 | * The length of the message in message_array. 57 | * 58 | * Returns: 59 | * sha Error Code. 60 | * 61 | */ 62 | int USHAInput(USHAContext *context, 63 | const uint8_t *bytes, unsigned int bytecount) 64 | { 65 | if (!context) return shaNull; 66 | switch (context->whichSha) { 67 | case SHA224: 68 | return SHA224Input((SHA224Context*)&context->ctx, bytes, 69 | bytecount); 70 | case SHA256: 71 | return SHA256Input((SHA256Context*)&context->ctx, bytes, 72 | bytecount); 73 | default: return shaBadParam; 74 | } 75 | } 76 | 77 | /* 78 | * USHAFinalBits 79 | * 80 | * Description: 81 | * This function will add in any final bits of the message. 82 | * 83 | * Parameters: 84 | * context: [in/out] 85 | * The SHA context to update. 86 | * message_bits: [in] 87 | * The final bits of the message, in the upper portion of the 88 | * byte. (Use 0b###00000 instead of 0b00000### to input the 89 | * three bits ###.) 90 | * length: [in] 91 | * The number of bits in message_bits, between 1 and 7. 92 | * 93 | * Returns: 94 | * sha Error Code. 95 | */ 96 | int USHAFinalBits(USHAContext *context, 97 | uint8_t bits, unsigned int bit_count) 98 | { 99 | if (!context) return shaNull; 100 | switch (context->whichSha) { 101 | case SHA224: 102 | return SHA224FinalBits((SHA224Context*)&context->ctx, bits, 103 | bit_count); 104 | case SHA256: 105 | return SHA256FinalBits((SHA256Context*)&context->ctx, bits, 106 | bit_count); 107 | default: return shaBadParam; 108 | } 109 | } 110 | 111 | /* 112 | * USHAResult 113 | * 114 | * Description: 115 | * This function will return the message digest of the appropriate 116 | * bit size, as returned by USHAHashSizeBits(whichSHA) for the 117 | * 'whichSHA' value used in the preceeding call to USHAReset, 118 | * into the Message_Digest array provided by the caller. 119 | * 120 | * Parameters: 121 | * context: [in/out] 122 | * The context to use to calculate the SHA-1 hash. 123 | * Message_Digest: [out] 124 | * Where the digest is returned. 125 | * 126 | * Returns: 127 | * sha Error Code. 128 | * 129 | */ 130 | int USHAResult(USHAContext *context, 131 | uint8_t Message_Digest[USHAMaxHashSize]) 132 | { 133 | if (!context) return shaNull; 134 | switch (context->whichSha) { 135 | case SHA224: 136 | return SHA224Result((SHA224Context*)&context->ctx, 137 | Message_Digest); 138 | case SHA256: 139 | return SHA256Result((SHA256Context*)&context->ctx, 140 | Message_Digest); 141 | default: return shaBadParam; 142 | } 143 | } 144 | 145 | /* 146 | * USHABlockSize 147 | * 148 | * Description: 149 | * This function will return the blocksize for the given SHA 150 | * algorithm. 151 | * 152 | * Parameters: 153 | * whichSha: 154 | * which SHA algorithm to query 155 | * 156 | * Returns: 157 | * block size 158 | * 159 | */ 160 | int USHABlockSize(enum SHAversion whichSha) 161 | { 162 | switch (whichSha) { 163 | case SHA224: return SHA224_Message_Block_Size; 164 | default: 165 | case SHA256: return SHA256_Message_Block_Size; 166 | } 167 | } 168 | 169 | /* 170 | * USHAHashSize 171 | * 172 | * Description: 173 | * This function will return the hashsize for the given SHA 174 | * algorithm. 175 | * 176 | * Parameters: 177 | * whichSha: 178 | * which SHA algorithm to query 179 | * 180 | * Returns: 181 | * hash size 182 | * 183 | */ 184 | int USHAHashSize(enum SHAversion whichSha) 185 | { 186 | switch (whichSha) { 187 | case SHA224: return SHA224HashSize; 188 | default: 189 | case SHA256: return SHA256HashSize; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /install_bin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | EXEDIR="$(dirname "$0")" 4 | EXEDIR="$(cd "$EXEDIR"; pwd)" 5 | BINS=binaries 6 | BINDIR="$EXEDIR/$BINS" 7 | 8 | ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"} 9 | . "$ZAPRET_BASE/common/base.sh" 10 | 11 | 12 | read_elf_arch() 13 | { 14 | # $1 - elf file 15 | 16 | local arch=$(dd if="$1" count=2 bs=1 skip=18 2>/dev/null | hexdump -e '2/1 "%02x"') 17 | local bit=$(dd if="$1" count=1 bs=1 skip=4 2>/dev/null | hexdump -e '1/1 "%02x"') 18 | echo $bit$arch 19 | } 20 | 21 | select_test_method() 22 | { 23 | local f ELF 24 | 25 | TEST=run 26 | 27 | # ash and dash try to execute invalid executables as a script. they interpret binary garbage with possible negative consequences 28 | # bash and zsh do not do this 29 | if exists bash; then 30 | TEST=bash 31 | elif exists zsh && [ "$UNAME" != CYGWIN ] ; then 32 | TEST=zsh 33 | elif [ "$UNAME" != CYGWIN ]; then 34 | if exists hexdump and exists dd; then 35 | # macos does not use ELF 36 | TEST=elf 37 | ELF= 38 | ELF_ARCH= 39 | for f in /bin/sh /system/bin/sh; do 40 | [ -x "$f" ] && { 41 | ELF=$f 42 | break 43 | } 44 | done 45 | [ -n "$ELF" ] && ELF_ARCH=$(read_elf_arch "$ELF") 46 | [ -n "$ELF_ARCH" ] && return 47 | fi 48 | 49 | # find does not use its own shell exec 50 | # it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh 51 | # that's why prefer bash or zsh if present. otherwise it's our last chance 52 | if exists find; then 53 | TEST=find 54 | FIND=find 55 | elif exists busybox; then 56 | busybox find /jGHUa3fh1A 2>/dev/null 57 | # 127 - command not found 58 | [ "$?" = 127 ] || { 59 | TEST=find 60 | FIND="busybox find" 61 | } 62 | fi 63 | fi 64 | 65 | } 66 | 67 | check_dir() 68 | { 69 | local dir="$BINDIR/$1" 70 | local exe="$dir/ip2net" 71 | local out 72 | if [ -f "$exe" ]; then 73 | if [ -x "$exe" ]; then 74 | case $TEST in 75 | bash) 76 | out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null) 77 | [ -n "$out" ] 78 | ;; 79 | zsh) 80 | out=$(echo 0.0.0.0 | zsh -c "\"$exe\"" 2>/dev/null) 81 | [ -n "$out" ] 82 | ;; 83 | elf) 84 | out=$(read_elf_arch "$exe") 85 | [ "$ELF_ARCH" = "$out" ] && { 86 | # exec test to verify it actually works. no illegal instruction or crash. 87 | out=$(echo 0.0.0.0 | "$exe" 2>/dev/null) 88 | [ -n "$out" ] 89 | } 90 | ;; 91 | find) 92 | out=$(echo 0.0.0.0 | $FIND "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null) 93 | [ -n "$out" ] 94 | ;; 95 | run) 96 | out=$(echo 0.0.0.0 | "$exe" 2>/dev/null) 97 | [ -n "$out" ] 98 | ;; 99 | *) 100 | false 101 | ;; 102 | esac 103 | else 104 | echo >&2 "$exe is not executable. set proper chmod." 105 | return 1 106 | fi 107 | else 108 | echo >&2 "$exe is absent" 109 | return 2 110 | fi 111 | } 112 | 113 | # link or copy executables. uncomment either ln or cp, comment other 114 | ccp() 115 | { 116 | local F="$(basename "$1")" 117 | [ -d "$ZAPRET_BASE/$2" ] || mkdir "$ZAPRET_BASE/$2" 118 | [ -f "$ZAPRET_BASE/$2/$F" ] && rm -f "$ZAPRET_BASE/$2/$F" 119 | ln -fs "../$BINS/$1" "$ZAPRET_BASE/$2" && echo linking : "../$BINS/$1" =\> "$ZAPRET_BASE/$2" 120 | #cp -f "../$BINS/$1" "$ZAPRET_BASE/$2" && echo copying : "../$BINS/$1" =\> "$ZAPRET_BASE/$2" 121 | } 122 | 123 | 124 | UNAME=$(uname) 125 | 126 | [ "$1" = getarch ] || 127 | if [ ! -d "$BINDIR" ] || ! dir_is_not_empty "$BINDIR" ]; then 128 | echo "no binaries found" 129 | case $UNAME in 130 | Linux) 131 | echo "you need to download release from github or build binaries from source" 132 | echo "building from source requires debian/ubuntu packages : make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev libluajit2-5.1-dev" 133 | echo "libsystemd-dev required only on systemd based systems" 134 | echo "on distributions with other package manager find dev package analogs" 135 | echo "to compile on systems with systemd : make systemd" 136 | echo "to compile on other systems : make" 137 | ;; 138 | Darwin) 139 | echo "macos is not supported" 140 | ;; 141 | FreeBSD) 142 | echo "you need to download release from github or build binaries from source" 143 | echo "to compile : make" 144 | ;; 145 | OpenBSD) 146 | echo "to compile : make bsd" 147 | ;; 148 | CYGWIN*) 149 | echo "you need to download release from github or build binaries from source" 150 | echo "to compile : read docs" 151 | echo "to make things easier use zapret-win-bundle" 152 | ;; 153 | esac 154 | exit 1 155 | fi 156 | 157 | unset PKTWS 158 | case $UNAME in 159 | Linux) 160 | ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc" 161 | PKTWS=nfqws2 162 | ;; 163 | FreeBSD) 164 | ARCHLIST="my freebsd-x86_64" 165 | PKTWS=dvtws2 166 | ;; 167 | CYGWIN*) 168 | UNAME=CYGWIN 169 | ARCHLIST="windows-x86_64 windows-x86" 170 | PKTWS=winws2 171 | ;; 172 | *) 173 | ARCHLIST="my" 174 | esac 175 | 176 | select_test_method 177 | 178 | if [ "$1" = "getarch" ]; then 179 | for arch in $ARCHLIST 180 | do 181 | [ -d "$BINDIR/$arch" ] || continue 182 | if check_dir $arch; then 183 | echo $arch 184 | exit 0 185 | fi 186 | done 187 | else 188 | echo "using arch detect method : $TEST${ELF_ARCH:+ $ELF_ARCH}" 189 | 190 | for arch in $ARCHLIST 191 | do 192 | [ -d "$BINDIR/$arch" ] || continue 193 | if check_dir $arch; then 194 | echo $arch is OK 195 | echo installing binaries ... 196 | ccp $arch/ip2net ip2net 197 | ccp $arch/mdig mdig 198 | [ -n "$PKTWS" ] && ccp $arch/$PKTWS nfq2 199 | exit 0 200 | else 201 | echo $arch is NOT OK 202 | fi 203 | done 204 | echo no compatible binaries found 205 | fi 206 | 207 | exit 1 208 | -------------------------------------------------------------------------------- /config.default: -------------------------------------------------------------------------------- 1 | # this file is included from init scripts 2 | # change values here 3 | 4 | # can help in case /tmp has not enough space 5 | #TMPDIR=/opt/zapret2/tmp 6 | 7 | # redefine user for zapret daemons. required on Keenetic 8 | #WS_USER=nobody 9 | 10 | # override firewall type : iptables,nftables,ipfw 11 | #FWTYPE=iptables 12 | # nftables only : set this to 0 to use pre-nat mode. default is post-nat. 13 | # pre-nat mode disables some bypass techniques for forwarded traffic but allows to see client IP addresses in debug log 14 | #POSTNAT=0 15 | 16 | # options for ipsets 17 | # maximum number of elements in sets. also used for nft sets 18 | SET_MAXELEM=522288 19 | # too low hashsize can cause memory allocation errors on low RAM systems , even if RAM is enough 20 | # too large hashsize will waste lots of RAM 21 | IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM" 22 | # dynamically generate additional ip. $1 = ipset/nfset/table name 23 | #IPSET_HOOK="/etc/zapret2.ipset.hook" 24 | 25 | # options for ip2net. "-4" or "-6" auto added by ipset create script 26 | IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4" 27 | IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5" 28 | # options for auto hostlist 29 | # NOTE : in order for these adjustment to work it's required to redirect enough starting packets 30 | # NOTE : set PKT_IN, PKT_OUT variables appropriately 31 | AUTOHOSTLIST_INCOMING_MAXSEQ=4096 32 | AUTOHOSTLIST_RETRANS_MAXSEQ=32768 33 | AUTOHOSTLIST_RETRANS_THRESHOLD=3 34 | AUTOHOSTLIST_FAIL_THRESHOLD=3 35 | AUTOHOSTLIST_FAIL_TIME=60 36 | AUTOHOSTLIST_UDP_IN=1 37 | AUTOHOSTLIST_UDP_OUT=4 38 | # 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log 39 | AUTOHOSTLIST_DEBUGLOG=0 40 | 41 | # number of parallel threads for domain list resolves 42 | MDIG_THREADS=30 43 | 44 | # ipset/*.sh can compress large lists 45 | GZIP_LISTS=1 46 | # command to reload ip/host lists after update 47 | # comment or leave empty for auto backend selection : ipset or ipfw if present 48 | # on BSD systems with PF no auto reloading happens. you must provide your own command 49 | # set to "-" to disable reload 50 | #LISTS_RELOAD="pfctl -f /etc/pf.conf" 51 | 52 | # mark bit used by nfqws to prevent loop 53 | DESYNC_MARK=0x40000000 54 | DESYNC_MARK_POSTNAT=0x20000000 55 | 56 | # do not pass outgoing traffic to tpws/nfqws not marked with this bit 57 | # this setting allows to write your own rules to limit traffic that should be fooled 58 | # for example based on source IP or incoming interface name 59 | # no filter if not defined 60 | #FILTER_MARK=0x10000000 61 | 62 | 63 | NFQWS2_ENABLE=0 64 | # redirect outgoing traffic with connbytes limiter applied in both directions. 65 | NFQWS2_PORTS_TCP=80,443 66 | NFQWS2_PORTS_UDP=443 67 | # PKT_OUT means connbytes dir original 68 | # PKT_IN means connbytes dir reply 69 | NFQWS2_TCP_PKT_OUT=20 70 | NFQWS2_TCP_PKT_IN=10 71 | NFQWS2_UDP_PKT_OUT=5 72 | NFQWS2_UDP_PKT_IN=3 73 | # redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter 74 | # normally it's needed only for stateless DPI that matches every packet in a single TCP session 75 | # typical example are plain HTTP keep alives 76 | # this mode can be very CPU consuming. enable with care ! 77 | #NFQWS2_PORTS_TCP_KEEPALIVE=80 78 | #NFQWS2_PORTS_UDP_KEEPALIVE= 79 | # use and placeholders to engage standard hostlists and autohostlist in ipset dir 80 | # hostlist markers are replaced to empty string if MODE_FILTER does not satisfy 81 | # appends ipset/zapret-hosts-auto.txt as normal list 82 | NFQWS2_OPT=" 83 | --filter-tcp=80 --filter-l7=http --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 --new 84 | --filter-tcp=443 --filter-l7=tls --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld --new 85 | --filter-udp=443 --filter-l7=quic --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6 86 | " 87 | 88 | # none,ipset,hostlist,autohostlist 89 | MODE_FILTER=none 90 | 91 | # donttouch,none,software,hardware 92 | FLOWOFFLOAD=donttouch 93 | 94 | # openwrt: specify networks to be treated as LAN. default is "lan" 95 | #OPENWRT_LAN="lan lan2 lan3" 96 | # openwrt: specify networks to be treated as WAN. default wans are interfaces with default route 97 | #OPENWRT_WAN4="wan vpn" 98 | #OPENWRT_WAN6="wan6 vpn6" 99 | 100 | # for routers based on desktop linux and macos. has no effect in openwrt. 101 | # CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES 102 | # or leave them commented if its not router 103 | # it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2" 104 | # if IFACE_WAN6 is not defined it take the value of IFACE_WAN 105 | #IFACE_WAN=eth1 106 | #IFACE_WAN6="ipsec0 wireguard0 he_net" 107 | 108 | # should start/stop command of init scripts apply firewall rules ? 109 | # not applicable to openwrt with firewall3+iptables 110 | INIT_APPLY_FW=1 111 | # firewall apply hooks 112 | #INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret2.hook.pre_up" 113 | #INIT_FW_POST_UP_HOOK="/etc/firewall.zapret2.hook.post_up" 114 | #INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret2.hook.pre_down" 115 | #INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret2.hook.post_down" 116 | 117 | # do not work with ipv4 118 | #DISABLE_IPV4=1 119 | # do not work with ipv6 120 | DISABLE_IPV6=1 121 | 122 | # drop icmp time exceeded messages for nfqws tampered connections 123 | # in POSTNAT mode this can interfere with default mtr/traceroute in tcp or udp mode. use source port not redirected to nfqws 124 | # set to 0 if you are not expecting connection breakage due to icmp in response to TCP SYN or UDP 125 | FILTER_TTL_EXPIRED_ICMP=1 126 | 127 | # select which init script will be used to get ip or host list 128 | # possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh 129 | # comment if not required 130 | #GETLIST= 131 | -------------------------------------------------------------------------------- /blockcheck2.d/standard/25-fake.sh: -------------------------------------------------------------------------------- 1 | . "$TESTDIR/def.inc" 2 | 3 | pktws_check_http() 4 | { 5 | # $1 - test function 6 | # $2 - domain 7 | [ "$NOTEST_FAKE_HTTP" = 1 ] && { echo "SKIPPED"; return; } 8 | 9 | local testf=$1 domain="$2" 10 | local ok ok_any ttls attls f ff fake fooling 11 | local PAYLOAD="--payload=http_req" 12 | 13 | if [ -n "$FAKE_HTTP" ]; then 14 | fake=fake_http 15 | else 16 | fake=fake_default_http 17 | fi 18 | 19 | need_fake=0 20 | 21 | ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL) 22 | attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA) 23 | 24 | ok_any=0 25 | ok=0 26 | for ttl in $ttls; do 27 | # orig-ttl=1 with start/cutoff limiter drops empty ACK packet in response to SYN,ACK. it does not reach DPI or server. 28 | # missing ACK is transmitted in the first data packet of TLS/HTTP proto 29 | for ff in $fake 0x00000000; do 30 | for f in '' "--payload=empty --out-range=s1/dev/null 40 | ipset flush $NFQWS_MY1_NAME4 41 | for subnet in $NFQWS_MY1_SUBNETS4; do 42 | echo add $NFQWS_MY1_NAME4 $subnet 43 | done | ipset -! restore 44 | } 45 | [ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && { 46 | ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null 47 | ipset flush $NFQWS_MY1_NAME6 48 | for subnet in $NFQWS_MY1_SUBNETS6; do 49 | echo add $NFQWS_MY1_NAME6 $subnet 50 | done | ipset -! restore 51 | } 52 | 53 | [ -n "$NFQWS_MY1_PORTS_TCP" ] && { 54 | [ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && { 55 | f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set" 56 | f6="$f4 $NFQWS_MY1_NAME6 dst" 57 | f4="$f4 $NFQWS_MY1_NAME4 dst" 58 | fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1 59 | } 60 | [ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && { 61 | f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set" 62 | f6="$f4 $NFQWS_MY1_NAME6 src" 63 | f4="$f4 $NFQWS_MY1_NAME4 src" 64 | fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1 65 | } 66 | } 67 | [ -n "$NFQWS_MY1_PORTS_UDP" ] && { 68 | [ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && { 69 | f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set" 70 | f6="$f4 $NFQWS_MY1_NAME6 dst" 71 | f4="$f4 $NFQWS_MY1_NAME4 dst" 72 | fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1 73 | } 74 | [ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && { 75 | f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set" 76 | f6="$f4 $NFQWS_MY1_NAME6 src" 77 | f4="$f4 $NFQWS_MY1_NAME4 src" 78 | fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1 79 | } 80 | } 81 | 82 | [ "$1" = 1 ] || { 83 | ipset destroy $NFQWS_MY1_NAME4 2>/dev/null 84 | ipset destroy $NFQWS_MY1_NAME6 2>/dev/null 85 | } 86 | } 87 | 88 | zapret_custom_firewall_nft() 89 | { 90 | local f4 f6 subnets 91 | local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT" 92 | 93 | [ "$DISABLE_IPV4" != 1 ] && { 94 | make_comma_list subnets $NFQWS_MY1_SUBNETS4 95 | nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;" 96 | nft_flush_set $NFQWS_MY1_NAME4 97 | nft_add_set_element $NFQWS_MY1_NAME4 "$subnets" 98 | } 99 | [ "$DISABLE_IPV6" != 1 ] && { 100 | make_comma_list subnets $NFQWS_MY1_SUBNETS6 101 | nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;" 102 | nft_flush_set $NFQWS_MY1_NAME6 103 | nft_add_set_element $NFQWS_MY1_NAME6 "$subnets" 104 | } 105 | 106 | [ -n "$NFQWS_MY1_PORTS_TCP" ] && { 107 | [ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && { 108 | f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)" 109 | f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6" 110 | f4="$f4 ip daddr @$NFQWS_MY1_NAME4" 111 | nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1 112 | } 113 | [ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && { 114 | f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)" 115 | f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6" 116 | f4="$f4 ip saddr @$NFQWS_MY1_NAME4" 117 | nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1 118 | } 119 | } 120 | [ -n "$NFQWS_MY1_PORTS_UDP" ] && { 121 | [ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && { 122 | f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)" 123 | f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6" 124 | f4="$f4 ip daddr @$NFQWS_MY1_NAME4" 125 | nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1 126 | } 127 | [ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && { 128 | f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)" 129 | f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6" 130 | f4="$f4 ip saddr @$NFQWS_MY1_NAME4" 131 | nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1 132 | } 133 | } 134 | } 135 | 136 | 137 | zapret_custom_firewall_nft_flush() 138 | { 139 | # this function is called after all nft fw rules are deleted 140 | # however sets are not deleted. it's desired to clear sets here. 141 | 142 | nft_del_set $NFQWS_MY1_NAME4 2>/dev/null 143 | nft_del_set $NFQWS_MY1_NAME6 2>/dev/null 144 | } 145 | -------------------------------------------------------------------------------- /init.d/openwrt/functions: -------------------------------------------------------------------------------- 1 | . /lib/functions/network.sh 2 | 3 | ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2} 4 | ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"} 5 | ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"} 6 | . "$ZAPRET_CONFIG" 7 | . "$ZAPRET_BASE/common/base.sh" 8 | . "$ZAPRET_BASE/common/fwtype.sh" 9 | . "$ZAPRET_BASE/common/linux_iphelper.sh" 10 | . "$ZAPRET_BASE/common/ipt.sh" 11 | . "$ZAPRET_BASE/common/nft.sh" 12 | . "$ZAPRET_BASE/common/linux_fw.sh" 13 | . "$ZAPRET_BASE/common/linux_daemons.sh" 14 | . "$ZAPRET_BASE/common/list.sh" 15 | . "$ZAPRET_BASE/common/custom.sh" 16 | CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt" 17 | 18 | QNUM=${QNUM:-300} 19 | WS_USER=${WS_USER:-daemon} 20 | DESYNC_MARK=${DESYNC_MARK:-0x40000000} 21 | DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000} 22 | OPENWRT_LAN=${OPENWRT_LAN:-lan} 23 | 24 | IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh" 25 | 26 | # can be multiple ipv6 outgoing interfaces 27 | # uplink from isp, tunnelbroker, vpn, ... 28 | # want them all. who knows what's the real one that blocks sites 29 | # dont want any manual configuration - want to do it automatically 30 | # standard network_find_wan[6] return only the first 31 | # we use low level function from network.sh to avoid this limitation 32 | # it can change theoretically and stop working 33 | 34 | network_find_wan4_all() 35 | { 36 | if [ -n "$OPENWRT_WAN4" ]; then 37 | eval $1="\$OPENWRT_WAN4" 38 | else 39 | __network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return 40 | network_find_wan $1 41 | fi 42 | } 43 | network_find_wan_all() 44 | { 45 | network_find_wan4_all "$@" 46 | } 47 | network_find_wan6_all() 48 | { 49 | if [ -n "$OPENWRT_WAN6" ]; then 50 | eval $1="\$OPENWRT_WAN6" 51 | else 52 | __network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return 53 | network_find_wan6 $1 54 | fi 55 | } 56 | network_find_wanX_devices() 57 | { 58 | # $1 - ip version: 4 or 6 59 | # $2 - variable to put result to 60 | local ifaces 61 | network_find_wan${1}_all ifaces 62 | call_for_multiple_items network_get_device $2 "$ifaces" 63 | } 64 | 65 | 66 | fw_nfqws_prepost_x() 67 | { 68 | # $1 - 1 - add, 0 - del 69 | # $2 - filter 70 | # $3 - queue number 71 | # $4 - 4/6 72 | # $5 - post/pre 73 | 74 | local ifaces DWAN 75 | network_find_wan${4}_all ifaces 76 | call_for_multiple_items network_get_device DWAN "$ifaces" 77 | 78 | [ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)" 79 | } 80 | fw_nfqws_post4() 81 | { 82 | fw_nfqws_prepost_x $1 "$2" $3 4 post 83 | } 84 | fw_nfqws_post6() 85 | { 86 | fw_nfqws_prepost_x $1 "$2" $3 6 post 87 | } 88 | fw_nfqws_pre4() 89 | { 90 | fw_nfqws_prepost_x $1 "$2" $3 4 pre 91 | } 92 | fw_nfqws_pre6() 93 | { 94 | fw_nfqws_prepost_x $1 "$2" $3 6 pre 95 | } 96 | 97 | create_ipset() 98 | { 99 | echo "Creating ip list table (firewall type $FWTYPE)" 100 | "$IPSET_CR" "$@" 101 | } 102 | 103 | list_nfqws_rules() 104 | { 105 | # $1 = '' for ipv4, '6' for ipv6 106 | ip$1tables -S POSTROUTING -t mangle | \ 107 | grep -E "NFQUEUE --queue-num $QNUM --queue-bypass|NFQUEUE --queue-num $(($QNUM+1)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+2)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+3)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+10)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+11)) --queue-bypass" | \ 108 | sed -re 's/^-A POSTROUTING (.*) -j NFQUEUE.*$/\1/' -e "s/-m mark ! --mark $DESYNC_MARK\/$DESYNC_MARK//" 109 | } 110 | apply_flow_offloading_enable_rule() 111 | { 112 | # $1 = '' for ipv4, '6' for ipv6 113 | local i off='-j FLOWOFFLOAD' 114 | [ "$FLOWOFFLOAD" = "hardware" ] && off="$off --hw" 115 | i="forwarding_rule_zapret -m comment --comment zapret_traffic_offloading_enable -m conntrack --ctstate RELATED,ESTABLISHED $off" 116 | echo enabling ipv${1:-4} flow offloading : $i 117 | ip$1tables -A $i 118 | } 119 | apply_flow_offloading_exempt_rule() 120 | { 121 | # $1 = '' for ipv4, '6' for ipv6 122 | local i v 123 | v=$1 124 | shift 125 | i="forwarding_rule_zapret $@ -m comment --comment zapret_traffic_offloading_exemption -j RETURN" 126 | echo applying ipv${v:-4} flow offloading exemption : $i 127 | ip${v}tables -A $i 128 | } 129 | flow_offloading_unexempt_v() 130 | { 131 | # $1 = '' for ipv4, '6' for ipv6 132 | local DWAN 133 | network_find_wanX_devices ${1:-4} DWAN 134 | for i in $DWAN; do ipt$1_del FORWARD -o $i -j forwarding_rule_zapret ; done 135 | ip$1tables -F forwarding_rule_zapret 2>/dev/null 136 | ip$1tables -X forwarding_rule_zapret 2>/dev/null 137 | } 138 | flow_offloading_exempt_v() 139 | { 140 | # $1 = '' for ipv4, '6' for ipv6 141 | is_ipt_flow_offload_avail $1 || return 0 142 | 143 | flow_offloading_unexempt_v $1 144 | 145 | [ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && { 146 | ip$1tables -N forwarding_rule_zapret 147 | 148 | # remove outgoing interface 149 | list_nfqws_rules $1 | sed -re 's/-o +[^ ]+//g' | 150 | while read rule; do 151 | apply_flow_offloading_exempt_rule "$1" $rule 152 | done 153 | 154 | apply_flow_offloading_enable_rule $1 155 | 156 | # only outgoing to WAN packets trigger flow offloading 157 | local DWAN 158 | network_find_wanX_devices ${1:-4} DWAN 159 | for i in $DWAN; do ipt$1 FORWARD -o $i -j forwarding_rule_zapret; done 160 | } 161 | return 0 162 | } 163 | flow_offloading_exempt() 164 | { 165 | [ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v 166 | [ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6 167 | } 168 | flow_offloading_unexempt() 169 | { 170 | [ "$DISABLE_IPV4" = "1" ] || flow_offloading_unexempt_v 171 | [ "$DISABLE_IPV6" = "1" ] || flow_offloading_unexempt_v 6 172 | } 173 | 174 | nft_fill_ifsets_overload() 175 | { 176 | local ifaces DLAN DWAN DWAN6 PDLAN PDWAN PDWAN6 177 | 178 | call_for_multiple_items network_get_device DLAN "$OPENWRT_LAN" 179 | call_for_multiple_items network_get_physdev PDLAN "$OPENWRT_LAN" 180 | 181 | network_find_wan4_all ifaces 182 | call_for_multiple_items network_get_device DWAN "$ifaces" 183 | call_for_multiple_items network_get_physdev PDWAN "$ifaces" 184 | 185 | network_find_wan6_all ifaces 186 | call_for_multiple_items network_get_device DWAN6 "$ifaces" 187 | call_for_multiple_items network_get_physdev PDWAN6 "$ifaces" 188 | 189 | nft_fill_ifsets "$DLAN" "$DWAN" "$DWAN6" "$PDLAN" "$PDWAN" "$PDWAN6" 190 | } 191 | nft_wanif_filter_present() 192 | { 193 | # in openwrt we always use wanif filter 194 | return 0 195 | } 196 | nft_wanif6_filter_present() 197 | { 198 | # in openwrt we always use wanif6 filter 199 | return 0 200 | } 201 | 202 | 203 | nft_fw_nfqws_post4() 204 | { 205 | _nft_fw_nfqws_post4 "$1" $2 always_apply_wan_filter 206 | } 207 | nft_fw_nfqws_post6() 208 | { 209 | _nft_fw_nfqws_post6 "$1" $2 always_apply_wan_filter 210 | } 211 | nft_fw_nfqws_pre4() 212 | { 213 | _nft_fw_nfqws_pre4 "$1" $2 always_apply_wan_filter 214 | } 215 | nft_fw_nfqws_pre6() 216 | { 217 | _nft_fw_nfqws_pre6 "$1" $2 always_apply_wan_filter 218 | } 219 | --------------------------------------------------------------------------------