├── .gitattributes ├── Makefile ├── README.md ├── binaries ├── aarch64 │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws ├── arm │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws ├── mips32r1-lsb │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws ├── mips32r1-msb │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws ├── mips64r2-msb │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws └── ppc │ ├── ip2net │ ├── mdig │ ├── nfqws │ └── tpws ├── blockcheck.sh ├── common ├── base.sh ├── dialog.sh ├── elevate.sh ├── fwtype.sh ├── installer.sh ├── ipt.sh ├── linux_fw.sh ├── linux_iphelper.sh ├── list.sh ├── nft.sh ├── pf.sh ├── queue.sh └── virt.sh ├── config.default ├── docs ├── LICENSE.txt ├── bsd.eng.md ├── bsd.txt ├── bsdfw.txt ├── changes.txt ├── compile │ ├── build_howto_openwrt.txt │ └── openwrt │ │ └── package │ │ └── zapret │ │ ├── ip2net │ │ ├── Makefile │ │ └── readme.txt │ │ ├── mdig │ │ ├── Makefile │ │ └── readme.txt │ │ ├── nfqws │ │ ├── Makefile │ │ └── readme.txt │ │ └── tpws │ │ ├── Makefile │ │ └── readme.txt ├── iptables.txt ├── manual_setup.txt ├── nftables.txt ├── nftables_notes.txt ├── quick_start.txt ├── quick_start_windows.txt ├── readme.eng.md ├── redsocks.txt ├── windows.eng.md ├── windows.txt └── wireguard │ ├── 010-wg-mod.patch │ ├── wireguard-mod.txt │ └── wireguard_iproute_openwrt.txt ├── files ├── fake │ ├── dht_find_node.bin │ ├── dht_get_peers.bin │ ├── dtls_clienthello_w3_org.bin │ ├── http_iana_org.bin │ ├── quic_initial_facebook_com.bin │ ├── quic_initial_facebook_com_quiche.bin │ ├── quic_initial_google_com.bin │ ├── quic_initial_rutracker_org.bin │ ├── quic_initial_rutracker_org_kyber_1.bin │ ├── quic_initial_rutracker_org_kyber_2.bin │ ├── quic_initial_vk_com.bin │ ├── quic_short_header.bin │ ├── tls_clienthello_gosuslugi_ru.bin │ ├── tls_clienthello_iana_org.bin │ ├── tls_clienthello_rutracker_org_kyber.bin │ ├── tls_clienthello_sberbank_ru.bin │ ├── tls_clienthello_vk_com.bin │ ├── tls_clienthello_vk_com_kyber.bin │ ├── wireguard_initiation.bin │ ├── wireguard_response.bin │ ├── zero_1024.bin │ ├── zero_256.bin │ └── zero_512.bin └── huawei │ └── E8372 │ ├── run-zapret-hostlist │ ├── run-zapret-ip │ ├── unfuck_nfqueue.ko │ ├── unzapret │ ├── unzapret-ip │ ├── zapret │ └── zapret-ip ├── img ├── dns.png ├── i1.png ├── i10.png ├── i11.png ├── i2.png ├── i3.png ├── i4.png ├── i5.png ├── i6.png ├── i7.png ├── i8.png ├── i9.png ├── i9_11.png ├── s1.png ├── s2.png ├── s3.png ├── s4.png └── s5.png ├── init.d ├── openrc │ └── zapret ├── openwrt │ ├── 90-zapret │ ├── custom-nfqws-dht4all │ ├── custom-nfqws-quic4all │ ├── custom-reuse-builtin-mode │ ├── custom-tpws4http-nfqws4https │ ├── custom.default │ ├── firewall.zapret │ ├── functions │ └── zapret ├── pfsense │ └── zapret.sh ├── runit │ └── zapret │ │ ├── finish │ │ └── run ├── s6 │ └── zapret │ │ ├── down │ │ ├── type │ │ └── up ├── systemd │ ├── zapret-list-update.service │ ├── zapret-list-update.timer │ └── zapret.service └── sysv │ ├── custom-nfqws-dht4all │ ├── custom-nfqws-quic4all │ ├── custom-reuse-builtin-mode │ ├── custom-tpws4http-nfqws4https │ ├── custom.default │ ├── functions │ └── zapret ├── install_bin.sh ├── install_easy.sh ├── install_prereq.sh ├── ip2net ├── Makefile ├── ip2net.c ├── qsort.c └── qsort.h ├── ipset ├── antifilter.helper ├── clear_lists.sh ├── create_ipset.sh ├── def.sh ├── get_antifilter_allyouneed.sh ├── get_antifilter_ip.sh ├── get_antifilter_ipresolve.sh ├── get_antifilter_ipsmart.sh ├── get_antifilter_ipsum.sh ├── get_antizapret_domains.sh ├── get_config.sh ├── get_exclude.sh ├── get_ipban.sh ├── get_reestr_hostlist.sh ├── get_reestr_preresolved.sh ├── get_reestr_preresolved_smart.sh ├── get_reestr_resolvable_domains.sh ├── get_reestr_resolve.sh ├── get_user.sh └── zapret-hosts-user-exclude.txt.default ├── mdig ├── Makefile └── mdig.c ├── nfq ├── BSDmakefile ├── Makefile ├── checksum.c ├── checksum.h ├── conntrack.c ├── conntrack.h ├── crypto │ ├── aes-gcm.c │ ├── aes-gcm.h │ ├── aes.c │ ├── aes.h │ ├── gcm.c │ ├── gcm.h │ ├── hkdf.c │ ├── hmac.c │ ├── sha-private.h │ ├── sha.h │ ├── sha224-256.c │ └── usha.c ├── darkmagic.c ├── darkmagic.h ├── desync.c ├── desync.h ├── gzip.c ├── gzip.h ├── helpers.c ├── helpers.h ├── hostlist.c ├── hostlist.h ├── nfqws.c ├── nfqws.h ├── packet_queue.c ├── packet_queue.h ├── params.h ├── pools.c ├── pools.h ├── protocol.c ├── protocol.h ├── sec.c ├── sec.h ├── uthash.h ├── win.c ├── win.h ├── windivert │ ├── libwindivert.a │ └── windivert.h ├── winicon.o └── winmanifest.o ├── tmp └── .keep ├── tpws ├── BSDmakefile ├── Makefile ├── epoll-shim │ ├── include │ │ └── sys │ │ │ └── epoll.h │ └── src │ │ ├── epoll.c │ │ ├── epoll_shim_ctx.c │ │ ├── epoll_shim_ctx.h │ │ ├── epollfd_ctx.c │ │ ├── epollfd_ctx.h │ │ ├── eventfd_ctx.h │ │ ├── fix.c │ │ ├── fix.h │ │ ├── signalfd_ctx.h │ │ └── timerfd_ctx.h ├── gzip.c ├── gzip.h ├── helpers.c ├── helpers.h ├── hostlist.c ├── hostlist.h ├── macos │ ├── net │ │ └── pfvar.h │ └── sys │ │ └── tree.h ├── params.h ├── pools.c ├── pools.h ├── protocol.c ├── protocol.h ├── redirect.c ├── redirect.h ├── resolver.c ├── resolver.h ├── sec.c ├── sec.h ├── socks.h ├── tamper.c ├── tamper.h ├── tpws.c ├── tpws.h ├── tpws_conn.c ├── tpws_conn.h └── uthash.h └── uninstall_easy.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DIRS := nfq tpws ip2net mdig 2 | DIRS_MAC := tpws ip2net mdig 3 | TGT := binaries/my 4 | 5 | all: clean 6 | @mkdir -p "$(TGT)"; \ 7 | for dir in $(DIRS); do \ 8 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 9 | $(MAKE) -C "$$dir" || exit; \ 10 | for exe in "$$dir/"*; do \ 11 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 12 | mv -f "$$exe" "${TGT}" ; \ 13 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 14 | fi \ 15 | done \ 16 | done 17 | 18 | bsd: clean 19 | @mkdir -p "$(TGT)"; \ 20 | for dir in $(DIRS); do \ 21 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 22 | $(MAKE) -C "$$dir" bsd || exit; \ 23 | for exe in "$$dir/"*; do \ 24 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 25 | mv -f "$$exe" "${TGT}" ; \ 26 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 27 | fi \ 28 | done \ 29 | done 30 | 31 | mac: clean 32 | @mkdir -p "$(TGT)"; \ 33 | for dir in $(DIRS_MAC); do \ 34 | find "$$dir" -type f \( -name "*.c" -o -name "*.h" -o -name "*akefile" \) -exec chmod -x {} \; ; \ 35 | $(MAKE) -C "$$dir" mac || exit; \ 36 | for exe in "$$dir/"*; do \ 37 | if [ -f "$$exe" ] && [ -x "$$exe" ]; then \ 38 | mv -f "$$exe" "${TGT}" ; \ 39 | ln -fs "../${TGT}/$$(basename "$$exe")" "$$exe" ; \ 40 | fi \ 41 | done \ 42 | done 43 | 44 | clean: 45 | @[ -d "$(TGT)" ] && rm -rf "$(TGT)" ; \ 46 | for dir in $(DIRS); do \ 47 | $(MAKE) -C "$$dir" clean; \ 48 | done 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Настройка zapret от bol-van на Keenetic 2 | 3 | Инструкция по установке zapret от bol-van на Keenetic предполагает, что OPKG Entware уже установлен. 4 | 5 | Оригинал статьи находится по ссылке https://telegra.ph/Nastrojka-zapret-ot-bol-van-na-Keentic-04-27 6 | 7 | Ссылка на автора zapret на гитхабе - https://github.com/bol-van/zapret 8 | 9 | **Обязательно любой сторонний DNS, желательно DNS-over-HTTPS, DoH** 10 | ![image](img/dns.png) 11 | Предварительно установите и настройте opkg на keenetic 12 | 13 | Устанавливаем пакеты: 14 | 15 | opkg install coreutils-sort curl git-http grep gzip ipset iptables kmod_ndms nano xtables-addons_legacy 16 | Переходим в tmp: 17 | 18 | cd /opt/tmp 19 | Скачиваем zapret: 20 | 21 | git clone --depth=1 https://github.com/AlexFBG/zapret.git 22 | Переходим в каталог zapret и выполняем скрипт 23 | 24 | cd zapret 25 | ./install_bin.sh 26 | и 27 | 28 | ./install_prereq.sh 29 | 30 | Выбираем тип файрволла 1 31 | 32 | ![image](/img/s1.png) 33 | 34 | your choice (default : iptables) : 1 35 | Из скрипта выходим Enter-ом 36 | Запускаем проверку провайдера (должны быть отключены все блокировки) 37 | 38 | ./blockcheck.sh 39 | ![mage](/img/s2.png) 40 | 41 | Оставляем все по умолчанию (проходим Enter), на вопрос типа сканирования выбираем standart 42 | 43 | ![image](/img/s3.png) 44 | 45 | При выборе сайта для сканирования, выбрать лучше из предложенных (rutracker.org) и не выбирать youtube.com и googlevideo.com, т.к. данные сайты не заблокированы, а сканер не тестирует сайты на скорость. 46 | 47 | ![image](/img/s4.png) 48 | 49 | По итогу получится что то вроде этого 50 | 51 | ![image](/img/s5.png) 52 | 53 | Как видим, найденные стратегии будут отображаться как !!!!! AVAILABLE !!!!! 54 | 55 | В конце скрипт предложит стратегию по обходу провайдера, можно выбрать ее но учитывая следующее: обход блокировки Youtube использует стратегию split2 56 | Поэтому запоминаем, записываем в Блокнот: 57 | 58 | nfqws --dpi-desync=fake,split2 --dpi-desync-ttl=5 59 | 60 | Начинаем установку скрипта: 61 | 62 | ./install_easy.sh 63 | 64 | ![image](/img/i1.png) 65 | 66 | На предупреждения отвечаем Y 67 | 68 | ![image](/img/i2.png) 69 | 70 | Папку по умолчанию оставляем как есть, отвечаем Y 71 | 72 | ![image](/img/i3.png) 73 | 74 | Пишет, что нужно будет вручную сделать автозапуск, отвечаем Y 75 | 76 | ![image](/img/i4.png) 77 | 78 | Выбираем iptables, жмем 1 79 | 80 | ![image](/img/i5.png) 81 | 82 | Спрашивает про поддержку IP6, не используем, поэтому N 83 | 84 | ![image](/img/i6.png) 85 | 86 | Выбираем nfqws, жмем 3 87 | 88 | ![image](/img/i7.png) 89 | 90 | Предлагает отредактировать файл конфигурации. Здесь внимание! Помните мы сканировали и определяли стратегию? Поэтому жмем Y и попадаем в редактор (в зависимости какой у вас установлен по умолчанию, nano или mcedit). Редактируем верхнюю строчку и вставляем свои параметры между кавычками: 91 | 92 | --dpi-desync=fake,split2 --dpi-desync-ttl=5 93 | 94 | Вставлять в окно SSH можно сочетанием клавиш: Shift+Insert 95 | 96 | ![image](/img/i8.png) 97 | 98 | Сохраняем файл конфигурации, идем далее 99 | 100 | ![image](/img/i9.png) 101 | 102 | Предлагает подключиться к интерфейсу WAN. Определить интерфейс можно запустив вторую копию ssh и ввести команду ifconfig. Ищем интерфейс с IP провайдера 103 | 104 | ![image](/img/i9_11.png) 105 | 106 | Выбираем 11 107 | 108 | После этого скрипт предложит выбрать стратегию обхода для выбранного MODE, выбираем get_antizapret_domains.sh (он по умолчанию). Произойдет скачивание листа заблокированных сайтов, установка правил. По итогу получим следующее 109 | 110 | ![image](/img/i10.png) 111 | 112 | Здесь имеется предупреждение, что установка не закончена и необходимо вручную сделать настройки. Жмем Enter и выходим в командную строку. Делаем настройки. 113 | Удаляем ненужное. 114 | 115 | cd 116 | rm -rf /opt/tmp/zapret 117 | Теперь сделаем, что бы запрет стартовал при запуске Keenetic. 118 | 119 | ln -fs /opt/zapret/init.d/sysv/zapret /opt/etc/init.d/S90-zapret 120 | Правим стартовый скрипт, добавляем PATH и WS_USER 121 | В этом примере используется текстовый редактор nano 122 | 123 | nano /opt/zapret/init.d/sysv/zapret 124 | В этом файле дописываем 125 | 126 | PATH=/opt/sbin:/opt/bin:/opt/usr/sbin:/opt/usr/bin:/usr/sbin:/usr/bin:/sbin:/bin 127 | WS_USER=nobody 128 | Должно получиться так 129 | 130 | ![image](/img/i11.png) 131 | 132 | Правим как у меня и сохраняем F2 133 | Создаем небольшой скрипт, чтобы Keenetic не забывал правила. 134 | 135 | nano /opt/etc/ndm/netfilter.d/000-zapret.sh 136 | 137 | В него вставляем 138 | 139 | #!/bin/sh 140 | [ "$type" == "ip6tables" ] && exit 0 141 | [ "$table" != "mangle" ] && exit 0 142 | /opt/zapret/init.d/sysv/zapret restart-fw 143 | 144 | сохраним и выходим если что можете использовать файловый менеджер mc там тоже есть текстовой редактор. После команда 145 | 146 | chmod +x /opt/etc/ndm/netfilter.d/000-zapret.sh 147 | 148 | Переводим net.netfilter.nf_conntrack_checksum в 0 149 | 150 | nano /opt/etc/init.d/S00fix 151 | 152 | Вставляем 153 | 154 | #!/bin/sh 155 | start() { 156 | echo 0 > /proc/sys/net/netfilter/nf_conntrack_checksum 157 | } 158 | stop() { 159 | echo 1 > /proc/sys/net/netfilter/nf_conntrack_checksum 160 | } 161 | case "$1" in 162 | 'start') 163 | start 164 | ;; 165 | 'stop') 166 | stop 167 | ;; 168 | *) 169 | stop 170 | start 171 | ;; 172 | esac 173 | exit 0 174 | 175 | Выставляем права 176 | 177 | chmod +x /opt/etc/init.d/S00fix 178 | 179 | На этом все, перегружаемся и проверяем. 180 | -------------------------------------------------------------------------------- /binaries/aarch64/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/aarch64/ip2net -------------------------------------------------------------------------------- /binaries/aarch64/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/aarch64/mdig -------------------------------------------------------------------------------- /binaries/aarch64/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/aarch64/nfqws -------------------------------------------------------------------------------- /binaries/aarch64/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/aarch64/tpws -------------------------------------------------------------------------------- /binaries/arm/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/arm/ip2net -------------------------------------------------------------------------------- /binaries/arm/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/arm/mdig -------------------------------------------------------------------------------- /binaries/arm/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/arm/nfqws -------------------------------------------------------------------------------- /binaries/arm/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/arm/tpws -------------------------------------------------------------------------------- /binaries/mips32r1-lsb/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-lsb/ip2net -------------------------------------------------------------------------------- /binaries/mips32r1-lsb/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-lsb/mdig -------------------------------------------------------------------------------- /binaries/mips32r1-lsb/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-lsb/nfqws -------------------------------------------------------------------------------- /binaries/mips32r1-lsb/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-lsb/tpws -------------------------------------------------------------------------------- /binaries/mips32r1-msb/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-msb/ip2net -------------------------------------------------------------------------------- /binaries/mips32r1-msb/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-msb/mdig -------------------------------------------------------------------------------- /binaries/mips32r1-msb/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-msb/nfqws -------------------------------------------------------------------------------- /binaries/mips32r1-msb/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips32r1-msb/tpws -------------------------------------------------------------------------------- /binaries/mips64r2-msb/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips64r2-msb/ip2net -------------------------------------------------------------------------------- /binaries/mips64r2-msb/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips64r2-msb/mdig -------------------------------------------------------------------------------- /binaries/mips64r2-msb/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips64r2-msb/nfqws -------------------------------------------------------------------------------- /binaries/mips64r2-msb/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/mips64r2-msb/tpws -------------------------------------------------------------------------------- /binaries/ppc/ip2net: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/ppc/ip2net -------------------------------------------------------------------------------- /binaries/ppc/mdig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/ppc/mdig -------------------------------------------------------------------------------- /binaries/ppc/nfqws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/ppc/nfqws -------------------------------------------------------------------------------- /binaries/ppc/tpws: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/binaries/ppc/tpws -------------------------------------------------------------------------------- /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/elevate.sh: -------------------------------------------------------------------------------- 1 | require_root() 2 | { 3 | local exe 4 | echo \* checking privileges 5 | [ $(id -u) -ne "0" ] && { 6 | echo root is required 7 | exe="$EXEDIR/$(basename "$0")" 8 | exists sudo && exec sudo sh "$exe" 9 | exists su && exec su root -c "sh \"$exe\"" 10 | echo su or sudo not found 11 | exitp 2 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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" -a "$MODE" != tpws -a "$MODE" != tpws-socks ] && 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 | 42 | first_packets_for_mode() 43 | { 44 | # autohostlist and autottl modes requires incoming traffic sample 45 | # always use conntrack packet limiter or nfqws will deal with gigabytes 46 | local n 47 | if [ "$MODE_FILTER" = "autohostlist" ]; then 48 | n=$((6+${AUTOHOSTLIST_RETRANS_THRESHOLD:-3})) 49 | else 50 | n=6 51 | fi 52 | echo $n 53 | } 54 | -------------------------------------------------------------------------------- /common/linux_iphelper.sh: -------------------------------------------------------------------------------- 1 | # there's no route_localnet for ipv6 2 | # the best we can is to route to link local of the incoming interface 3 | # OUTPUT - can DNAT to ::1 4 | # PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr 5 | # not a good idea to expose tpws to the world (bind to ::) 6 | 7 | 8 | get_ipv6_linklocal() 9 | { 10 | # $1 - interface name. if empty - any interface 11 | if exists ip ; then 12 | local dev 13 | [ -n "$1" ] && dev="dev $1" 14 | ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1 15 | else 16 | ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Link.*$/\1/;t;d' | head -n 1 17 | fi 18 | } 19 | get_ipv6_global() 20 | { 21 | # $1 - interface name. if empty - any interface 22 | if exists ip ; then 23 | local dev 24 | [ -n "$1" ] && dev="dev $1" 25 | ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1 26 | else 27 | ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Global.*$/\1/;t;d' | head -n 1 28 | fi 29 | } 30 | 31 | iface_is_up() 32 | { 33 | # $1 - interface name 34 | [ -f /sys/class/net/$1/operstate ] || return 35 | local state 36 | read state file "/opt/zapret/ipset/zapret-ip.txt" 85 | table file "/opt/zapret/ipset/zapret-ip-user.txt" 86 | table file "/opt/zapret/ipset/zapret-ip-exclude.txt" 87 | pass out quick on em0 inet proto tcp to port {80,443} 88 | pass in quick on em0 inet proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state 89 | pass in quick on em0 inet proto tcp from port {80,443} no state 90 | pass out quick on em0 inet proto tcp to port {80,443} divert-packet port 989 no state 91 | pass in quick on em0 inet proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state 92 | pass in quick on em0 inet proto tcp from port {80,443} no state 93 | pass out quick on em0 inet proto tcp to port {80,443} divert-packet port 989 no state 94 | table file "/opt/zapret/ipset/zapret-ip6.txt" 95 | table file "/opt/zapret/ipset/zapret-ip-user6.txt" 96 | table file "/opt/zapret/ipset/zapret-ip-exclude6.txt" 97 | pass out quick on em0 inet6 proto tcp to port {80,443} 98 | pass in quick on em0 inet6 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state 99 | pass in quick on em0 inet6 proto tcp from port {80,443} no state 100 | pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet port 989 no state 101 | pass in quick on em0 inet6 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state 102 | pass in quick on em0 inet6 proto tcp from port {80,443} no state 103 | pass out quick on em0 inet6 proto tcp to port {80,443} divert-packet port 989 no state 104 | -------------------------------------------------------------------------------- /docs/compile/build_howto_openwrt.txt: -------------------------------------------------------------------------------- 1 | How to compile native programs for use in openwrt 2 | ------------------------------------------------- 3 | 4 | 1) 5 | 6 | cd ~ 7 | 8 | 9 | git clone git://git.openwrt.org/15.05/openwrt.git 10 | 11 | git clone git://git.openwrt.org/14.07/openwrt.git 12 | 13 | git clone git://git.openwrt.org/openwrt.git 14 | 15 | cd openwrt 16 | 17 | 2) ./scripts/feeds update -a 18 | ./scripts/feeds install -a 19 | 20 | 3) #add zapret packages to build root 21 | #copy package descriptions 22 | copy compile/openwrt/* to ~/openwrt 23 | #copy source code of tpws 24 | copy tpws to ~/openwrt/package/zapret/tpws 25 | #copy source code of nfq 26 | copy nfq to ~/openwrt/package/zapret/nfq 27 | #copy source code of ip2net 28 | copy ip2net to ~/openwrt/package/zapret/ip2net 29 | 30 | 4) make menuconfig 31 | #select your target architecture 32 | #select packages Network/Zapret/* as "M" 33 | 34 | 5) make toolchain/compile 35 | 36 | 6) make package/tpws/compile 37 | make package/nfqws/compile 38 | make package/ip2net/compile 39 | make package/mdig/compile 40 | 41 | 7) find bin -name tpws*.ipk 42 | #take your tpws*.ipk , nfqws*.ipk , ip2net*.ipk, mdig*.ipk from there 43 | -------------------------------------------------------------------------------- /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/zapret/ip2net 28 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/ip2net 29 | endef 30 | 31 | $(eval $(call BuildPackage,ip2net)) 32 | 33 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/ip2net/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "ip2net" folder here ! 2 | -------------------------------------------------------------------------------- /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/zapret/mdig 28 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/mdig 29 | endef 30 | 31 | $(eval $(call BuildPackage,mdig)) 32 | 33 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/mdig/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "mdig" folder here ! 2 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/nfqws/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | 3 | include $(TOPDIR)/rules.mk 4 | 5 | PKG_NAME:=nfqws 6 | PKG_RELEASE:=1 7 | 8 | include $(INCLUDE_DIR)/package.mk 9 | 10 | define Package/nfqws 11 | SECTION:=net 12 | CATEGORY:=Network 13 | TITLE:=nfqws 14 | SUBMENU:=Zapret 15 | DEPENDS:=+libnetfilter-queue +libcap +zlib 16 | endef 17 | 18 | define Build/Prepare 19 | mkdir -p $(PKG_BUILD_DIR) 20 | $(CP) ./nfq/* $(PKG_BUILD_DIR)/ 21 | endef 22 | 23 | define Build/Compile 24 | $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) 25 | endef 26 | 27 | define Package/nfqws/install 28 | $(INSTALL_DIR) $(1)/opt/zapret/nfq 29 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws $(1)/opt/zapret/nfq 30 | endef 31 | 32 | $(eval $(call BuildPackage,nfqws)) 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/nfqws/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "nfq" folder here ! 2 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/tpws/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | 3 | include $(TOPDIR)/rules.mk 4 | 5 | PKG_NAME:=tpws 6 | PKG_RELEASE:=1 7 | 8 | include $(INCLUDE_DIR)/package.mk 9 | 10 | define Package/tpws 11 | SECTION:=net 12 | CATEGORY:=Network 13 | TITLE:=tpws 14 | SUBMENU:=Zapret 15 | DEPENDS:=+zlib +libcap 16 | endef 17 | 18 | define Build/Prepare 19 | mkdir -p $(PKG_BUILD_DIR) 20 | $(CP) ./tpws/* $(PKG_BUILD_DIR)/ 21 | endef 22 | 23 | define Build/Compile 24 | $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) 25 | endef 26 | 27 | define Package/tpws/install 28 | $(INSTALL_DIR) $(1)/opt/zapret/tpws 29 | $(INSTALL_BIN) $(PKG_BUILD_DIR)/tpws $(1)/opt/zapret/tpws 30 | endef 31 | 32 | $(eval $(call BuildPackage,tpws)) 33 | 34 | -------------------------------------------------------------------------------- /docs/compile/openwrt/package/zapret/tpws/readme.txt: -------------------------------------------------------------------------------- 1 | Copy "tpws" folder here ! 2 | -------------------------------------------------------------------------------- /docs/iptables.txt: -------------------------------------------------------------------------------- 1 | For window size changing : 2 | 3 | iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass 4 | iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass 5 | 6 | For dpi desync attack : 7 | 8 | iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass 9 | iptables -t mangle -I POSTROUTING -p tcp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass 10 | iptables -t mangle -I POSTROUTING -p udp --dport 443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass 11 | 12 | # auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI 13 | sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 14 | iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:12 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass 15 | iptables -t mangle -I PREROUTING -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass 16 | 17 | 18 | For TPROXY : 19 | 20 | sysctl -w net.ipv4.ip_forward=1 21 | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 22 | 23 | ip -f inet rule add fwmark 1 lookup 100 24 | ip -f inet route add local default dev lo table 100 25 | # prevent loop 26 | iptables -t filter -I INPUT -p tcp --dport 988 -j REJECT 27 | iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j MARK --set-mark 1 28 | iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 988 29 | 30 | iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m set --match-set zapret dst -j MARK --set-mark 1 31 | iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m mark --mark 0x1/0x1 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 988 32 | 33 | For DNAT : 34 | 35 | # run tpws as user "tpws". its required to avoid loops. 36 | sysctl -w net.ipv4.conf.eth1.route_localnet=1 37 | iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.127:988 38 | iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988 39 | 40 | 41 | Reset all iptable rules : 42 | 43 | iptables -F 44 | iptables -X 45 | iptables -t nat -F 46 | iptables -t nat -X 47 | iptables -t mangle -F 48 | iptables -t mangle -X 49 | iptables -t raw -F 50 | iptables -t raw -X 51 | 52 | Reset iptable policies : 53 | 54 | iptables -P INPUT ACCEPT 55 | iptables -P FORWARD ACCEPT 56 | iptables -P OUTPUT ACCEPT 57 | iptables -t mangle -P POSTROUTING ACCEPT 58 | iptables -t mangle -P PREROUTING ACCEPT 59 | iptables -t mangle -P INPUT ACCEPT 60 | iptables -t mangle -P FORWARD ACCEPT 61 | iptables -t mangle -P OUTPUT ACCEPT 62 | iptables -t raw -P PREROUTING ACCEPT 63 | iptables -t raw -P OUTPUT ACCEPT 64 | -------------------------------------------------------------------------------- /docs/nftables.txt: -------------------------------------------------------------------------------- 1 | nftables test cheat sheet 2 | simplified rules to test nfqws and tpws 3 | 4 | 5 | For DNAT : 6 | 7 | # run tpws as user "tpws". its required to avoid loops. 8 | 9 | nft delete table inet ztest 10 | nft create table inet ztest 11 | nft add chain inet ztest pre "{type nat hook prerouting priority dstnat;}" 12 | nft add rule inet ztest pre tcp dport "{80,443}" redirect to :988 13 | nft add chain inet ztest out "{type nat hook output priority -100;}" 14 | nft add rule inet ztest out tcp dport "{80,443}" skuid != tpws redirect to :988 15 | 16 | 17 | For dpi desync attack : 18 | 19 | nft delete table inet ztest 20 | nft create table inet ztest 21 | nft add chain inet ztest post "{type filter hook postrouting priority mangle;}" 22 | nft add rule inet ztest post tcp dport "{80,443}" ct original packets 1-12 queue num 200 bypass 23 | nft add rule inet ztest post udp dport 443 ct original packets 1-4 queue num 200 bypass 24 | 25 | # auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI 26 | sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1 27 | nft add chain inet ztest pre "{type filter hook prerouting priority filter;}" 28 | nft add rule inet ztest pre tcp sport "{80,443}" ct reply packets 1-4 queue num 200 bypass 29 | 30 | 31 | show rules : nft list table inet ztest 32 | delete table : nft delete table inet ztest 33 | -------------------------------------------------------------------------------- /docs/wireguard/010-wg-mod.patch: -------------------------------------------------------------------------------- 1 | Index: WireGuard-0.0.20190123/src/cookie.c 2 | =================================================================== 3 | --- WireGuard-0.0.20190123.orig/src/cookie.c 4 | +++ WireGuard-0.0.20190123/src/cookie.c 5 | @@ -193,6 +193,8 @@ void wg_cookie_message_create(struct mes 6 | xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN, 7 | macs->mac1, COOKIE_LEN, dst->nonce, 8 | checker->cookie_encryption_key); 9 | + // MOD : randomize trash 10 | + dst->header.trash = gen_trash(); 11 | } 12 | 13 | void wg_cookie_message_consume(struct message_handshake_cookie *src, 14 | Index: WireGuard-0.0.20190123/src/messages.h 15 | =================================================================== 16 | --- WireGuard-0.0.20190123.orig/src/messages.h 17 | +++ WireGuard-0.0.20190123/src/messages.h 18 | @@ -53,23 +53,41 @@ enum limits { 19 | MAX_QUEUED_PACKETS = 1024 /* TODO: replace this with DQL */ 20 | }; 21 | 22 | +/* 23 | enum message_type { 24 | - MESSAGE_INVALID = 0, 25 | - MESSAGE_HANDSHAKE_INITIATION = 1, 26 | - MESSAGE_HANDSHAKE_RESPONSE = 2, 27 | - MESSAGE_HANDSHAKE_COOKIE = 3, 28 | - MESSAGE_DATA = 4 29 | + MESSAGE_INVALID = 0, 30 | + MESSAGE_HANDSHAKE_INITIATION = 1, 31 | + MESSAGE_HANDSHAKE_RESPONSE = 2, 32 | + MESSAGE_HANDSHAKE_COOKIE = 3, 33 | + MESSAGE_DATA = 4 34 | }; 35 | +*/ 36 | + 37 | +// MOD : message type 38 | +enum message_type { 39 | + MESSAGE_INVALID = 0xE319CCD0, 40 | + MESSAGE_HANDSHAKE_INITIATION = 0x48ADE198, 41 | + MESSAGE_HANDSHAKE_RESPONSE = 0xFCA6A8F3, 42 | + MESSAGE_HANDSHAKE_COOKIE = 0x64A3BB18, 43 | + MESSAGE_DATA = 0x391820AA 44 | +}; 45 | + 46 | +// MOD : generate fast trash without true RNG 47 | +__le32 gen_trash(void); 48 | 49 | struct message_header { 50 | - /* The actual layout of this that we want is: 51 | - * u8 type 52 | - * u8 reserved_zero[3] 53 | - * 54 | - * But it turns out that by encoding this as little endian, 55 | - * we achieve the same thing, and it makes checking faster. 56 | - */ 57 | - __le32 type; 58 | + /* The actual layout of this that we want is: 59 | + * u8 type 60 | + * u8 reserved_zero[3] 61 | + * 62 | + * But it turns out that by encoding this as little endian, 63 | + * we achieve the same thing, and it makes checking faster. 64 | + */ 65 | + 66 | + // MOD : trash field to change message size and add 4 byte offset to all fields 67 | + __le32 trash; 68 | + 69 | + __le32 type; 70 | }; 71 | 72 | struct message_macs { 73 | Index: WireGuard-0.0.20190123/src/noise.c 74 | =================================================================== 75 | --- WireGuard-0.0.20190123.orig/src/noise.c 76 | +++ WireGuard-0.0.20190123/src/noise.c 77 | @@ -17,6 +17,24 @@ 78 | #include 79 | #include 80 | 81 | + 82 | +// MOD : trash generator 83 | +__le32 gtrash = 0; 84 | +__le32 gen_trash(void) 85 | +{ 86 | + if (gtrash) 87 | + gtrash = gtrash*1103515243 + 12345; 88 | + else 89 | + // first value is true random 90 | + get_random_bytes_wait(>rash, sizeof(gtrash)); 91 | + return gtrash; 92 | +} 93 | + 94 | /* This implements Noise_IKpsk2: 95 | * 96 | * <- s 97 | @@ -515,6 +533,10 @@ wg_noise_handshake_create_initiation(str 98 | &handshake->entry); 99 | 100 | handshake->state = HANDSHAKE_CREATED_INITIATION; 101 | + 102 | + // MOD : randomize trash 103 | + dst->header.trash = gen_trash(); 104 | + 105 | ret = true; 106 | 107 | out: 108 | @@ -655,6 +677,10 @@ bool wg_noise_handshake_create_response( 109 | &handshake->entry); 110 | 111 | handshake->state = HANDSHAKE_CREATED_RESPONSE; 112 | + 113 | + // MOD : randomize trash 114 | + dst->header.trash = gen_trash(); 115 | + 116 | ret = true; 117 | 118 | out: 119 | Index: WireGuard-0.0.20190123/src/send.c 120 | =================================================================== 121 | --- WireGuard-0.0.20190123.orig/src/send.c 122 | +++ WireGuard-0.0.20190123/src/send.c 123 | @@ -200,6 +200,10 @@ static bool encrypt_packet(struct sk_buf 124 | header->header.type = cpu_to_le32(MESSAGE_DATA); 125 | header->key_idx = keypair->remote_index; 126 | header->counter = cpu_to_le64(PACKET_CB(skb)->nonce); 127 | + 128 | + // MOD : randomize trash 129 | + header->header.trash = gen_trash(); 130 | + 131 | pskb_put(skb, trailer, trailer_len); 132 | 133 | /* Now we can encrypt the scattergather segments */ 134 | -------------------------------------------------------------------------------- /files/fake/dht_find_node.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/dht_find_node.bin -------------------------------------------------------------------------------- /files/fake/dht_get_peers.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/dht_get_peers.bin -------------------------------------------------------------------------------- /files/fake/dtls_clienthello_w3_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/dtls_clienthello_w3_org.bin -------------------------------------------------------------------------------- /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/quic_initial_facebook_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_facebook_com.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_facebook_com_quiche.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_facebook_com_quiche.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_google_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_google_com.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_rutracker_org.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org_kyber_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_rutracker_org_kyber_1.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_rutracker_org_kyber_2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_rutracker_org_kyber_2.bin -------------------------------------------------------------------------------- /files/fake/quic_initial_vk_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_initial_vk_com.bin -------------------------------------------------------------------------------- /files/fake/quic_short_header.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/quic_short_header.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_gosuslugi_ru.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_gosuslugi_ru.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_iana_org.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_iana_org.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_rutracker_org_kyber.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_rutracker_org_kyber.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_sberbank_ru.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_sberbank_ru.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_vk_com.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_vk_com.bin -------------------------------------------------------------------------------- /files/fake/tls_clienthello_vk_com_kyber.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/tls_clienthello_vk_com_kyber.bin -------------------------------------------------------------------------------- /files/fake/wireguard_initiation.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/wireguard_initiation.bin -------------------------------------------------------------------------------- /files/fake/wireguard_response.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/fake/wireguard_response.bin -------------------------------------------------------------------------------- /files/fake/zero_1024.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/fake/zero_256.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/fake/zero_512.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /files/huawei/E8372/run-zapret-hostlist: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | # download hostlist from http(s) (need curl, its absent by default), 4 | # feed it to zapret. save flash write cycles 5 | 6 | u="https://your.host.com/censorship/hoslist.txt" 7 | 8 | SCRIPT=$(readlink -f "$0") 9 | EXEDIR=$(dirname "$SCRIPT") 10 | 11 | d=/data/censorship 12 | [ -d $d ] || mkdir $d 13 | f=$d/hostlist.txt 14 | t=/hostlist.txt 15 | 16 | curl -k --fail --max-time 10 -o "$t" "$u" && { 17 | if [ -s "$t" ]; then 18 | m1=$(md5sum "$t" | cut -d ' ' -f 1) 19 | m2=$(md5sum "$f" | cut -d ' ' -f 1) 20 | echo $m1 $m2 21 | if [ -z "$m2" ] || [ "$m1" != "$m2" ]; then 22 | echo updating hostlist 23 | cp -f "$t" "$f" 24 | else 25 | echo hostlist was not changed. keeping old copy 26 | fi 27 | else 28 | echo downloaded hostlist is empty. disabling zapret 29 | rm "$f" 30 | fi 31 | } 32 | 33 | rm -f "$t" 34 | "$EXEDIR/unzapret" 35 | [ -s "$f" ] && exec "$EXEDIR/zapret" "--hostlist=$f" 36 | -------------------------------------------------------------------------------- /files/huawei/E8372/run-zapret-ip: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | # download hostlist from http(s) (need curl, its absent by default), 4 | # resolve to ip list, feed to zapret-ip. save flash write cycles 5 | 6 | u="https://your.host.com/censorship/hoslist.txt" 7 | 8 | SCRIPT=$(readlink -f "$0") 9 | EXEDIR=$(dirname "$SCRIPT") 10 | 11 | d=/data/censorship 12 | [ -d $d ] || mkdir $d 13 | f=$d/hostlist.txt 14 | t=/hostlist.txt 15 | i=/iplist.txt 16 | 17 | curl -k --fail --max-time 10 -o "$t" "$u" && { 18 | if [ -s "$t" ]; then 19 | m1=$(md5sum "$t" | cut -d ' ' -f 1) 20 | m2=$(md5sum "$f" | cut -d ' ' -f 1) 21 | echo $m1 $m2 22 | if [ -z "$m2" ] || [ "$m1" != "$m2" ]; then 23 | echo updating hostlist 24 | cp -f "$t" "$f" 25 | else 26 | echo hostlist was not changed. keeping old copy 27 | fi 28 | else 29 | echo downloaded hostlist is empty. disabling zapret 30 | rm "$f" 31 | fi 32 | } 33 | 34 | rm -f "$t" 35 | "$EXEDIR/unzapret-ip" 36 | [ -s "$f" ] && { 37 | mdig --threads=10 --family=4 <"$f" >"$i" 38 | [ -s "$i" ] && exec "$EXEDIR/zapret-ip" "$i" 39 | } 40 | -------------------------------------------------------------------------------- /files/huawei/E8372/unfuck_nfqueue.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/files/huawei/E8372/unfuck_nfqueue.ko -------------------------------------------------------------------------------- /files/huawei/E8372/unzapret: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | rule="PREROUTING -t nat -i br0 ! -d 192.168.0.0/16 -p tcp -m multiport --dports 80,443 -j REDIRECT --to-port 1" 4 | iptables -C $rule 2>/dev/null && iptables -D $rule 5 | killall tpws 6 | 7 | rule="OUTPUT -t mangle -o wan0 -p tcp -m multiport --dports 80,443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass" 8 | iptables -C $rule 2>/dev/null && iptables -D $rule 9 | killall nfqws 10 | -------------------------------------------------------------------------------- /files/huawei/E8372/unzapret-ip: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | rule="PREROUTING -t nat -i br0 -p tcp -m multiport --dports 80,443 -j tpws" 4 | iptables -C $rule 2>/dev/null && iptables -D $rule 5 | iptables -F tpws -t nat 6 | iptables -X tpws -t nat 7 | killall tpws 8 | 9 | rule="OUTPUT -t mangle -o wan0 -p tcp -m multiport --dports 80,443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass" 10 | iptables -C $rule 2>/dev/null && iptables -D $rule 11 | killall nfqws 12 | -------------------------------------------------------------------------------- /files/huawei/E8372/zapret: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | # $1 - additional parameters for nfqws 4 | 5 | insmod /online/modules/unfuck_nfqueue.ko 2>/dev/null 6 | 7 | rule="PREROUTING -t nat -i br0 ! -d 192.168.0.0/16 -p tcp -m multiport --dports 80,443 -j REDIRECT --to-port 1" 8 | iptables -C $rule 2>/dev/null || iptables -I $rule 9 | 10 | tpws --uid 1:3003 --port=1 --daemon 11 | 12 | rule="OUTPUT -t mangle -o wan0 -p tcp -m multiport --dports 80,443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass" 13 | iptables -C $rule 2>/dev/null || iptables -I $rule 14 | 15 | nfqws --uid 2 --qnum=200 --dpi-desync=disorder --dpi-desync-ttl=8 --dpi-desync-fooling=md5sig --daemon $1 16 | -------------------------------------------------------------------------------- /files/huawei/E8372/zapret-ip: -------------------------------------------------------------------------------- 1 | #!/system/bin/busybox sh 2 | 3 | # $1 - ip list file. create individual rules for tpws redirection. ipset is not available 4 | 5 | [ -z "$1" ] && { 6 | echo need iplist file as parameter 7 | exit 1 8 | } 9 | 10 | insmod /online/modules/unfuck_nfqueue.ko 2>/dev/null 11 | 12 | tpws --maxconn=1024 --uid 1:3003 --port=1 --daemon 13 | 14 | 15 | REDIR="-j REDIRECT --to-port 1" 16 | 17 | iptables -F tpws -t nat 18 | iptables -X tpws -t nat 19 | iptables -N tpws -t nat 20 | iptables -A tpws -t nat -d 192.168.0.0/16 -j RETURN 21 | 22 | while read ip; do 23 | echo redirecting $ip 24 | iptables -A tpws -t nat -d $ip -p tcp $REDIR 25 | done <"$1" 26 | 27 | 28 | rule="PREROUTING -t nat -i br0 -p tcp -m multiport --dports 80,443 -j tpws" 29 | iptables -C $rule 2>/dev/null || iptables -I $rule 30 | 31 | nfqws --uid 2 --qnum=200 --dpi-desync=disorder --dpi-desync-ttl=8 --dpi-desync-fooling=md5sig --daemon 32 | 33 | rule="OUTPUT -t mangle -o wan0 -p tcp -m multiport --dports 80,443 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass" 34 | iptables -C $rule 2>/dev/null || iptables -I $rule 35 | -------------------------------------------------------------------------------- /img/dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/dns.png -------------------------------------------------------------------------------- /img/i1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i1.png -------------------------------------------------------------------------------- /img/i10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i10.png -------------------------------------------------------------------------------- /img/i11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i11.png -------------------------------------------------------------------------------- /img/i2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i2.png -------------------------------------------------------------------------------- /img/i3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i3.png -------------------------------------------------------------------------------- /img/i4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i4.png -------------------------------------------------------------------------------- /img/i5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i5.png -------------------------------------------------------------------------------- /img/i6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i6.png -------------------------------------------------------------------------------- /img/i7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i7.png -------------------------------------------------------------------------------- /img/i8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i8.png -------------------------------------------------------------------------------- /img/i9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i9.png -------------------------------------------------------------------------------- /img/i9_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/i9_11.png -------------------------------------------------------------------------------- /img/s1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/s1.png -------------------------------------------------------------------------------- /img/s2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/s2.png -------------------------------------------------------------------------------- /img/s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/s3.png -------------------------------------------------------------------------------- /img/s4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/s4.png -------------------------------------------------------------------------------- /img/s5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/img/s5.png -------------------------------------------------------------------------------- /init.d/openrc/zapret: -------------------------------------------------------------------------------- 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/zapret" 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 | -------------------------------------------------------------------------------- /init.d/openwrt/90-zapret: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ZAPRET=/etc/init.d/zapret 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 | check_need_to_reload_tpws6() 17 | { 18 | # tpws6 dnat target nft map can only be reloaded within firewall apply procedure 19 | # interface ifsets (wanif, wanif6, lanif) can be reloaded independently 20 | check_lan 21 | RELOAD_TPWS6= 22 | [ "$ACTION" = "ifup" -a "$DISABLE_IPV6" != 1 -a -n "$IS_LAN" ] && [ "$MODE" = "tpws" -o "$MODE" = "custom" ] && RELOAD_TPWS6=1 23 | } 24 | 25 | 26 | [ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && { 27 | SCRIPT=$(readlink "$ZAPRET") 28 | if [ -n "$SCRIPT" ]; then 29 | EXEDIR=$(dirname "$SCRIPT") 30 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 31 | else 32 | ZAPRET_BASE=/opt/zapret 33 | fi 34 | . "$ZAPRET_BASE/config" 35 | 36 | check_need_to_reload_tpws6 37 | [ -n "$RELOAD_TPWS6" ] && { 38 | logger -t zapret restarting daemons due to $ACTION of $INTERFACE to update tpws6 dnat target 39 | "$ZAPRET" restart_daemons 40 | } 41 | . "$ZAPRET_BASE/common/base.sh" 42 | . "$ZAPRET_BASE/common/fwtype.sh" 43 | linux_fwtype 44 | case "$FWTYPE" in 45 | nftables) 46 | if [ -n "$RELOAD_TPWS6" ] ; then 47 | logger -t zapret reloading nftables due to $ACTION of $INTERFACE to update tpws6 dnat target 48 | "$ZAPRET" restart_fw 49 | else 50 | logger -t zapret reloading nftables ifsets due to $ACTION of $INTERFACE 51 | "$ZAPRET" reload_ifsets 52 | fi 53 | ;; 54 | iptables) 55 | openwrt_fw3 || { 56 | logger -t zapret reloading iptables due to $ACTION of $INTERFACE 57 | "$ZAPRET" restart_fw 58 | } 59 | ;; 60 | esac 61 | } 62 | -------------------------------------------------------------------------------- /init.d/openwrt/custom-nfqws-dht4all: -------------------------------------------------------------------------------- 1 | # this custom script in addition to MODE=nfqws runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering 2 | # need to add to config : NFQWS_OPT_DESYNC_DHT="--dpi-desync=fake --dpi-desync-ttl=5" 3 | 4 | QNUM2=$(($QNUM+20)) 5 | 6 | zapret_custom_daemons() 7 | { 8 | # stop logic is managed by procd 9 | 10 | local MODE_OVERRIDE=nfqws 11 | local opt 12 | 13 | start_daemons_procd 14 | 15 | opt="--qnum=$QNUM2 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_DHT" 16 | run_daemon 100 $NFQWS "$opt" 17 | } 18 | zapret_custom_firewall() 19 | { 20 | # $1 - 1 - run, 0 - stop 21 | 22 | local MODE_OVERRIDE=nfqws 23 | local f uf4 uf6 24 | local first_packet_only="$ipt_connbytes 1:1" 25 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 26 | 27 | zapret_do_firewall_rules_ipt $1 28 | 29 | f='-p udp -m length --length 109:407 -m u32 --u32' 30 | uf4='0>>22&0x3C@8>>16=0x6431' 31 | uf6='48>>16=0x6431' 32 | fw_nfqws_post $1 "$f $uf4 $desync $first_packet_only" "$f $uf6 $desync $first_packet_only" $QNUM2 33 | } 34 | zapret_custom_firewall_nft() 35 | { 36 | # stop logic is not required 37 | 38 | local MODE_OVERRIDE=nfqws 39 | local f 40 | local first_packet_only="$nft_connbytes 1" 41 | local desync="mark and $DESYNC_MARK == 0" 42 | 43 | zapret_apply_firewall_rules_nft 44 | 45 | f="meta length 109-407 meta l4proto udp @th,64,16 0x6431" 46 | nft_fw_nfqws_post "$f $desync $first_packet_only" "$f $desync $first_packet_only" $QNUM2 47 | } 48 | -------------------------------------------------------------------------------- /init.d/openwrt/custom-nfqws-quic4all: -------------------------------------------------------------------------------- 1 | # this custom script in addition to MODE=nfqws runs desync to all QUIC initial packets, without ipset/hostlist filtering 2 | # need to add to config : NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake" 3 | # NOTE : do not use TTL fooling. chromium QUIC engine breaks sessions if TTL expired in transit received 4 | 5 | QNUM2=$(($QNUM+10)) 6 | 7 | zapret_custom_daemons() 8 | { 9 | # stop logic is managed by procd 10 | 11 | local MODE_OVERRIDE=nfqws 12 | local opt 13 | 14 | start_daemons_procd 15 | 16 | opt="--qnum=$QNUM2 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_QUIC" 17 | run_daemon 100 $NFQWS "$opt" 18 | } 19 | zapret_custom_firewall() 20 | { 21 | # $1 - 1 - run, 0 - stop 22 | 23 | local MODE_OVERRIDE=nfqws 24 | local f 25 | local first_packets_only="$ipt_connbytes 1:3" 26 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 27 | 28 | zapret_do_firewall_rules_ipt $1 29 | 30 | f="-p udp -m multiport --dports $QUIC_PORTS_IPT" 31 | fw_nfqws_post $1 "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2 32 | 33 | } 34 | zapret_custom_firewall_nft() 35 | { 36 | # stop logic is not required 37 | 38 | local MODE_OVERRIDE=nfqws 39 | local f 40 | local first_packets_only="$nft_connbytes 1-3" 41 | local desync="mark and $DESYNC_MARK == 0" 42 | 43 | zapret_apply_firewall_rules_nft 44 | 45 | f="udp dport {$QUIC_PORTS}" 46 | nft_fw_nfqws_post "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2 47 | } 48 | -------------------------------------------------------------------------------- /init.d/openwrt/custom-reuse-builtin-mode: -------------------------------------------------------------------------------- 1 | # this custom script demonstrates how to reuse built-in modes and add something from yourself 2 | 3 | MY_TPPORT=$(($TPPORT + 1)) 4 | MY_TPWS_OPT="--methodeol --hostcase" 5 | MY_DPORT=81 6 | 7 | zapret_custom_daemons() 8 | { 9 | # stop logic is managed by procd 10 | 11 | local MODE_OVERRIDE=tpws 12 | local opt 13 | 14 | start_daemons_procd 15 | 16 | opt="--port=$MY_TPPORT $MY_TPWS_OPT" 17 | filter_apply_hostlist_target opt 18 | run_tpws 100 "$opt" 19 | } 20 | zapret_custom_firewall() 21 | { 22 | # $1 - 1 - run, 0 - stop 23 | 24 | local MODE_OVERRIDE=tpws 25 | local f4 f6 26 | 27 | zapret_do_firewall_rules_ipt $1 28 | 29 | f4="-p tcp --dport $MY_DPORT" 30 | f6=$f4 31 | filter_apply_ipset_target f4 f6 32 | fw_tpws $1 "$f4" "$f6" $MY_TPPORT 33 | } 34 | zapret_custom_firewall_nft() 35 | { 36 | # stop logic is not required 37 | 38 | local MODE_OVERRIDE=tpws 39 | local f4 f6 40 | 41 | zapret_apply_firewall_rules_nft 42 | 43 | f4="tcp dport $MY_DPORT" 44 | f6=$f4 45 | nft_filter_apply_ipset_target f4 f6 46 | nft_fw_tpws "$f4" "$f6" $MY_TPPORT 47 | } 48 | -------------------------------------------------------------------------------- /init.d/openwrt/custom-tpws4http-nfqws4https: -------------------------------------------------------------------------------- 1 | # this custom script demonstrates how to apply tpws to http and nfqws to https 2 | # it preserves config settings : MODE_HTTP, MODE_HTTPS, MODE_FILTER, TPWS_OPT, NFQWS_OPT_DESYNC, NFQWS_OPT_DESYNC_HTTPS 3 | 4 | zapret_custom_daemons() 5 | { 6 | # stop logic is managed by procd 7 | 8 | local opt 9 | 10 | [ "$MODE_HTTP" = "1" ] && { 11 | opt="--port=$TPPORT $TPWS_OPT" 12 | filter_apply_hostlist_target opt 13 | run_tpws 1 "$opt" 14 | } 15 | 16 | [ "$MODE_HTTPS" = "1" ] && { 17 | opt="--qnum=$QNUM $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_HTTPS" 18 | filter_apply_hostlist_target opt 19 | run_daemon 2 $NFQWS "$opt" 20 | } 21 | } 22 | zapret_custom_firewall() 23 | { 24 | # $1 - 1 - run, 0 - stop 25 | 26 | local f4 f6 27 | local first_packet_only="$ipt_connbytes 1:$(first_packets_for_mode)" 28 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 29 | 30 | [ "$MODE_HTTP" = "1" ] && { 31 | f4="-p tcp -m multiport --dports $HTTP_PORTS_IPT" 32 | f6=$f4 33 | filter_apply_ipset_target f4 f6 34 | fw_tpws $1 "$f4" "$f6" $TPPORT 35 | } 36 | 37 | [ "$MODE_HTTPS" = "1" ] && { 38 | f4="-p tcp -m multiport --dports $HTTPS_PORTS_IPT $first_packet_only" 39 | f6=$f4 40 | filter_apply_ipset_target f4 f6 41 | fw_nfqws_post $1 "$f4 $desync" "$f6 $desync" $QNUM 42 | } 43 | } 44 | zapret_custom_firewall_nft() 45 | { 46 | # stop logic is not required 47 | 48 | local f4 f6 49 | local first_packet_only="$nft_connbytes 1-$(first_packets_for_mode)" 50 | local desync="mark and $DESYNC_MARK == 0" 51 | 52 | [ "$MODE_HTTP" = "1" ] && { 53 | f4="tcp dport {$HTTP_PORTS}" 54 | f6=$f4 55 | nft_filter_apply_ipset_target f4 f6 56 | nft_fw_tpws "$f4" "$f6" $TPPORT 57 | } 58 | 59 | [ "$MODE_HTTPS" = "1" ] && { 60 | f4="tcp dport {$HTTPS_PORTS} $first_packet_only" 61 | f6=$f4 62 | nft_filter_apply_ipset_target f4 f6 63 | nft_fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM 64 | # for modes that require incoming traffic 65 | nft_fw_reverse_nfqws_rule "$f4" "$f6" $QNUM 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /init.d/openwrt/custom.default: -------------------------------------------------------------------------------- 1 | # this script contain your special code to launch daemons and configure firewall 2 | # use helpers from "functions" file and "zapret" init script 3 | # in case of upgrade keep this file only, do not modify others 4 | 5 | zapret_custom_daemons() 6 | { 7 | # stop logic is managed by procd 8 | 9 | # PLACEHOLDER 10 | echo !!! NEED ATTENTION !!! 11 | echo Start daemon\(s\) 12 | echo Study how other sections work 13 | 14 | run_daemon 1 /bin/sleep 20 15 | } 16 | zapret_custom_firewall() 17 | { 18 | # $1 - 1 - run, 0 - stop 19 | 20 | # PLACEHOLDER 21 | echo !!! NEED ATTENTION !!! 22 | echo Configure iptables for required actions 23 | echo Study how other sections work 24 | } 25 | zapret_custom_firewall_nft() 26 | { 27 | # stop logic is not required 28 | 29 | # PLACEHOLDER 30 | echo !!! NEED ATTENTION !!! 31 | echo Configure nftables for required actions 32 | echo Study how other sections work 33 | } 34 | -------------------------------------------------------------------------------- /init.d/openwrt/firewall.zapret: -------------------------------------------------------------------------------- 1 | SCRIPT=$(readlink /etc/init.d/zapret) 2 | if [ -n "$SCRIPT" ]; then 3 | EXEDIR=$(dirname "$SCRIPT") 4 | ZAPRET_BASE=$(readlink -f "$EXEDIR/../..") 5 | else 6 | ZAPRET_BASE=/opt/zapret 7 | fi 8 | 9 | . "$ZAPRET_BASE/init.d/openwrt/functions" 10 | 11 | zapret_apply_firewall 12 | -------------------------------------------------------------------------------- /init.d/pfsense/zapret.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # this file should be placed to /usr/local/etc/rc.d and chmod 755 4 | 5 | # prepare system 6 | 7 | kldload ipfw 8 | kldload ipdivert 9 | 10 | # for older pfsense versions. newer do not have these sysctls 11 | sysctl net.inet.ip.pfil.outbound=ipfw,pf 12 | sysctl net.inet.ip.pfil.inbound=ipfw,pf 13 | sysctl net.inet6.ip6.pfil.outbound=ipfw,pf 14 | sysctl net.inet6.ip6.pfil.inbound=ipfw,pf 15 | 16 | # required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state 17 | pfctl -d ; pfctl -e 18 | 19 | # add ipfw rules and start daemon 20 | 21 | ipfw delete 100 22 | ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted not sockarg 23 | pkill ^dvtws$ 24 | dvtws --daemon --port 989 --dpi-desync=split2 25 | -------------------------------------------------------------------------------- /init.d/runit/zapret/finish: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /opt/zapret/init.d/sysv/zapret stop 3 | -------------------------------------------------------------------------------- /init.d/runit/zapret/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /opt/zapret/init.d/sysv/zapret start 3 | exec chpst -b zapret sleep infinity 4 | -------------------------------------------------------------------------------- /init.d/s6/zapret/down: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -P 2 | exec /opt/zapret/init.d/sysv/zapret stop 3 | -------------------------------------------------------------------------------- /init.d/s6/zapret/type: -------------------------------------------------------------------------------- 1 | oneshot 2 | -------------------------------------------------------------------------------- /init.d/s6/zapret/up: -------------------------------------------------------------------------------- 1 | #!/bin/execlineb -P 2 | exec /opt/zapret/init.d/sysv/zapret start 3 | -------------------------------------------------------------------------------- /init.d/systemd/zapret-list-update.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=zapret 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/zapret/ipset/get_config.sh 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /init.d/systemd/zapret-list-update.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=zapret 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=zapret-list-update.service 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /init.d/systemd/zapret.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/zapret/init.d/sysv/zapret start 14 | ExecStop=/opt/zapret/init.d/sysv/zapret stop 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /init.d/sysv/custom-nfqws-dht4all: -------------------------------------------------------------------------------- 1 | # this custom script in addition to MODE=nfqws runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering 2 | # need to add to config : NFQWS_OPT_DESYNC_DHT="--dpi-desync=fake --dpi-desync-ttl=5" 3 | 4 | QNUM2=$(($QNUM+20)) 5 | 6 | zapret_custom_daemons() 7 | { 8 | # stop logic is managed by procd 9 | 10 | local MODE_OVERRIDE=nfqws 11 | local opt 12 | 13 | zapret_do_daemons $1 14 | 15 | opt="--qnum=$QNUM2 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_DHT" 16 | do_nfqws $1 100 "$opt" 17 | } 18 | zapret_custom_firewall() 19 | { 20 | # $1 - 1 - run, 0 - stop 21 | 22 | local MODE_OVERRIDE=nfqws 23 | local f uf4 uf6 24 | local first_packet_only="$ipt_connbytes 1:1" 25 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 26 | 27 | zapret_do_firewall_rules_ipt $1 28 | 29 | f='-p udp -m length --length 109:407 -m u32 --u32' 30 | uf4='0>>22&0x3C@8>>16=0x6431' 31 | uf6='48>>16=0x6431' 32 | fw_nfqws_post $1 "$f $uf4 $desync $first_packet_only" "$f $uf6 $desync $first_packet_only" $QNUM2 33 | 34 | } 35 | zapret_custom_firewall_nft() 36 | { 37 | # stop logic is not required 38 | 39 | local MODE_OVERRIDE=nfqws 40 | local f 41 | local first_packet_only="$nft_connbytes 1" 42 | local desync="mark and $DESYNC_MARK == 0" 43 | 44 | zapret_apply_firewall_rules_nft 45 | 46 | f="meta length 109-407 meta l4proto udp @th,64,16 0x6431" 47 | nft_fw_nfqws_post "$f $desync $first_packet_only" "$f $desync $first_packet_only" $QNUM2 48 | } 49 | 50 | -------------------------------------------------------------------------------- /init.d/sysv/custom-nfqws-quic4all: -------------------------------------------------------------------------------- 1 | # this custom script in addition to MODE=nfqws runs desync to all QUIC initial packets, without ipset/hostlist filtering 2 | # need to add to config : NFQWS_OPT_DESYNC_QUIC="--dpi-desync=fake" 3 | # NOTE : do not use TTL fooling. chromium QUIC engine breaks sessions if TTL expired in transit received 4 | 5 | QNUM2=$(($QNUM+10)) 6 | 7 | zapret_custom_daemons() 8 | { 9 | # $1 - 1 - run, 0 - stop 10 | 11 | local MODE_OVERRIDE=nfqws 12 | local opt 13 | 14 | zapret_do_daemons $1 15 | 16 | opt="--qnum=$QNUM2 $NFQWS_OPT_BASE $NFQWS_OPT_DESYNC_QUIC" 17 | do_nfqws $1 100 "$opt" 18 | } 19 | zapret_custom_firewall() 20 | { 21 | # $1 - 1 - run, 0 - stop 22 | 23 | local MODE_OVERRIDE=nfqws 24 | local f 25 | local first_packets_only="$ipt_connbytes 1:3" 26 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 27 | 28 | zapret_do_firewall_rules_ipt $1 29 | 30 | f="-p udp -m multiport --dports $QUIC_PORTS_IPT" 31 | fw_nfqws_post $1 "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2 32 | 33 | } 34 | zapret_custom_firewall_nft() 35 | { 36 | # stop logic is not required 37 | 38 | local MODE_OVERRIDE=nfqws 39 | local f 40 | local first_packets_only="$nft_connbytes 1-3" 41 | local desync="mark and $DESYNC_MARK == 0" 42 | 43 | zapret_apply_firewall_rules_nft 44 | 45 | f="udp dport {$QUIC_PORTS}" 46 | nft_fw_nfqws_post "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2 47 | } 48 | -------------------------------------------------------------------------------- /init.d/sysv/custom-reuse-builtin-mode: -------------------------------------------------------------------------------- 1 | # this custom script demonstrates how to reuse built-in modes and add something from yourself 2 | 3 | MY_TPPORT=$(($TPPORT + 1)) 4 | MY_TPWS_OPT="--methodeol --hostcase" 5 | MY_DPORT=81 6 | 7 | zapret_custom_daemons() 8 | { 9 | # $1 - 1 - run, 0 - stop 10 | 11 | local MODE_OVERRIDE=tpws 12 | local opt 13 | 14 | zapret_do_daemons $1 15 | 16 | opt="--port=$MY_TPPORT $MY_TPWS_OPT" 17 | filter_apply_hostlist_target opt 18 | do_tpws $1 100 "$opt" 19 | } 20 | zapret_custom_firewall() 21 | { 22 | # $1 - 1 - run, 0 - stop 23 | 24 | local MODE_OVERRIDE=tpws 25 | local f4 f6 26 | 27 | zapret_do_firewall_rules_ipt $1 28 | 29 | f4="-p tcp --dport $MY_DPORT" 30 | f6=$f4 31 | filter_apply_ipset_target f4 f6 32 | fw_tpws $1 "$f4" "$f6" $MY_TPPORT 33 | } 34 | zapret_custom_firewall_nft() 35 | { 36 | # stop logic is not required 37 | 38 | local MODE_OVERRIDE=tpws 39 | local f4 f6 40 | 41 | zapret_apply_firewall_rules_nft 42 | 43 | f4="tcp dport $MY_DPORT" 44 | f6=$f4 45 | nft_filter_apply_ipset_target f4 f6 46 | nft_fw_tpws "$f4" "$f6" $MY_TPPORT 47 | } 48 | -------------------------------------------------------------------------------- /init.d/sysv/custom-tpws4http-nfqws4https: -------------------------------------------------------------------------------- 1 | # this custom script demonstrates how to apply tpws to http and nfqws to https 2 | # it preserves config settings : MODE_HTTP, MODE_HTTPS, MODE_FILTER, TPWS_OPT, NFQWS_OPT_DESYNC, NFQWS_OPT_DESYNC_HTTPS 3 | 4 | zapret_custom_daemons() 5 | { 6 | # $1 - 1 - run, 0 - stop 7 | 8 | local opt 9 | 10 | [ "$MODE_HTTP" = "1" ] && { 11 | opt="--port=$TPPORT $TPWS_OPT" 12 | filter_apply_hostlist_target opt 13 | do_tpws $1 1 "$opt" 14 | } 15 | 16 | [ "$MODE_HTTPS" = "1" ] && { 17 | opt="--qnum=$QNUM $NFQWS_OPT_DESYNC_HTTPS" 18 | filter_apply_hostlist_target opt 19 | do_nfqws $1 2 "$opt" 20 | } 21 | } 22 | zapret_custom_firewall() 23 | { 24 | # $1 - 1 - run, 0 - stop 25 | 26 | local f4 f6 27 | local first_packet_only="$ipt_connbytes 1:$(first_packets_for_mode)" 28 | local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" 29 | 30 | [ "$MODE_HTTP" = "1" ] && { 31 | f4="-p tcp -m multiport --dports $HTTP_PORTS_IPT" 32 | f6=$f4 33 | filter_apply_ipset_target f4 f6 34 | fw_tpws $1 "$f4" "$f6" $TPPORT 35 | } 36 | 37 | [ "$MODE_HTTPS" = "1" ] && { 38 | f4="-p tcp -m multiport --dports $HTTPS_PORTS_IPT $first_packet_only" 39 | f6=$f4 40 | filter_apply_ipset_target f4 f6 41 | fw_nfqws_post $1 "$f4 $desync" "$f6 $desync" $QNUM 42 | # for modes that require incoming traffic 43 | fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM 44 | } 45 | } 46 | zapret_custom_firewall_nft() 47 | { 48 | # stop logic is not required 49 | 50 | local f4 f6 51 | local first_packet_only="$nft_connbytes 1-$(first_packets_for_mode)" 52 | local desync="mark and $DESYNC_MARK == 0" 53 | 54 | [ "$MODE_HTTP" = "1" ] && { 55 | f4="tcp dport {$HTTP_PORTS}" 56 | f6=$f4 57 | nft_filter_apply_ipset_target f4 f6 58 | nft_fw_tpws "$f4" "$f6" $TPPORT 59 | } 60 | 61 | [ "$MODE_HTTPS" = "1" ] && { 62 | f4="tcp dport {$HTTPS_PORTS} $first_packet_only" 63 | f6=$f4 64 | nft_filter_apply_ipset_target f4 f6 65 | nft_fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM 66 | # for modes that require incoming traffic 67 | nft_fw_reverse_nfqws_rule "$f4" "$f6" $QNUM 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /init.d/sysv/custom.default: -------------------------------------------------------------------------------- 1 | # this script contain your special code to launch daemons and configure firewall 2 | # use helpers from "functions" file 3 | # in case of upgrade keep this file only, do not modify others 4 | 5 | zapret_custom_daemons() 6 | { 7 | # $1 - 1 - run, 0 - stop 8 | 9 | # PLACEHOLDER 10 | echo !!! NEED ATTENTION !!! 11 | echo Start daemon\(s\) 12 | echo Study how other sections work 13 | 14 | do_daemon $1 1 /bin/sleep 20 15 | } 16 | zapret_custom_firewall() 17 | { 18 | # $1 - 1 - run, 0 - stop 19 | 20 | # PLACEHOLDER 21 | echo !!! NEED ATTENTION !!! 22 | echo Configure iptables for required actions 23 | echo Study how other sections work 24 | } 25 | 26 | zapret_custom_firewall_nft() 27 | { 28 | # stop logic is not required 29 | 30 | # PLACEHOLDER 31 | echo !!! NEED ATTENTION !!! 32 | echo Configure nftables for required actions 33 | echo Study how other sections work 34 | } 35 | -------------------------------------------------------------------------------- /init.d/sysv/zapret: -------------------------------------------------------------------------------- 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 | N=/etc/init.d/$NAME 78 | echo "Usage: $N {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2 79 | exit 1 80 | ;; 81 | esac 82 | 83 | exit 0 84 | -------------------------------------------------------------------------------- /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="$EXEDIR" 9 | . "$ZAPRET_BASE/common/base.sh" 10 | 11 | check_dir() 12 | { 13 | local dir="$BINDIR/$1" 14 | local exe="$dir/ip2net" 15 | local out 16 | if [ -f "$exe" ]; then 17 | if [ -x "$exe" ]; then 18 | # ash and dash try to execute invalid executables as a script. they interpret binary garbage with possible negative consequences 19 | # bash and zsh do not do this 20 | if exists bash; then 21 | out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null) 22 | elif exists zsh; then 23 | out=$(echo 0.0.0.0 | zsh -c "\"$exe\"" 2>/dev/null) 24 | else 25 | # find does not use its own shell exec 26 | # it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh 27 | # that's why prefer bash or zsh if present. otherwise it's our last chance 28 | out=$(echo 0.0.0.0 | find "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null) 29 | fi 30 | [ -n "$out" ] 31 | else 32 | echo "$exe is not executable. set proper chmod." 33 | return 1 34 | fi 35 | else 36 | echo "$exe is absent" 37 | return 2 38 | fi 39 | } 40 | 41 | # link or copy executables. uncomment either ln or cp, comment other 42 | ccp() 43 | { 44 | local F=$(basename $1) 45 | [ -d "$EXEDIR/$2" ] || mkdir "$EXEDIR/$2" 46 | [ -f "$EXEDIR/$2/$F" ] && rm -f "$EXEDIR/$2/$F" 47 | ln -fs "../$BINS/$1" "$EXEDIR/$2" && echo linking : "../$BINS/$1" =\> "$EXEDIR/$2" 48 | #cp -f "$BINDIR/$1" "$EXEDIR/$2" && echo copying : "$BINDIR/$1" =\> "$EXEDIR/$2" 49 | } 50 | 51 | UNAME=$(uname) 52 | unset PKTWS 53 | case $UNAME in 54 | Linux) 55 | ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb ppc" 56 | PKTWS=nfqws 57 | ;; 58 | Darwin) 59 | ARCHLIST="my mac64" 60 | ;; 61 | FreeBSD) 62 | ARCHLIST="my freebsd-x64" 63 | PKTWS=dvtws 64 | ;; 65 | CYGWIN*) 66 | UNAME=CYGWIN 67 | ARCHLIST="win64" 68 | PKTWS=winws 69 | ;; 70 | *) 71 | ARCHLIST="my" 72 | esac 73 | 74 | if [ "$1" = "getarch" ]; then 75 | for arch in $ARCHLIST 76 | do 77 | [ -d "$BINDIR/$arch" ] || continue 78 | if check_dir $arch; then 79 | echo $arch 80 | exit 0 81 | fi 82 | done 83 | else 84 | for arch in $ARCHLIST 85 | do 86 | [ -d "$BINDIR/$arch" ] || continue 87 | if check_dir $arch; then 88 | echo $arch is OK 89 | echo installing binaries ... 90 | ccp $arch/ip2net ip2net 91 | ccp $arch/mdig mdig 92 | [ -n "$PKTWS" ] && ccp $arch/$PKTWS nfq 93 | [ "$UNAME" = CYGWIN ] || ccp $arch/tpws tpws 94 | exit 0 95 | else 96 | echo $arch is NOT OK 97 | fi 98 | done 99 | echo no compatible binaries found 100 | fi 101 | 102 | exit 1 103 | -------------------------------------------------------------------------------- /install_prereq.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # install prerequisites 4 | 5 | EXEDIR="$(dirname "$0")" 6 | EXEDIR="$(cd "$EXEDIR"; pwd)" 7 | ZAPRET_CONFIG="$EXEDIR/config" 8 | ZAPRET_BASE="$EXEDIR" 9 | 10 | [ -f "$ZAPRET_CONFIG" ] || cp "${ZAPRET_CONFIG}.default" "$ZAPRET_CONFIG" 11 | . "$ZAPRET_CONFIG" 12 | . "$ZAPRET_BASE/common/base.sh" 13 | . "$ZAPRET_BASE/common/elevate.sh" 14 | . "$ZAPRET_BASE/common/fwtype.sh" 15 | . "$ZAPRET_BASE/common/dialog.sh" 16 | . "$ZAPRET_BASE/common/installer.sh" 17 | . "$ZAPRET_BASE/common/ipt.sh" 18 | 19 | umask 0022 20 | fix_sbin_path 21 | fsleep_setup 22 | check_system accept_unknown_rc 23 | [ $UNAME = "Linux" ] || { 24 | echo no prerequisites required for $UNAME 25 | exitp 0 26 | } 27 | require_root 28 | 29 | case $UNAME in 30 | Linux) 31 | select_fwtype 32 | case $SYSTEM in 33 | openwrt) 34 | select_ipv6 35 | check_prerequisites_openwrt 36 | ;; 37 | *) 38 | check_prerequisites_linux 39 | ;; 40 | esac 41 | ;; 42 | esac 43 | 44 | exitp 0 45 | -------------------------------------------------------------------------------- /ip2net/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3 3 | CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch 4 | CFLAGS_WIN = -static 5 | LIBS = 6 | LIBS_WIN = -lws2_32 7 | SRC_FILES = ip2net.c qsort.c 8 | 9 | all: ip2net 10 | 11 | ip2net: $(SRC_FILES) 12 | $(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS) 13 | 14 | bsd: $(SRC_FILES) 15 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS) 16 | 17 | mac: $(SRC_FILES) 18 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2neta $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS) 19 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o ip2netx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS) 20 | strip ip2neta ip2netx 21 | lipo -create -output ip2net ip2netx ip2neta 22 | rm -f ip2netx ip2neta 23 | 24 | win: $(SRC_FILES) 25 | $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o ip2net $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN) 26 | 27 | clean: 28 | rm -f ip2net *.o 29 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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=$(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 | -------------------------------------------------------------------------------- /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_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_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 | -------------------------------------------------------------------------------- /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_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://internat12.ru/images/DOC/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=$(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 | -------------------------------------------------------------------------------- /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 | . "$IPSET_DIR/../config" 8 | 9 | [ -z "$GETLIST" ] && GETLIST=get_ipban.sh 10 | [ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST" 11 | -------------------------------------------------------------------------------- /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 | 13 | [ "$MODE_FILTER" = hostlist ] && hup_zapret_daemons 14 | -------------------------------------------------------------------------------- /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 | 13 | [ "$MODE_FILTER" = hostlist ] && hup_zapret_daemons 14 | -------------------------------------------------------------------------------- /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" 9 | IPB="$TMPDIR/ipb.txt" 10 | ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv 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=$(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 | LANG=C cut -s -f2 -d';' "$ZREESTR" | 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 | LANG=C nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' "$ZREESTR" | 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 | -------------------------------------------------------------------------------- /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=$(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 | zzcat "$TMPLIST" | zz "$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=$(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 | zzcat "$TMPLIST" | zz "$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_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=$(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 | zzcat "$TMPLIST" | zz "$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 | -------------------------------------------------------------------------------- /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" 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 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=$(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 | LANG=C cut -s -f2 -d';' "$ZREESTR" | LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' 38 | } 39 | reestr_extract_ip() 40 | { 41 | LANG=C nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' "$ZREESTR" | 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 | -------------------------------------------------------------------------------- /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/zapret-hosts-user-exclude.txt.default: -------------------------------------------------------------------------------- 1 | 10.0.0.0/8 2 | 172.16.0.0/12 3 | 192.168.0.0/16 4 | 169.254.0.0/16 5 | fc00::/7 6 | fe80::/10 7 | -------------------------------------------------------------------------------- /mdig/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3 3 | CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch 4 | CFLAGS_WIN = -static 5 | LIBS = -lpthread 6 | LIBS_WIN = -lws2_32 7 | SRC_FILES = *.c 8 | 9 | all: mdig 10 | 11 | mdig: $(SRC_FILES) 12 | $(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS) 13 | 14 | bsd: $(SRC_FILES) 15 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS) 16 | 17 | mac: $(SRC_FILES) 18 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdiga $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS_BSD) 19 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o mdigx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS_BSD) 20 | strip mdiga mdigx 21 | lipo -create -output mdig mdigx mdiga 22 | rm -f mdigx mdiga 23 | 24 | win: $(SRC_FILES) 25 | $(CC) -s $(CFLAGS) $(CFLAGS_WIN) -o mdig $(SRC_FILES) $(LDFLAGS) $(LIBS_WIN) 26 | 27 | clean: 28 | rm -f mdig *.o 29 | -------------------------------------------------------------------------------- /nfq/BSDmakefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | CFLAGS += -std=gnu99 -s -O3 -Wno-address-of-packed-member -Wno-logical-op-parentheses -Wno-switch 3 | LIBS = -lz 4 | SRC_FILES = *.c crypto/*.c 5 | 6 | all: dvtws 7 | 8 | dvtws: $(SRC_FILES) 9 | $(CC) $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS) 10 | 11 | clean: 12 | rm -f dvtws 13 | -------------------------------------------------------------------------------- /nfq/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3 3 | CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch 4 | CFLAGS_MAC = -mmacosx-version-min=10.8 5 | CFLAGS_CYGWIN = -Wno-address-of-packed-member -static 6 | LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz 7 | LIBS_BSD = -lz 8 | LIBS_CYGWIN = -lz -Lwindivert -lwindivert -lwlanapi -lole32 -loleaut32 -luuid 9 | SRC_FILES = *.c crypto/*.c 10 | 11 | all: nfqws 12 | 13 | nfqws: $(SRC_FILES) 14 | $(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS_LINUX) 15 | 16 | bsd: $(SRC_FILES) 17 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o dvtws $(SRC_FILES) $(LDFLAGS) $(LIBS_BSD) 18 | 19 | mac: $(SRC_FILES) 20 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsa $(SRC_FILES) $(LDFLAGS) -target arm64-apple-macos10.8 $(LIBS_BSD) 21 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -o dvtwsx $(SRC_FILES) $(LDFLAGS) -target x86_64-apple-macos10.8 $(LIBS_BSD) 22 | strip dvtwsa dvtwsx 23 | lipo -create -output dvtws dvtwsx dvtwsa 24 | rm -f dvtwsx dvtwsa 25 | 26 | cygwin: 27 | $(CC) -s $(CFLAGS) $(CFLAGS_CYGWIN) -o winws $(SRC_FILES) $(LDFLAGS) $(LIBS_CYGWIN) winmanifest.o winicon.o 28 | 29 | clean: 30 | rm -f nfqws dvtws winws.exe 31 | -------------------------------------------------------------------------------- /nfq/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 | -------------------------------------------------------------------------------- /nfq/checksum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | uint16_t csum_partial(const void *buff, size_t len); 13 | uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum); 14 | uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum); 15 | 16 | uint16_t ip4_compute_csum(const void *buff, size_t len); 17 | void ip4_fix_checksum(struct ip *ip); 18 | 19 | void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr); 20 | void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr); 21 | void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr); 22 | 23 | void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr); 24 | void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr); 25 | void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr); 26 | -------------------------------------------------------------------------------- /nfq/conntrack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // this conntrack is not bullet-proof 4 | // its designed to satisfy dpi desync needs only 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "packet_queue.h" 18 | 19 | //#define HASH_BLOOM 20 20 | #define HASH_NONFATAL_OOM 1 21 | #undef HASH_FUNCTION 22 | #define HASH_FUNCTION HASH_BER 23 | #include "uthash.h" 24 | 25 | #define RETRANS_COUNTER_STOP ((uint8_t)-1) 26 | 27 | typedef union { 28 | struct in_addr ip; 29 | struct in6_addr ip6; 30 | } t_addr; 31 | typedef struct 32 | { 33 | t_addr src, dst; 34 | uint16_t sport,dport; 35 | uint8_t l3proto; // IPPROTO_IP, IPPROTO_IPV6 36 | uint8_t l4proto; // IPPROTO_TCP, IPPROTO_UDP 37 | } t_conn; 38 | 39 | // this structure helps to reassemble continuous packets streams. it does not support out-of-orders 40 | typedef struct { 41 | uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size. 42 | uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session. 43 | size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet' 44 | size_t size_present; // how many bytes already stored in 'packet' 45 | } t_reassemble; 46 | 47 | // SYN - SYN or SYN/ACK received 48 | // ESTABLISHED - any except SYN or SYN/ACK received 49 | // FIN - FIN or RST received 50 | typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate; 51 | typedef enum {UNKNOWN=0, HTTP, TLS, QUIC, WIREGUARD, DHT} t_l7proto; 52 | typedef struct 53 | { 54 | // common state 55 | time_t t_start, t_last; 56 | uint64_t pcounter_orig, pcounter_reply; // packet counter 57 | uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload) 58 | uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current 59 | uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current 60 | 61 | // tcp only state, not used in udp 62 | t_connstate state; 63 | uint32_t seq0, ack0; // starting seq and ack 64 | uint16_t winsize_orig, winsize_reply; // last seen window size 65 | uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none 66 | 67 | uint8_t req_retrans_counter; // number of request retransmissions 68 | bool req_seq_present,req_seq_finalized,req_seq_abandoned; 69 | uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions) 70 | 71 | uint8_t autottl; 72 | 73 | bool b_cutoff; // mark for deletion 74 | bool b_wssize_cutoff, b_desync_cutoff; 75 | 76 | t_l7proto l7proto; 77 | char *hostname; 78 | bool hostname_ah_check; // should perform autohostlist checks 79 | 80 | t_reassemble reasm_orig; 81 | struct rawpacket_tailhead delayed; 82 | } t_ctrack; 83 | 84 | typedef struct 85 | { 86 | t_ctrack track; 87 | UT_hash_handle hh; // makes this structure hashable 88 | t_conn conn; // key 89 | } t_conntrack_pool; 90 | typedef struct 91 | { 92 | // inactivity time to purge an entry in each connection state 93 | uint32_t timeout_syn,timeout_established,timeout_fin,timeout_udp; 94 | time_t t_purge_interval, t_last_purge; 95 | t_conntrack_pool *pool; 96 | } t_conntrack; 97 | 98 | 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); 99 | void ConntrackPoolDestroy(t_conntrack *p); 100 | 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); 101 | // do not create, do not update. only find existing 102 | 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); 103 | bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); 104 | void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr); 105 | void ConntrackPoolDump(const t_conntrack *p); 106 | void ConntrackPoolPurge(t_conntrack *p); 107 | void ConntrackClearHostname(t_ctrack *track); 108 | 109 | bool ReasmInit(t_reassemble *reasm, size_t size_requested, uint32_t seq_start); 110 | bool ReasmResize(t_reassemble *reasm, size_t new_size); 111 | void ReasmClear(t_reassemble *reasm); 112 | // false means reassemble session has failed and we should ReasmClear() it 113 | bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len); 114 | // check if it has enough space to buffer 'len' bytes 115 | bool ReasmHasSpace(t_reassemble *reasm, size_t len); 116 | inline static bool ReasmIsEmpty(t_reassemble *reasm) {return !reasm->size;} 117 | inline static bool ReasmIsFull(t_reassemble *reasm) {return !ReasmIsEmpty(reasm) && (reasm->size==reasm->size_present);} 118 | -------------------------------------------------------------------------------- /nfq/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_setkey(&ctx, key, (const uint)key_len); 9 | ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len); 10 | gcm_zero_ctx(&ctx); 11 | 12 | return ret; 13 | } 14 | -------------------------------------------------------------------------------- /nfq/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 | -------------------------------------------------------------------------------- /nfq/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 0 // 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 | -------------------------------------------------------------------------------- /nfq/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 | -------------------------------------------------------------------------------- /nfq/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 | -------------------------------------------------------------------------------- /nfq/desync.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "darkmagic.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef __linux__ 13 | #define DPI_DESYNC_FWMARK_DEFAULT 0x40000000 14 | #else 15 | #define DPI_DESYNC_FWMARK_DEFAULT 512 16 | #endif 17 | 18 | #define DPI_DESYNC_MAX_FAKE_LEN 9216 19 | 20 | enum dpi_desync_mode { 21 | DESYNC_NONE=0, 22 | DESYNC_INVALID, 23 | DESYNC_FAKE, 24 | DESYNC_FAKE_KNOWN, 25 | DESYNC_RST, 26 | DESYNC_RSTACK, 27 | DESYNC_SYNACK, 28 | DESYNC_SYNDATA, 29 | DESYNC_DISORDER, 30 | DESYNC_DISORDER2, 31 | DESYNC_SPLIT, 32 | DESYNC_SPLIT2, 33 | DESYNC_IPFRAG2, 34 | DESYNC_HOPBYHOP, 35 | DESYNC_DESTOPT, 36 | DESYNC_IPFRAG1, 37 | DESYNC_UDPLEN, 38 | DESYNC_TAMPER 39 | }; 40 | 41 | extern const char *fake_http_request_default; 42 | extern const uint8_t fake_tls_clienthello_default[517]; 43 | 44 | enum dpi_desync_mode desync_mode_from_string(const char *s); 45 | bool desync_valid_zero_stage(enum dpi_desync_mode mode); 46 | bool desync_valid_first_stage(enum dpi_desync_mode mode); 47 | bool desync_only_first_stage(enum dpi_desync_mode mode); 48 | bool desync_valid_second_stage(enum dpi_desync_mode mode); 49 | bool desync_valid_second_stage_tcp(enum dpi_desync_mode mode); 50 | bool desync_valid_second_stage_udp(enum dpi_desync_mode mode); 51 | 52 | void desync_init(void); 53 | uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt); 54 | -------------------------------------------------------------------------------- /nfq/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 | if (*buf) 69 | { 70 | free(*buf); 71 | *buf = NULL; 72 | } 73 | return r; 74 | } 75 | 76 | bool is_gzip(FILE* F) 77 | { 78 | unsigned char magic[2]; 79 | bool b = !fseek(F, 0, SEEK_SET) && fread(magic, 1, 2, F) == 2 && magic[0] == 0x1F && magic[1] == 0x8B; 80 | fseek(F, 0, SEEK_SET); 81 | return b; 82 | } 83 | -------------------------------------------------------------------------------- /nfq/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 | -------------------------------------------------------------------------------- /nfq/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit); 13 | char *strncasestr(const char *s,const char *find, size_t slen); 14 | bool load_file(const char *filename,void *buffer,size_t *buffer_size); 15 | bool load_file_nonempty(const char *filename,void *buffer,size_t *buffer_size); 16 | bool save_file(const char *filename, const void *buffer, size_t buffer_size); 17 | bool append_to_list_file(const char *filename, const char *s); 18 | 19 | void print_sockaddr(const struct sockaddr *sa); 20 | void ntop46(const struct sockaddr *sa, char *str, size_t len); 21 | void ntop46_port(const struct sockaddr *sa, char *str, size_t len); 22 | bool pton4_port(const char *s, struct sockaddr_in *sa); 23 | bool pton6_port(const char *s, struct sockaddr_in6 *sa); 24 | 25 | bool seq_within(uint32_t s, uint32_t s1, uint32_t s2); 26 | 27 | void dbgprint_socket_buffers(int fd); 28 | bool set_socket_buffers(int fd, int rcvbuf, int sndbuf); 29 | 30 | uint64_t pntoh64(const void *p); 31 | void phton64(uint8_t *p, uint64_t v); 32 | 33 | bool ipv6_addr_is_zero(const struct in6_addr *a); 34 | 35 | static inline uint16_t pntoh16(const uint8_t *p) { 36 | return ((uint16_t)p[0] << 8) | (uint16_t)p[1]; 37 | } 38 | static inline void phton16(uint8_t *p, uint16_t v) { 39 | p[0] = (uint8_t)(v >> 8); 40 | p[1] = v & 0xFF; 41 | } 42 | static inline uint32_t pntoh32(const uint8_t *p) { 43 | return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3]; 44 | } 45 | 46 | bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size); 47 | void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize); 48 | 49 | int fprint_localtime(FILE *F); 50 | 51 | time_t file_mod_time(const char *filename); 52 | 53 | typedef struct 54 | { 55 | uint16_t from,to; 56 | bool neg; 57 | } port_filter; 58 | bool pf_in_range(uint16_t port, const port_filter *pf); 59 | bool pf_parse(const char *s, port_filter *pf); 60 | -------------------------------------------------------------------------------- /nfq/hostlist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hostlist.h" 3 | #include "gzip.h" 4 | #include "params.h" 5 | #include "helpers.h" 6 | 7 | // inplace tolower() and add to pool 8 | static bool addpool(strpool **hostlist, char **s, const char *end) 9 | { 10 | char *p; 11 | 12 | // advance until eol lowering all chars 13 | for (p = *s; pstr)) return false; 105 | } 106 | return true; 107 | } 108 | 109 | bool NonEmptyHostlist(strpool **hostlist) 110 | { 111 | // add impossible hostname if the list is empty 112 | return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4); 113 | } 114 | 115 | 116 | bool SearchHostList(strpool *hostlist, const char *host) 117 | { 118 | if (hostlist) 119 | { 120 | const char *p = host; 121 | bool bInHostList; 122 | while (p) 123 | { 124 | bInHostList = StrPoolCheckStr(hostlist, p); 125 | if (params.debug) printf("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative"); 126 | if (bInHostList) return true; 127 | p = strchr(p, '.'); 128 | if (p) p++; 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | // return : true = apply fooling, false = do not apply 135 | static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const char *host, bool *excluded) 136 | { 137 | if (excluded) *excluded = false; 138 | if (hostlist_exclude) 139 | { 140 | if (params.debug) printf("Checking exclude hostlist\n"); 141 | if (SearchHostList(hostlist_exclude, host)) 142 | { 143 | if (excluded) *excluded = true; 144 | return false; 145 | } 146 | } 147 | if (hostlist) 148 | { 149 | if (params.debug) printf("Checking include hostlist\n"); 150 | return SearchHostList(hostlist, host); 151 | } 152 | return true; 153 | } 154 | 155 | // return : true = apply fooling, false = do not apply 156 | bool HostlistCheck(const char *host, bool *excluded) 157 | { 158 | if (*params.hostlist_auto_filename) 159 | { 160 | time_t t = file_mod_time(params.hostlist_auto_filename); 161 | if (t!=params.hostlist_auto_mod_time) 162 | { 163 | printf("Autohostlist was modified by another process. Reloading include hostslist.\n"); 164 | if (!LoadIncludeHostLists()) 165 | { 166 | // what will we do without hostlist ?? sure, gonna die 167 | exit(1); 168 | } 169 | params.hostlist_auto_mod_time = t; 170 | NonEmptyHostlist(¶ms.hostlist); 171 | } 172 | } 173 | return HostlistCheck_(params.hostlist, params.hostlist_exclude, host, excluded); 174 | } 175 | 176 | bool LoadIncludeHostLists() 177 | { 178 | if (!LoadHostLists(¶ms.hostlist, ¶ms.hostlist_files)) 179 | return false; 180 | if (*params.hostlist_auto_filename) 181 | params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename); 182 | return true; 183 | } 184 | bool LoadExcludeHostLists() 185 | { 186 | return LoadHostLists(¶ms.hostlist_exclude, ¶ms.hostlist_exclude_files); 187 | } 188 | -------------------------------------------------------------------------------- /nfq/hostlist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "pools.h" 5 | 6 | bool AppendHostList(strpool **hostlist, char *filename); 7 | bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list); 8 | bool LoadIncludeHostLists(); 9 | bool LoadExcludeHostLists(); 10 | bool NonEmptyHostlist(strpool **hostlist); 11 | bool SearchHostList(strpool *hostlist, const char *host); 12 | // return : true = apply fooling, false = do not apply 13 | bool HostlistCheck(const char *host, bool *excluded); -------------------------------------------------------------------------------- /nfq/nfqws.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __CYGWIN__ 6 | extern bool bQuit; 7 | #endif 8 | int main(int argc, char *argv[]); 9 | -------------------------------------------------------------------------------- /nfq/packet_queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "packet_queue.h" 5 | 6 | void rawpacket_queue_init(struct rawpacket_tailhead *q) 7 | { 8 | TAILQ_INIT(q); 9 | } 10 | void rawpacket_free(struct rawpacket *rp) 11 | { 12 | if (rp) free(rp->packet); 13 | free(rp); 14 | } 15 | struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q) 16 | { 17 | struct rawpacket *rp; 18 | rp = TAILQ_FIRST(q); 19 | if (rp) TAILQ_REMOVE(q, rp, next); 20 | return rp; 21 | } 22 | void rawpacket_queue_destroy(struct rawpacket_tailhead *q) 23 | { 24 | struct rawpacket *rp; 25 | while((rp = rawpacket_dequeue(q))) rawpacket_free(rp); 26 | } 27 | 28 | struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload) 29 | { 30 | struct rawpacket *rp = malloc(sizeof(struct rawpacket)); 31 | if (!rp) return NULL; 32 | 33 | rp->packet = malloc(len); 34 | if (!rp->packet) 35 | { 36 | free(rp); 37 | return NULL; 38 | } 39 | 40 | rp->dst = *dst; 41 | rp->fwmark = fwmark; 42 | if (ifout) 43 | { 44 | strncpy(rp->ifout,ifout,sizeof(rp->ifout)); 45 | rp->ifout[sizeof(rp->ifout)-1]=0; 46 | } 47 | else 48 | rp->ifout[0]=0; 49 | memcpy(rp->packet,data,len); 50 | rp->len=len; 51 | rp->len_payload=len_payload; 52 | 53 | TAILQ_INSERT_TAIL(q, rp, next); 54 | 55 | return rp; 56 | } 57 | 58 | unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q) 59 | { 60 | const struct rawpacket *rp; 61 | unsigned int ct=0; 62 | TAILQ_FOREACH(rp, q, next) ct++; 63 | return ct; 64 | } 65 | bool rawpacket_queue_empty(const struct rawpacket_tailhead *q) 66 | { 67 | return !TAILQ_FIRST(q); 68 | } 69 | -------------------------------------------------------------------------------- /nfq/packet_queue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct rawpacket 10 | { 11 | struct sockaddr_storage dst; 12 | char ifout[IFNAMSIZ+1]; 13 | uint32_t fwmark; 14 | size_t len, len_payload; 15 | uint8_t *packet; 16 | TAILQ_ENTRY(rawpacket) next; 17 | }; 18 | TAILQ_HEAD(rawpacket_tailhead, rawpacket); 19 | 20 | void rawpacket_queue_init(struct rawpacket_tailhead *q); 21 | void rawpacket_queue_destroy(struct rawpacket_tailhead *q); 22 | bool rawpacket_queue_empty(const struct rawpacket_tailhead *q); 23 | unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q); 24 | struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark,const char *ifout,const void *data,size_t len,size_t len_payload); 25 | struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q); 26 | void rawpacket_free(struct rawpacket *rp); 27 | -------------------------------------------------------------------------------- /nfq/params.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pools.h" 4 | #include "conntrack.h" 5 | #include "desync.h" 6 | #include "protocol.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define TLS_PARTIALS_ENABLE true 17 | 18 | #define Q_RCVBUF (128*1024) // in bytes 19 | #define Q_SNDBUF (64*1024) // in bytes 20 | #define RAW_SNDBUF (64*1024) // in bytes 21 | 22 | #define Q_MAXLEN 1024 // in packets 23 | 24 | #define BADSEQ_INCREMENT_DEFAULT -10000 25 | #define BADSEQ_ACK_INCREMENT_DEFAULT -66000 26 | 27 | #define IPFRAG_UDP_DEFAULT 8 28 | #define IPFRAG_TCP_DEFAULT 32 29 | 30 | #define UDPLEN_INCREMENT_DEFAULT 2 31 | 32 | #define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3 33 | #define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60 34 | #define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3 35 | 36 | struct params_s 37 | { 38 | bool debug; 39 | uint16_t wsize,wssize; 40 | uint8_t wscale,wsscale; 41 | char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence 42 | unsigned int wssize_cutoff; 43 | #ifdef __linux__ 44 | int qnum; 45 | #elif defined(BSD) 46 | uint16_t port; // divert port 47 | #endif 48 | char bind_fix4,bind_fix6; 49 | bool hostcase, hostnospace, domcase; 50 | char hostspell[4]; 51 | enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2; 52 | bool desync_retrans,desync_skip_nosni,desync_any_proto; 53 | unsigned int desync_repeats,desync_split_pos,desync_seqovl,desync_ipfrag_pos_tcp,desync_ipfrag_pos_udp; 54 | enum httpreqpos desync_split_http_req; 55 | enum tlspos desync_split_tls; 56 | char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence 57 | unsigned int desync_start, desync_cutoff; 58 | uint8_t desync_ttl, desync_ttl6; 59 | autottl desync_autottl, desync_autottl6; 60 | uint32_t desync_fooling_mode; 61 | uint32_t desync_fwmark; // unused in BSD 62 | uint32_t desync_badseq_increment, desync_badseq_ack_increment; 63 | uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460]; 64 | uint8_t fake_unknown_udp[1472],udplen_pattern[1472],fake_quic[1472],fake_wg[1472],fake_dht[1472]; 65 | size_t fake_http_size,fake_tls_size,fake_quic_size,fake_wg_size,fake_dht_size,fake_unknown_size,fake_syndata_size,fake_unknown_udp_size; 66 | int udplen_increment; 67 | 68 | #ifdef __CYGWIN__ 69 | struct str_list_head ssid_filter,nlm_filter; 70 | #else 71 | bool droproot; 72 | uid_t uid; 73 | gid_t gid; 74 | #endif 75 | 76 | strpool *hostlist, *hostlist_exclude; 77 | struct str_list_head hostlist_files, hostlist_exclude_files; 78 | char hostlist_auto_filename[PATH_MAX], hostlist_auto_debuglog[PATH_MAX]; 79 | int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold; 80 | time_t hostlist_auto_mod_time; 81 | hostfail_pool *hostlist_auto_fail_counters; 82 | 83 | unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp; 84 | t_conntrack conntrack; 85 | }; 86 | 87 | extern struct params_s params; 88 | 89 | #define DLOG(format, ...) {if (params.debug) printf(format, ##__VA_ARGS__);} 90 | 91 | #define LOG_APPEND(filename, format, ...) \ 92 | { \ 93 | FILE *F = fopen(filename,"at"); \ 94 | if (F) \ 95 | { \ 96 | fprint_localtime(F); \ 97 | fprintf(F, " : " format "\n", ##__VA_ARGS__); \ 98 | fclose(F); \ 99 | } \ 100 | } 101 | #define HOSTLIST_DEBUGLOG_APPEND(format, ...) if (*params.hostlist_auto_debuglog) LOG_APPEND(params.hostlist_auto_debuglog, format, ##__VA_ARGS__) 102 | -------------------------------------------------------------------------------- /nfq/pools.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "pools.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #define DESTROY_STR_POOL(etype, ppool) \ 8 | etype *elem, *tmp; \ 9 | HASH_ITER(hh, *ppool, elem, tmp) { \ 10 | free(elem->str); \ 11 | HASH_DEL(*ppool, elem); \ 12 | free(elem); \ 13 | } 14 | 15 | #define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \ 16 | etype *elem; \ 17 | if (!(elem = (etype*)malloc(sizeof(etype)))) \ 18 | return false; \ 19 | if (!(elem->str = malloc(keystr_len + 1))) \ 20 | { \ 21 | free(elem); \ 22 | return false; \ 23 | } \ 24 | memcpy(elem->str, keystr, keystr_len); \ 25 | elem->str[keystr_len] = 0; \ 26 | oom = false; \ 27 | HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \ 28 | if (oom) \ 29 | { \ 30 | free(elem->str); \ 31 | free(elem); \ 32 | return false; \ 33 | } 34 | 35 | 36 | #undef uthash_nonfatal_oom 37 | #define uthash_nonfatal_oom(elt) ut_oom_recover(elt) 38 | static bool oom = false; 39 | static void ut_oom_recover(void *elem) 40 | { 41 | oom = true; 42 | } 43 | 44 | // for not zero terminated strings 45 | bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen) 46 | { 47 | ADD_STR_POOL(strpool, pp, s, slen) 48 | return true; 49 | } 50 | // for zero terminated strings 51 | bool StrPoolAddStr(strpool **pp, const char *s) 52 | { 53 | return StrPoolAddStrLen(pp, s, strlen(s)); 54 | } 55 | 56 | bool StrPoolCheckStr(strpool *p, const char *s) 57 | { 58 | strpool *elem; 59 | HASH_FIND_STR(p, s, elem); 60 | return elem != NULL; 61 | } 62 | 63 | void StrPoolDestroy(strpool **pp) 64 | { 65 | DESTROY_STR_POOL(strpool, pp) 66 | } 67 | 68 | 69 | 70 | void HostFailPoolDestroy(hostfail_pool **pp) 71 | { 72 | DESTROY_STR_POOL(hostfail_pool, pp) 73 | } 74 | hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time) 75 | { 76 | size_t slen = strlen(s); 77 | ADD_STR_POOL(hostfail_pool, pp, s, slen) 78 | elem->expire = time(NULL) + fail_time; 79 | elem->counter = 0; 80 | return elem; 81 | } 82 | hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s) 83 | { 84 | hostfail_pool *elem; 85 | HASH_FIND_STR(p, s, elem); 86 | return elem; 87 | } 88 | void HostFailPoolDel(hostfail_pool **p, hostfail_pool *elem) 89 | { 90 | HASH_DEL(*p, elem); 91 | free(elem); 92 | } 93 | void HostFailPoolPurge(hostfail_pool **pp) 94 | { 95 | hostfail_pool *elem, *tmp; 96 | time_t now = time(NULL); 97 | HASH_ITER(hh, *pp, elem, tmp) 98 | { 99 | if (now >= elem->expire) 100 | { 101 | free(elem->str); 102 | HASH_DEL(*pp, elem); 103 | free(elem); 104 | } 105 | } 106 | } 107 | static time_t host_fail_purge_prev=0; 108 | void HostFailPoolPurgeRateLimited(hostfail_pool **pp) 109 | { 110 | time_t now = time(NULL); 111 | // do not purge too often to save resources 112 | if (host_fail_purge_prev != now) 113 | { 114 | HostFailPoolPurge(pp); 115 | host_fail_purge_prev = now; 116 | } 117 | } 118 | void HostFailPoolDump(hostfail_pool *p) 119 | { 120 | hostfail_pool *elem, *tmp; 121 | time_t now = time(NULL); 122 | HASH_ITER(hh, p, elem, tmp) 123 | printf("host=%s counter=%d time_left=%lld\n",elem->str,elem->counter,(long long int)elem->expire-now); 124 | } 125 | 126 | 127 | bool strlist_add(struct str_list_head *head, const char *filename) 128 | { 129 | struct str_list *entry = malloc(sizeof(struct str_list)); 130 | if (!entry) return false; 131 | entry->str = strdup(filename); 132 | if (!entry->str) 133 | { 134 | free(entry); 135 | return false; 136 | } 137 | LIST_INSERT_HEAD(head, entry, next); 138 | return true; 139 | } 140 | static void strlist_entry_destroy(struct str_list *entry) 141 | { 142 | if (entry->str) free(entry->str); 143 | free(entry); 144 | } 145 | void strlist_destroy(struct str_list_head *head) 146 | { 147 | struct str_list *entry; 148 | while ((entry = LIST_FIRST(head))) 149 | { 150 | LIST_REMOVE(entry, next); 151 | strlist_entry_destroy(entry); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /nfq/pools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //#define HASH_BLOOM 20 9 | #define HASH_NONFATAL_OOM 1 10 | #define HASH_FUNCTION HASH_BER 11 | #include "uthash.h" 12 | 13 | typedef struct strpool { 14 | char *str; /* key */ 15 | UT_hash_handle hh; /* makes this structure hashable */ 16 | } strpool; 17 | 18 | void StrPoolDestroy(strpool **pp); 19 | bool StrPoolAddStr(strpool **pp,const char *s); 20 | bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen); 21 | bool StrPoolCheckStr(strpool *p,const char *s); 22 | 23 | struct str_list { 24 | char *str; 25 | LIST_ENTRY(str_list) next; 26 | }; 27 | LIST_HEAD(str_list_head, str_list); 28 | 29 | 30 | typedef struct hostfail_pool { 31 | char *str; /* key */ 32 | int counter; /* value */ 33 | time_t expire; /* when to expire record (unixtime) */ 34 | UT_hash_handle hh; /* makes this structure hashable */ 35 | } hostfail_pool; 36 | 37 | void HostFailPoolDestroy(hostfail_pool **pp); 38 | hostfail_pool *HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time); 39 | hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s); 40 | void HostFailPoolDel(hostfail_pool **pp, hostfail_pool *elem); 41 | void HostFailPoolPurge(hostfail_pool **pp); 42 | void HostFailPoolPurgeRateLimited(hostfail_pool **pp); 43 | void HostFailPoolDump(hostfail_pool *p); 44 | 45 | bool strlist_add(struct str_list_head *head, const char *filename); 46 | void strlist_destroy(struct str_list_head *head); 47 | -------------------------------------------------------------------------------- /nfq/protocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "crypto/sha.h" 7 | #include "crypto/aes-gcm.h" 8 | #include "helpers.h" 9 | 10 | extern const char *http_methods[9]; 11 | const char *HttpMethod(const uint8_t *data, size_t len); 12 | bool IsHttp(const uint8_t *data, size_t len); 13 | bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs); 14 | bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs); 15 | // header must be passed like this : "\nHost:" 16 | bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf); 17 | bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host); 18 | bool IsHttpReply(const uint8_t *data, size_t len); 19 | const char *HttpFind2ndLevelDomain(const char *host); 20 | // must be pre-checked by IsHttpReply 21 | int HttpReplyCode(const uint8_t *data, size_t len); 22 | // must be pre-checked by IsHttpReply 23 | bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host); 24 | enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host, httpreqpos_pos }; 25 | size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz); 26 | 27 | uint16_t TLSRecordDataLen(const uint8_t *data); 28 | size_t TLSRecordLen(const uint8_t *data); 29 | bool IsTLSRecordFull(const uint8_t *data, size_t len); 30 | bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK); 31 | size_t TLSHandshakeLen(const uint8_t *data); 32 | bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len); 33 | bool IsTLSHandshakeFull(const uint8_t *data, size_t len); 34 | bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); 35 | bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); 36 | bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK); 37 | bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK); 38 | enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos }; 39 | size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type); 40 | 41 | bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len); 42 | bool IsDhtD1(const uint8_t *data, size_t len); 43 | 44 | #define QUIC_MAX_CID_LENGTH 20 45 | typedef struct quic_cid { 46 | uint8_t len; 47 | uint8_t cid[QUIC_MAX_CID_LENGTH]; 48 | } quic_cid_t; 49 | 50 | bool IsQUICInitial(const uint8_t *data, size_t len); 51 | bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, size_t *hello_len); 52 | bool QUICIsLongHeader(const uint8_t *data, size_t len); 53 | uint32_t QUICExtractVersion(const uint8_t *data, size_t len); 54 | uint8_t QUICDraftVersion(uint32_t version); 55 | bool QUICExtractDCID(const uint8_t *data, size_t len, quic_cid_t *cid); 56 | 57 | bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, size_t *clean_len); 58 | bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len); 59 | bool QUICExtractHostFromInitial(const uint8_t *data, size_t data_len, char *host, size_t len_host, bool *bDecryptOK, bool *bIsCryptoHello); 60 | -------------------------------------------------------------------------------- /nfq/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 | # define REG_SYSCALL regs.regs[8] 23 | # define ARCH_NR AUDIT_ARCH_AARCH64 24 | #elif defined(__amd64__) 25 | # define REG_SYSCALL REG_RAX 26 | # define ARCH_NR AUDIT_ARCH_X86_64 27 | #elif defined(__arm__) && (defined(__ARM_EABI__) || defined(__thumb__)) 28 | # define REG_SYSCALL regs.uregs[7] 29 | # if __BYTE_ORDER == __LITTLE_ENDIAN 30 | # define ARCH_NR AUDIT_ARCH_ARM 31 | # else 32 | # define ARCH_NR AUDIT_ARCH_ARMEB 33 | # endif 34 | #elif defined(__i386__) 35 | # define REG_SYSCALL REG_EAX 36 | # define ARCH_NR AUDIT_ARCH_I386 37 | #elif defined(__mips__) 38 | # define REG_SYSCALL regs[2] 39 | # if __BYTE_ORDER == __LITTLE_ENDIAN 40 | # define ARCH_NR AUDIT_ARCH_MIPSEL 41 | # else 42 | # define ARCH_NR AUDIT_ARCH_MIPS 43 | # endif 44 | #elif defined(__PPC__) 45 | # define REG_SYSCALL regs.gpr[0] 46 | # define ARCH_NR AUDIT_ARCH_PPC 47 | #else 48 | # warning "Platform does not support seccomp filter yet" 49 | # define REG_SYSCALL 0 50 | # define ARCH_NR 0 51 | #endif 52 | 53 | #endif 54 | 55 | #ifndef __CYGWIN__ 56 | bool sec_harden(void); 57 | bool can_drop_root(void); 58 | bool droproot(uid_t uid, gid_t gid); 59 | void print_id(void); 60 | #endif 61 | 62 | void daemonize(void); 63 | bool writepid(const char *filename); 64 | -------------------------------------------------------------------------------- /nfq/win.c: -------------------------------------------------------------------------------- 1 | #ifdef __CYGWIN__ 2 | 3 | #include 4 | 5 | #include "win.h" 6 | #include "nfqws.h" 7 | 8 | #define SERVICE_NAME "winws" 9 | 10 | static SERVICE_STATUS ServiceStatus; 11 | static SERVICE_STATUS_HANDLE hStatus = NULL; 12 | static int service_argc = 0; 13 | static char **service_argv = NULL; 14 | 15 | void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))); 16 | 17 | bool service_run(int argc, char *argv[]) 18 | { 19 | SERVICE_TABLE_ENTRY ServiceTable[] = { 20 | {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main}, 21 | {NULL, NULL} 22 | }; 23 | 24 | service_argc = argc; 25 | service_argv = argv; 26 | 27 | return StartServiceCtrlDispatcherA(ServiceTable); 28 | } 29 | 30 | static void service_set_status(DWORD state) 31 | { 32 | ServiceStatus.dwCurrentState = state; 33 | SetServiceStatus(hStatus, &ServiceStatus); 34 | } 35 | 36 | // Control handler function 37 | void service_controlhandler(DWORD request) 38 | { 39 | switch (request) 40 | { 41 | case SERVICE_CONTROL_STOP: 42 | case SERVICE_CONTROL_SHUTDOWN: 43 | bQuit = true; 44 | ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; 45 | break; 46 | } 47 | SetServiceStatus(hStatus, &ServiceStatus); 48 | } 49 | 50 | void service_main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) 51 | { 52 | ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 53 | ServiceStatus.dwCurrentState = SERVICE_RUNNING; 54 | ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 55 | ServiceStatus.dwWin32ExitCode = 0; 56 | ServiceStatus.dwServiceSpecificExitCode = 0; 57 | ServiceStatus.dwCheckPoint = 1; 58 | ServiceStatus.dwWaitHint = 0; 59 | 60 | hStatus = RegisterServiceCtrlHandlerA( 61 | SERVICE_NAME, 62 | (LPHANDLER_FUNCTION)service_controlhandler); 63 | if (hStatus == (SERVICE_STATUS_HANDLE)0) 64 | { 65 | // Registering Control Handler failed 66 | return; 67 | } 68 | 69 | SetServiceStatus(hStatus, &ServiceStatus); 70 | 71 | // Calling main with saved argc & argv 72 | ServiceStatus.dwWin32ExitCode = (DWORD)main(service_argc, service_argv); 73 | 74 | ServiceStatus.dwCurrentState = SERVICE_STOPPED; 75 | SetServiceStatus(hStatus, &ServiceStatus); 76 | return; 77 | } 78 | 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /nfq/win.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __CYGWIN__ 4 | 5 | #include 6 | 7 | bool service_run(); 8 | 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /nfq/windivert/libwindivert.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/nfq/windivert/libwindivert.a -------------------------------------------------------------------------------- /nfq/winicon.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/nfq/winicon.o -------------------------------------------------------------------------------- /nfq/winmanifest.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/nfq/winmanifest.o -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFBG/zapret/82bcd2830416adfdb46c759dfcfec6c8ed5d1762/tmp/.keep -------------------------------------------------------------------------------- /tpws/BSDmakefile: -------------------------------------------------------------------------------- 1 | CC ?= cc 2 | CFLAGS += -std=gnu99 -s -O3 -Wno-logical-op-parentheses 3 | LIBS = -lz -lpthread 4 | SRC_FILES = *.c 5 | 6 | all: tpws 7 | 8 | tpws: $(SRC_FILES) 9 | $(CC) $(CFLAGS) -Iepoll-shim/include -o $@ $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS) 10 | 11 | clean: 12 | rm -f tpws *.o 13 | -------------------------------------------------------------------------------- /tpws/Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | CFLAGS += -std=gnu99 -Wno-logical-op-parentheses -O3 3 | CFLAGS_BSD = -Wno-address-of-packed-member -Wno-switch 4 | LIBS = -lz -lpthread 5 | SRC_FILES = *.c 6 | 7 | all: tpws 8 | 9 | tpws: $(SRC_FILES) 10 | $(CC) -s $(CFLAGS) -o $@ $(SRC_FILES) $(LDFLAGS) $(LIBS) 11 | 12 | bsd: $(SRC_FILES) 13 | $(CC) -s $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -o tpws $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS) 14 | 15 | mac: $(SRC_FILES) 16 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsa -target arm64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS) 17 | $(CC) $(CFLAGS) $(CFLAGS_BSD) -Iepoll-shim/include -Imacos -o tpwsx -target x86_64-apple-macos10.8 $(SRC_FILES) epoll-shim/src/*.c $(LDFLAGS) $(LIBS) 18 | strip tpwsa tpwsx 19 | lipo -create -output tpws tpwsx tpwsa 20 | rm -f tpwsx tpwsa 21 | 22 | clean: 23 | rm -f tpws *.o 24 | -------------------------------------------------------------------------------- /tpws/epoll-shim/include/sys/epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef SHIM_SYS_EPOLL_H 2 | #define SHIM_SYS_EPOLL_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #if defined(__NetBSD__) 13 | #include 14 | #elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__APPLE__) 15 | #include 16 | #endif 17 | 18 | #define EPOLL_CLOEXEC O_CLOEXEC 19 | #define EPOLL_NONBLOCK O_NONBLOCK 20 | 21 | enum EPOLL_EVENTS { __EPOLL_DUMMY }; 22 | #define EPOLLIN 0x001 23 | #define EPOLLPRI 0x002 24 | #define EPOLLOUT 0x004 25 | #define EPOLLRDNORM 0x040 26 | #define EPOLLNVAL 0x020 27 | #define EPOLLRDBAND 0x080 28 | #define EPOLLWRNORM 0x100 29 | #define EPOLLWRBAND 0x200 30 | #define EPOLLMSG 0x400 31 | #define EPOLLERR 0x008 32 | #define EPOLLHUP 0x010 33 | #define EPOLLRDHUP 0x2000 34 | #define EPOLLEXCLUSIVE (1U<<28) 35 | #define EPOLLWAKEUP (1U<<29) 36 | #define EPOLLONESHOT (1U<<30) 37 | #define EPOLLET (1U<<31) 38 | 39 | #define EPOLL_CTL_ADD 1 40 | #define EPOLL_CTL_DEL 2 41 | #define EPOLL_CTL_MOD 3 42 | 43 | typedef union epoll_data { 44 | void *ptr; 45 | int fd; 46 | uint32_t u32; 47 | uint64_t u64; 48 | } epoll_data_t; 49 | 50 | struct epoll_event { 51 | uint32_t events; 52 | epoll_data_t data; 53 | } 54 | #ifdef __x86_64__ 55 | __attribute__ ((__packed__)) 56 | #endif 57 | ; 58 | 59 | 60 | int epoll_create(int); 61 | int epoll_create1(int); 62 | int epoll_ctl(int, int, int, struct epoll_event *); 63 | int epoll_wait(int, struct epoll_event *, int, int); 64 | int epoll_pwait(int, struct epoll_event *, int, int, const sigset_t *); 65 | 66 | 67 | #ifndef SHIM_SYS_SHIM_HELPERS 68 | #define SHIM_SYS_SHIM_HELPERS 69 | #include /* IWYU pragma: keep */ 70 | 71 | extern int epoll_shim_close(int); 72 | #define close epoll_shim_close 73 | #endif 74 | 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif /* sys/epoll.h */ 81 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/epoll_shim_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef EPOLL_SHIM_CTX_H_ 2 | #define EPOLL_SHIM_CTX_H_ 3 | 4 | #include "fix.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include "epollfd_ctx.h" 11 | #include "eventfd_ctx.h" 12 | #include "signalfd_ctx.h" 13 | #include "timerfd_ctx.h" 14 | 15 | struct fd_context_map_node_; 16 | typedef struct fd_context_map_node_ FDContextMapNode; 17 | 18 | typedef errno_t (*fd_context_read_fun)(FDContextMapNode *node, /**/ 19 | void *buf, size_t nbytes, size_t *bytes_transferred); 20 | typedef errno_t (*fd_context_write_fun)(FDContextMapNode *node, /**/ 21 | const void *buf, size_t nbytes, size_t *bytes_transferred); 22 | typedef errno_t (*fd_context_close_fun)(FDContextMapNode *node); 23 | 24 | typedef struct { 25 | fd_context_read_fun read_fun; 26 | fd_context_write_fun write_fun; 27 | fd_context_close_fun close_fun; 28 | } FDContextVTable; 29 | 30 | errno_t fd_context_default_read(FDContextMapNode *node, /**/ 31 | void *buf, size_t nbytes, size_t *bytes_transferred); 32 | errno_t fd_context_default_write(FDContextMapNode *node, /**/ 33 | void const *buf, size_t nbytes, size_t *bytes_transferred); 34 | 35 | struct fd_context_map_node_ { 36 | RB_ENTRY(fd_context_map_node_) entry; 37 | int fd; 38 | int flags; 39 | union { 40 | EpollFDCtx epollfd; 41 | EventFDCtx eventfd; 42 | TimerFDCtx timerfd; 43 | SignalFDCtx signalfd; 44 | } ctx; 45 | FDContextVTable const *vtable; 46 | }; 47 | 48 | errno_t fd_context_map_node_destroy(FDContextMapNode *node); 49 | 50 | /**/ 51 | 52 | typedef RB_HEAD(fd_context_map_, fd_context_map_node_) FDContextMap; 53 | 54 | typedef struct { 55 | FDContextMap fd_context_map; 56 | pthread_mutex_t mutex; 57 | } EpollShimCtx; 58 | 59 | extern EpollShimCtx epoll_shim_ctx; 60 | 61 | FDContextMapNode *epoll_shim_ctx_create_node(EpollShimCtx *epoll_shim_ctx, 62 | errno_t *ec); 63 | FDContextMapNode *epoll_shim_ctx_find_node(EpollShimCtx *epoll_shim_ctx, 64 | int fd); 65 | FDContextMapNode *epoll_shim_ctx_remove_node(EpollShimCtx *epoll_shim_ctx, 66 | int fd); 67 | void epoll_shim_ctx_remove_node_explicit(EpollShimCtx *epoll_shim_ctx, 68 | FDContextMapNode *node); 69 | 70 | /**/ 71 | 72 | int epoll_shim_close(int fd); 73 | ssize_t epoll_shim_read(int fd, void *buf, size_t nbytes); 74 | ssize_t epoll_shim_write(int fd, void const *buf, size_t nbytes); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/epollfd_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef EPOLLFD_CTX_H_ 2 | #define EPOLLFD_CTX_H_ 3 | 4 | #include "fix.h" 5 | 6 | #define SHIM_SYS_SHIM_HELPERS 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | struct registered_fds_node_; 20 | typedef struct registered_fds_node_ RegisteredFDsNode; 21 | 22 | typedef enum { 23 | EOF_STATE_READ_EOF = 0x01, 24 | EOF_STATE_WRITE_EOF = 0x02, 25 | } EOFState; 26 | 27 | typedef enum { 28 | NODE_TYPE_FIFO = 1, 29 | NODE_TYPE_SOCKET = 2, 30 | NODE_TYPE_KQUEUE = 3, 31 | NODE_TYPE_OTHER = 4, 32 | NODE_TYPE_POLL = 5, 33 | } NodeType; 34 | 35 | struct registered_fds_node_ { 36 | RB_ENTRY(registered_fds_node_) entry; 37 | TAILQ_ENTRY(registered_fds_node_) pollfd_list_entry; 38 | 39 | int fd; 40 | epoll_data_t data; 41 | 42 | bool is_registered; 43 | 44 | bool has_evfilt_read; 45 | bool has_evfilt_write; 46 | bool has_evfilt_except; 47 | 48 | bool got_evfilt_read; 49 | bool got_evfilt_write; 50 | bool got_evfilt_except; 51 | 52 | NodeType node_type; 53 | union { 54 | struct { 55 | bool readable; 56 | bool writable; 57 | } fifo; 58 | } node_data; 59 | int eof_state; 60 | bool pollpri_active; 61 | 62 | uint16_t events; 63 | uint32_t revents; 64 | 65 | bool is_edge_triggered; 66 | bool is_oneshot; 67 | 68 | bool is_on_pollfd_list; 69 | int self_pipe[2]; 70 | }; 71 | 72 | typedef TAILQ_HEAD(pollfds_list_, registered_fds_node_) PollFDList; 73 | typedef RB_HEAD(registered_fds_set_, registered_fds_node_) RegisteredFDsSet; 74 | 75 | typedef struct { 76 | int kq; // non owning 77 | pthread_mutex_t mutex; 78 | 79 | PollFDList poll_fds; 80 | size_t poll_fds_size; 81 | 82 | RegisteredFDsSet registered_fds; 83 | size_t registered_fds_size; 84 | 85 | struct kevent *kevs; 86 | size_t kevs_length; 87 | 88 | struct pollfd *pfds; 89 | size_t pfds_length; 90 | 91 | pthread_mutex_t nr_polling_threads_mutex; 92 | pthread_cond_t nr_polling_threads_cond; 93 | unsigned long nr_polling_threads; 94 | 95 | int self_pipe[2]; 96 | } EpollFDCtx; 97 | 98 | errno_t epollfd_ctx_init(EpollFDCtx *epollfd, int kq); 99 | errno_t epollfd_ctx_terminate(EpollFDCtx *epollfd); 100 | 101 | void epollfd_ctx_fill_pollfds(EpollFDCtx *epollfd, struct pollfd *pfds); 102 | 103 | errno_t epollfd_ctx_ctl(EpollFDCtx *epollfd, int op, int fd2, 104 | struct epoll_event *ev); 105 | errno_t epollfd_ctx_wait(EpollFDCtx *epollfd, struct epoll_event *ev, int cnt, 106 | int *actual_cnt); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/eventfd_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef EVENTFD_CTX_H_ 2 | #define EVENTFD_CTX_H_ 3 | 4 | #include "fix.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #define EVENTFD_CTX_FLAG_SEMAPHORE (1 << 0) 13 | 14 | typedef struct { 15 | int kq_; // non owning 16 | int flags_; 17 | pthread_mutex_t mutex_; 18 | 19 | bool is_signalled_; 20 | int self_pipe_[2]; // only used if EVFILT_USER is not available 21 | uint_least64_t counter_; 22 | } EventFDCtx; 23 | 24 | errno_t eventfd_ctx_init(EventFDCtx *eventfd, int kq, unsigned int counter, 25 | int flags); 26 | errno_t eventfd_ctx_terminate(EventFDCtx *eventfd); 27 | 28 | errno_t eventfd_ctx_write(EventFDCtx *eventfd, uint64_t value); 29 | errno_t eventfd_ctx_read(EventFDCtx *eventfd, uint64_t *value); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/fix.c: -------------------------------------------------------------------------------- 1 | #include "fix.h" 2 | 3 | #ifdef __APPLE__ 4 | 5 | #include 6 | 7 | int ppoll(struct pollfd *fds, nfds_t nfds,const struct timespec *tmo_p, const sigset_t *sigmask) 8 | { 9 | // macos does not implement ppoll 10 | // this is a hacky ppoll shim. only for tpws which does not require sigmask 11 | if (sigmask) 12 | { 13 | errno = EINVAL; 14 | return -1; 15 | } 16 | return poll(fds,nfds,tmo_p ? tmo_p->tv_sec*1000 + tmo_p->tv_nsec/1000000 : -1); 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/fix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef _ERRNO_T_DEFINED 4 | #define _ERRNO_T_DEFINED 5 | typedef int errno_t; 6 | #endif 7 | 8 | #ifdef __APPLE__ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | struct itimerspec { 15 | struct timespec it_interval; 16 | struct timespec it_value; 17 | }; 18 | int ppoll(struct pollfd *fds, nfds_t nfds,const struct timespec *tmo_p, const sigset_t *sigmask); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/signalfd_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNALFD_CTX_H_ 2 | #define SIGNALFD_CTX_H_ 3 | 4 | #include "fix.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | int kq; // non owning 12 | } SignalFDCtx; 13 | 14 | errno_t signalfd_ctx_init(SignalFDCtx *signalfd, int kq, const sigset_t *sigs); 15 | errno_t signalfd_ctx_terminate(SignalFDCtx *signalfd); 16 | 17 | errno_t signalfd_ctx_read(SignalFDCtx *signalfd, uint32_t *ident); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tpws/epoll-shim/src/timerfd_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMERFD_CTX_H_ 2 | #define TIMERFD_CTX_H_ 3 | 4 | #include "fix.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | typedef struct { 15 | int kq; // non owning 16 | int flags; 17 | pthread_mutex_t mutex; 18 | 19 | int clockid; 20 | /* 21 | * Next expiration time, absolute (clock given by clockid). 22 | * If it_interval is != 0, it is a periodic timer. 23 | * If it_value is == 0, the timer is disarmed. 24 | */ 25 | struct itimerspec current_itimerspec; 26 | uint64_t nr_expirations; 27 | } TimerFDCtx; 28 | 29 | errno_t timerfd_ctx_init(TimerFDCtx *timerfd, int kq, int clockid); 30 | errno_t timerfd_ctx_terminate(TimerFDCtx *timerfd); 31 | 32 | errno_t timerfd_ctx_settime(TimerFDCtx *timerfd, int flags, 33 | struct itimerspec const *new, struct itimerspec *old); 34 | errno_t timerfd_ctx_gettime(TimerFDCtx *timerfd, struct itimerspec *cur); 35 | 36 | errno_t timerfd_ctx_read(TimerFDCtx *timerfd, uint64_t *value); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /tpws/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 | if (*buf) 69 | { 70 | free(*buf); 71 | *buf = NULL; 72 | } 73 | return r; 74 | } 75 | 76 | bool is_gzip(FILE* F) 77 | { 78 | unsigned char magic[2]; 79 | bool b = !fseek(F, 0, SEEK_SET) && fread(magic, 1, 2, F) == 2 && magic[0] == 0x1F && magic[1] == 0x8B; 80 | fseek(F, 0, SEEK_SET); 81 | return b; 82 | } 83 | -------------------------------------------------------------------------------- /tpws/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 | -------------------------------------------------------------------------------- /tpws/helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | char *strncasestr(const char *s,const char *find, size_t slen); 12 | 13 | bool append_to_list_file(const char *filename, const char *s); 14 | 15 | void ntop46(const struct sockaddr *sa, char *str, size_t len); 16 | void ntop46_port(const struct sockaddr *sa, char *str, size_t len); 17 | void print_sockaddr(const struct sockaddr *sa); 18 | void print_addrinfo(const struct addrinfo *ai); 19 | bool check_local_ip(const struct sockaddr *saddr); 20 | 21 | bool saismapped(const struct sockaddr_in6 *sa); 22 | bool samappedcmp(const struct sockaddr_in *sa1,const struct sockaddr_in6 *sa2); 23 | bool sacmp(const struct sockaddr *sa1,const struct sockaddr *sa2); 24 | uint16_t saport(const struct sockaddr *sa); 25 | // true = was converted 26 | bool saconvmapped(struct sockaddr_storage *a); 27 | 28 | bool is_localnet(const struct sockaddr *a); 29 | bool is_linklocal(const struct sockaddr_in6* a); 30 | bool is_private6(const struct sockaddr_in6* a); 31 | 32 | bool set_keepalive(int fd); 33 | bool set_ttl(int fd, int ttl); 34 | bool set_hl(int fd, int hl); 35 | bool set_ttl_hl(int fd, int ttl); 36 | int get_so_error(int fd); 37 | 38 | // alignment-safe functions 39 | static inline uint16_t pntoh16(const uint8_t *p) { 40 | return ((uint16_t)p[0] << 8) | (uint16_t)p[1]; 41 | } 42 | static inline void phton16(uint8_t *p, uint16_t v) { 43 | p[0] = (uint8_t)(v>>8); 44 | p[1] = (uint8_t)v; 45 | } 46 | 47 | int fprint_localtime(FILE *F); 48 | 49 | time_t file_mod_time(const char *filename); 50 | 51 | typedef struct 52 | { 53 | uint16_t from,to; 54 | bool neg; 55 | } port_filter; 56 | bool pf_in_range(uint16_t port, const port_filter *pf); 57 | bool pf_parse(const char *s, port_filter *pf); 58 | -------------------------------------------------------------------------------- /tpws/hostlist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hostlist.h" 3 | #include "gzip.h" 4 | #include "params.h" 5 | #include "helpers.h" 6 | 7 | // inplace tolower() and add to pool 8 | static bool addpool(strpool **hostlist, char **s, const char *end) 9 | { 10 | char *p; 11 | 12 | // advance until eol lowering all chars 13 | for (p = *s; pstr)) return false; 105 | } 106 | return true; 107 | } 108 | 109 | bool NonEmptyHostlist(strpool **hostlist) 110 | { 111 | // add impossible hostname if the list is empty 112 | return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4); 113 | } 114 | 115 | 116 | bool SearchHostList(strpool *hostlist, const char *host) 117 | { 118 | if (hostlist) 119 | { 120 | const char *p = host; 121 | bool bInHostList; 122 | while (p) 123 | { 124 | bInHostList = StrPoolCheckStr(hostlist, p); 125 | if (params.debug) printf("Hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative"); 126 | if (bInHostList) return true; 127 | p = strchr(p, '.'); 128 | if (p) p++; 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | // return : true = apply fooling, false = do not apply 135 | static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const char *host, bool *excluded) 136 | { 137 | if (excluded) *excluded = false; 138 | if (hostlist_exclude) 139 | { 140 | if (params.debug) printf("Checking exclude hostlist\n"); 141 | if (SearchHostList(hostlist_exclude, host)) 142 | { 143 | if (excluded) *excluded = true; 144 | return false; 145 | } 146 | } 147 | if (hostlist) 148 | { 149 | if (params.debug) printf("Checking include hostlist\n"); 150 | return SearchHostList(hostlist, host); 151 | } 152 | return true; 153 | } 154 | 155 | // return : true = apply fooling, false = do not apply 156 | bool HostlistCheck(const char *host, bool *excluded) 157 | { 158 | if (*params.hostlist_auto_filename) 159 | { 160 | time_t t = file_mod_time(params.hostlist_auto_filename); 161 | if (t!=params.hostlist_auto_mod_time) 162 | { 163 | printf("Autohostlist was modified by another process. Reloading include hostslist.\n"); 164 | if (!LoadIncludeHostLists()) 165 | { 166 | // what will we do without hostlist ?? sure, gonna die 167 | exit(1); 168 | } 169 | params.hostlist_auto_mod_time = t; 170 | } 171 | } 172 | return HostlistCheck_(params.hostlist, params.hostlist_exclude, host, excluded); 173 | } 174 | 175 | bool LoadIncludeHostLists() 176 | { 177 | if (!LoadHostLists(¶ms.hostlist, ¶ms.hostlist_files)) 178 | return false; 179 | if (*params.hostlist_auto_filename) 180 | params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename); 181 | return true; 182 | } 183 | bool LoadExcludeHostLists() 184 | { 185 | return LoadHostLists(¶ms.hostlist_exclude, ¶ms.hostlist_exclude_files); 186 | } 187 | -------------------------------------------------------------------------------- /tpws/hostlist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "pools.h" 5 | 6 | bool AppendHostList(strpool **hostlist, char *filename); 7 | bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list); 8 | bool LoadIncludeHostLists(); 9 | bool LoadExcludeHostLists(); 10 | bool NonEmptyHostlist(strpool **hostlist); 11 | bool SearchHostList(strpool *hostlist, const char *host); 12 | // return : true = apply fooling, false = do not apply 13 | bool HostlistCheck(const char *host, bool *excluded); -------------------------------------------------------------------------------- /tpws/macos/net/pfvar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // taken from an older apple SDK 7 | // some fields are different from BSDs 8 | 9 | #define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook) 10 | 11 | enum { PF_INOUT, PF_IN, PF_OUT, PF_FWD }; 12 | 13 | struct pf_addr { 14 | union { 15 | struct in_addr v4; 16 | struct in6_addr v6; 17 | u_int8_t addr8[16]; 18 | u_int16_t addr16[8]; 19 | u_int32_t addr32[4]; 20 | } pfa; /* 128-bit address */ 21 | #define v4 pfa.v4 22 | #define v6 pfa.v6 23 | #define addr8 pfa.addr8 24 | #define addr16 pfa.addr16 25 | #define addr32 pfa.addr32 26 | }; 27 | 28 | union pf_state_xport { 29 | u_int16_t port; 30 | u_int16_t call_id; 31 | u_int32_t spi; 32 | }; 33 | 34 | struct pfioc_natlook { 35 | struct pf_addr saddr; 36 | struct pf_addr daddr; 37 | struct pf_addr rsaddr; 38 | struct pf_addr rdaddr; 39 | union pf_state_xport sxport; 40 | union pf_state_xport dxport; 41 | union pf_state_xport rsxport; 42 | union pf_state_xport rdxport; 43 | sa_family_t af; 44 | u_int8_t proto; 45 | u_int8_t proto_variant; 46 | u_int8_t direction; 47 | }; 48 | -------------------------------------------------------------------------------- /tpws/params.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "tpws.h" 10 | #include "pools.h" 11 | #include "helpers.h" 12 | #include "protocol.h" 13 | 14 | #define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3 15 | #define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60 16 | 17 | enum bindll { unwanted=0, no, prefer, force }; 18 | 19 | #define MAX_BINDS 32 20 | struct bind_s 21 | { 22 | char bindaddr[64],bindiface[IF_NAMESIZE]; 23 | bool bind_if6; 24 | enum bindll bindll; 25 | int bind_wait_ifup,bind_wait_ip,bind_wait_ip_ll; 26 | }; 27 | 28 | struct params_s 29 | { 30 | struct bind_s binds[MAX_BINDS]; 31 | int binds_last; 32 | bool bind_wait_only; 33 | uint16_t port; 34 | 35 | uint8_t proxy_type; 36 | bool no_resolve; 37 | bool skip_nodelay; 38 | bool droproot; 39 | uid_t uid; 40 | gid_t gid; 41 | bool daemon; 42 | int maxconn,resolver_threads,maxfiles,max_orphan_time; 43 | int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf; 44 | 45 | bool tamper; // any tamper option is set 46 | bool hostcase, hostdot, hosttab, hostnospace, methodspace, methodeol, unixeol, domcase; 47 | int hostpad; 48 | char hostspell[4]; 49 | enum httpreqpos split_http_req; 50 | enum tlspos tlsrec; 51 | int tlsrec_pos; 52 | enum tlspos split_tls; 53 | bool split_any_protocol; 54 | int split_pos; 55 | bool disorder, disorder_http, disorder_tls; 56 | bool oob, oob_http, oob_tls; 57 | uint8_t oob_byte; 58 | int ttl_default; 59 | 60 | int mss; 61 | port_filter mss_pf; 62 | 63 | char pidfile[256]; 64 | 65 | strpool *hostlist, *hostlist_exclude; 66 | struct str_list_head hostlist_files, hostlist_exclude_files; 67 | char hostlist_auto_filename[PATH_MAX], hostlist_auto_debuglog[PATH_MAX]; 68 | int hostlist_auto_fail_threshold, hostlist_auto_fail_time; 69 | time_t hostlist_auto_mod_time; 70 | hostfail_pool *hostlist_auto_fail_counters; 71 | 72 | bool tamper_start_n,tamper_cutoff_n; 73 | unsigned int tamper_start,tamper_cutoff; 74 | 75 | int debug; 76 | 77 | #if defined(BSD) 78 | bool pf_enable; 79 | #endif 80 | #ifdef SPLICE_PRESENT 81 | bool nosplice; 82 | #endif 83 | }; 84 | 85 | extern struct params_s params; 86 | 87 | #define _DBGPRINT(format, level, ...) { if (params.debug>=level) printf(format "\n", ##__VA_ARGS__); } 88 | #define VPRINT(format, ...) _DBGPRINT(format,1,##__VA_ARGS__) 89 | #define DBGPRINT(format, ...) _DBGPRINT(format,2,##__VA_ARGS__) 90 | 91 | #define LOG_APPEND(filename, format, ...) \ 92 | { \ 93 | FILE *F = fopen(filename,"at"); \ 94 | if (F) \ 95 | { \ 96 | fprint_localtime(F); \ 97 | fprintf(F, " : " format "\n", ##__VA_ARGS__); \ 98 | fclose(F); \ 99 | } \ 100 | } 101 | #define HOSTLIST_DEBUGLOG_APPEND(format, ...) if (*params.hostlist_auto_debuglog) LOG_APPEND(params.hostlist_auto_debuglog, format, ##__VA_ARGS__) 102 | -------------------------------------------------------------------------------- /tpws/pools.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "pools.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #define DESTROY_STR_POOL(etype, ppool) \ 8 | etype *elem, *tmp; \ 9 | HASH_ITER(hh, *ppool, elem, tmp) { \ 10 | free(elem->str); \ 11 | HASH_DEL(*ppool, elem); \ 12 | free(elem); \ 13 | } 14 | 15 | #define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \ 16 | etype *elem; \ 17 | if (!(elem = (etype*)malloc(sizeof(etype)))) \ 18 | return false; \ 19 | if (!(elem->str = malloc(keystr_len + 1))) \ 20 | { \ 21 | free(elem); \ 22 | return false; \ 23 | } \ 24 | memcpy(elem->str, keystr, keystr_len); \ 25 | elem->str[keystr_len] = 0; \ 26 | oom = false; \ 27 | HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \ 28 | if (oom) \ 29 | { \ 30 | free(elem->str); \ 31 | free(elem); \ 32 | return false; \ 33 | } 34 | 35 | 36 | #undef uthash_nonfatal_oom 37 | #define uthash_nonfatal_oom(elt) ut_oom_recover(elt) 38 | static bool oom = false; 39 | static void ut_oom_recover(void *elem) 40 | { 41 | oom = true; 42 | } 43 | 44 | // for not zero terminated strings 45 | bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen) 46 | { 47 | ADD_STR_POOL(strpool, pp, s, slen) 48 | return true; 49 | } 50 | // for zero terminated strings 51 | bool StrPoolAddStr(strpool **pp, const char *s) 52 | { 53 | return StrPoolAddStrLen(pp, s, strlen(s)); 54 | } 55 | 56 | bool StrPoolCheckStr(strpool *p, const char *s) 57 | { 58 | strpool *elem; 59 | HASH_FIND_STR(p, s, elem); 60 | return elem != NULL; 61 | } 62 | 63 | void StrPoolDestroy(strpool **pp) 64 | { 65 | DESTROY_STR_POOL(strpool, pp) 66 | } 67 | 68 | 69 | 70 | void HostFailPoolDestroy(hostfail_pool **pp) 71 | { 72 | DESTROY_STR_POOL(hostfail_pool, pp) 73 | } 74 | hostfail_pool * HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time) 75 | { 76 | size_t slen = strlen(s); 77 | ADD_STR_POOL(hostfail_pool, pp, s, slen) 78 | elem->expire = time(NULL) + fail_time; 79 | elem->counter = 0; 80 | return elem; 81 | } 82 | hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s) 83 | { 84 | hostfail_pool *elem; 85 | HASH_FIND_STR(p, s, elem); 86 | return elem; 87 | } 88 | void HostFailPoolDel(hostfail_pool **p, hostfail_pool *elem) 89 | { 90 | HASH_DEL(*p, elem); 91 | free(elem); 92 | } 93 | void HostFailPoolPurge(hostfail_pool **pp) 94 | { 95 | hostfail_pool *elem, *tmp; 96 | time_t now = time(NULL); 97 | HASH_ITER(hh, *pp, elem, tmp) 98 | { 99 | if (now >= elem->expire) 100 | { 101 | free(elem->str); 102 | HASH_DEL(*pp, elem); 103 | free(elem); 104 | } 105 | } 106 | } 107 | static time_t host_fail_purge_prev=0; 108 | void HostFailPoolPurgeRateLimited(hostfail_pool **pp) 109 | { 110 | time_t now = time(NULL); 111 | // do not purge too often to save resources 112 | if (host_fail_purge_prev != now) 113 | { 114 | HostFailPoolPurge(pp); 115 | host_fail_purge_prev = now; 116 | } 117 | } 118 | void HostFailPoolDump(hostfail_pool *p) 119 | { 120 | hostfail_pool *elem, *tmp; 121 | time_t now = time(NULL); 122 | HASH_ITER(hh, p, elem, tmp) 123 | printf("host=%s counter=%d time_left=%lld\n",elem->str,elem->counter,(long long int)elem->expire-now); 124 | } 125 | 126 | 127 | bool strlist_add(struct str_list_head *head, const char *filename) 128 | { 129 | struct str_list *entry = malloc(sizeof(struct str_list)); 130 | if (!entry) return false; 131 | entry->str = strdup(filename); 132 | if (!entry->str) 133 | { 134 | free(entry); 135 | return false; 136 | } 137 | LIST_INSERT_HEAD(head, entry, next); 138 | return true; 139 | } 140 | static void strlist_entry_destroy(struct str_list *entry) 141 | { 142 | if (entry->str) free(entry->str); 143 | free(entry); 144 | } 145 | void strlist_destroy(struct str_list_head *head) 146 | { 147 | struct str_list *entry; 148 | while ((entry = LIST_FIRST(head))) 149 | { 150 | LIST_REMOVE(entry, next); 151 | strlist_entry_destroy(entry); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /tpws/pools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | //#define HASH_BLOOM 20 9 | #define HASH_NONFATAL_OOM 1 10 | #define HASH_FUNCTION HASH_BER 11 | #include "uthash.h" 12 | 13 | typedef struct strpool { 14 | char *str; /* key */ 15 | UT_hash_handle hh; /* makes this structure hashable */ 16 | } strpool; 17 | 18 | void StrPoolDestroy(strpool **pp); 19 | bool StrPoolAddStr(strpool **pp,const char *s); 20 | bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen); 21 | bool StrPoolCheckStr(strpool *p,const char *s); 22 | 23 | struct str_list { 24 | char *str; 25 | LIST_ENTRY(str_list) next; 26 | }; 27 | LIST_HEAD(str_list_head, str_list); 28 | 29 | 30 | typedef struct hostfail_pool { 31 | char *str; /* key */ 32 | int counter; /* value */ 33 | time_t expire; /* when to expire record (unixtime) */ 34 | UT_hash_handle hh; /* makes this structure hashable */ 35 | } hostfail_pool; 36 | 37 | void HostFailPoolDestroy(hostfail_pool **pp); 38 | hostfail_pool *HostFailPoolAdd(hostfail_pool **pp,const char *s,int fail_time); 39 | hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s); 40 | void HostFailPoolDel(hostfail_pool **pp, hostfail_pool *elem); 41 | void HostFailPoolPurge(hostfail_pool **pp); 42 | void HostFailPoolPurgeRateLimited(hostfail_pool **pp); 43 | void HostFailPoolDump(hostfail_pool *p); 44 | 45 | bool strlist_add(struct str_list_head *head, const char *filename); 46 | void strlist_destroy(struct str_list_head *head); 47 | -------------------------------------------------------------------------------- /tpws/protocol.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | extern const char *http_methods[9]; 8 | const char *HttpMethod(const uint8_t *data, size_t len); 9 | bool IsHttp(const uint8_t *data, size_t len); 10 | bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs); 11 | bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs); 12 | // header must be passed like this : "\nHost:" 13 | bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf); 14 | bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host); 15 | bool IsHttpReply(const uint8_t *data, size_t len); 16 | const char *HttpFind2ndLevelDomain(const char *host); 17 | // must be pre-checked by IsHttpReply 18 | int HttpReplyCode(const uint8_t *data, size_t len); 19 | // must be pre-checked by IsHttpReply 20 | bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host); 21 | enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host, httpreqpos_pos }; 22 | size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz); 23 | 24 | uint16_t TLSRecordDataLen(const uint8_t *data); 25 | size_t TLSRecordLen(const uint8_t *data); 26 | bool IsTLSRecordFull(const uint8_t *data, size_t len); 27 | bool IsTLSClientHello(const uint8_t *data, size_t len, bool bPartialIsOK); 28 | bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); 29 | bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK); 30 | bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK); 31 | bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK); 32 | enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos }; 33 | size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type); 34 | -------------------------------------------------------------------------------- /tpws/redirect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | bool get_dest_addr(int sockfd, const struct sockaddr *accept_sa, struct sockaddr_storage *orig_dst); 8 | bool redir_init(void); 9 | void redir_close(void); 10 | -------------------------------------------------------------------------------- /tpws/resolver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct resolve_item 10 | { 11 | char dom[256]; // request dom 12 | struct sockaddr_storage ss; // resolve result 13 | int ga_res; // getaddrinfo result code 14 | uint16_t port; // request port 15 | void *ptr; 16 | TAILQ_ENTRY(resolve_item) next; 17 | }; 18 | 19 | struct resolve_item *resolver_queue(const char *dom, uint16_t port, void *ptr); 20 | void resolver_deinit(void); 21 | bool resolver_init(int threads, int fd_signal_pipe); 22 | int resolver_thread_count(void); 23 | -------------------------------------------------------------------------------- /tpws/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 | # define REG_SYSCALL regs.regs[8] 23 | # define ARCH_NR AUDIT_ARCH_AARCH64 24 | #elif defined(__amd64__) 25 | # define REG_SYSCALL REG_RAX 26 | # define ARCH_NR AUDIT_ARCH_X86_64 27 | #elif defined(__arm__) && (defined(__ARM_EABI__) || defined(__thumb__)) 28 | # define REG_SYSCALL regs.uregs[7] 29 | # if __BYTE_ORDER == __LITTLE_ENDIAN 30 | # define ARCH_NR AUDIT_ARCH_ARM 31 | # else 32 | # define ARCH_NR AUDIT_ARCH_ARMEB 33 | # endif 34 | #elif defined(__i386__) 35 | # define REG_SYSCALL REG_EAX 36 | # define ARCH_NR AUDIT_ARCH_I386 37 | #elif defined(__mips__) 38 | # define REG_SYSCALL regs[2] 39 | # if __BYTE_ORDER == __LITTLE_ENDIAN 40 | # define ARCH_NR AUDIT_ARCH_MIPSEL 41 | # else 42 | # define ARCH_NR AUDIT_ARCH_MIPS 43 | # endif 44 | #elif defined(__PPC__) 45 | # define REG_SYSCALL regs.gpr[0] 46 | # define ARCH_NR AUDIT_ARCH_PPC 47 | #else 48 | # warning "Platform does not support seccomp filter yet" 49 | # define REG_SYSCALL 0 50 | # define ARCH_NR 0 51 | #endif 52 | 53 | #endif 54 | 55 | bool sec_harden(void); 56 | bool can_drop_root(); 57 | bool droproot(uid_t uid, gid_t gid); 58 | void print_id(void); 59 | void daemonize(void); 60 | bool writepid(const char *filename); 61 | -------------------------------------------------------------------------------- /tpws/socks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #pragma pack(push,1) 7 | 8 | #define S4_CMD_CONNECT 1 9 | #define S4_CMD_BIND 2 10 | typedef struct 11 | { 12 | uint8_t ver,cmd; 13 | uint16_t port; 14 | uint32_t ip; 15 | } s4_req; 16 | #define S4_REQ_HEADER_VALID(r,l) (l>=sizeof(s4_req) && r->ver==4) 17 | #define S4_REQ_CONNECT_VALID(r,l) (S4_REQ_HEADER_VALID(r,l) && r->cmd==S4_CMD_CONNECT) 18 | 19 | #define S4_REP_OK 90 20 | #define S4_REP_FAILED 91 21 | typedef struct 22 | { 23 | uint8_t zero,rep; 24 | uint16_t port; 25 | uint32_t ip; 26 | } s4_rep; 27 | 28 | 29 | 30 | #define S5_AUTH_NONE 0 31 | #define S5_AUTH_GSSAPI 1 32 | #define S5_AUTH_USERPASS 2 33 | #define S5_AUTH_UNACCEPTABLE 0xFF 34 | typedef struct 35 | { 36 | uint8_t ver,nmethods,methods[255]; 37 | } s5_handshake; 38 | #define S5_REQ_HANDHSHAKE_VALID(r,l) (l>=3 && r->ver==5 && r->nmethods && l>=(2+r->nmethods)) 39 | typedef struct 40 | { 41 | uint8_t ver,method; 42 | } s5_handshake_ack; 43 | 44 | #define S5_CMD_CONNECT 1 45 | #define S5_CMD_BIND 2 46 | #define S5_CMD_UDP_ASSOC 3 47 | #define S5_ATYP_IP4 1 48 | #define S5_ATYP_DOM 3 49 | #define S5_ATYP_IP6 4 50 | typedef struct 51 | { 52 | uint8_t ver,cmd,rsv,atyp; 53 | union { 54 | struct { 55 | struct in_addr addr; 56 | uint16_t port; 57 | } d4; 58 | struct { 59 | struct in6_addr addr; 60 | uint16_t port; 61 | } d6; 62 | struct { 63 | uint8_t len; 64 | char domport[255+2]; // max hostname + binary port 65 | } dd; 66 | }; 67 | } s5_req; 68 | #define S5_REQ_HEADER_VALID(r,l) (l>=4 && r->ver==5) 69 | #define S5_IP46_VALID(r,l) (r->atyp==S5_ATYP_IP4 && l>=(4+sizeof(r->d4)) || r->atyp==S5_ATYP_IP6 && l>=(4+sizeof(r->d6))) 70 | #define S5_REQ_CONNECT_VALID(r,l) (S5_REQ_HEADER_VALID(r,l) && r->cmd==S5_CMD_CONNECT && (S5_IP46_VALID(r,l) || r->atyp==S5_ATYP_DOM && l>=5 && l>=(5+r->dd.len))) 71 | #define S5_PORT_FROM_DD(r,l) (l>=(4+r->dd.len+2) ? ntohs(*(uint16_t*)(r->dd.domport+r->dd.len)) : 0) 72 | 73 | #define S5_REP_OK 0 74 | #define S5_REP_GENERAL_FAILURE 1 75 | #define S5_REP_NOT_ALLOWED_BY_RULESET 2 76 | #define S5_REP_NETWORK_UNREACHABLE 3 77 | #define S5_REP_HOST_UNREACHABLE 4 78 | #define S5_REP_CONN_REFUSED 5 79 | #define S5_REP_TTL_EXPIRED 6 80 | #define S5_REP_COMMAND_NOT_SUPPORTED 7 81 | #define S5_REP_ADDR_TYPE_NOT_SUPPORTED 8 82 | typedef struct 83 | { 84 | uint8_t ver,rep,rsv,atyp; 85 | union { 86 | struct { 87 | struct in_addr addr; 88 | uint16_t port; 89 | } d4; 90 | }; 91 | } s5_rep; 92 | 93 | #pragma pack(pop) 94 | -------------------------------------------------------------------------------- /tpws/tamper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define SPLIT_FLAG_DISORDER 0x01 8 | #define SPLIT_FLAG_OOB 0x02 9 | 10 | typedef enum {UNKNOWN=0, HTTP, TLS} t_l7proto; 11 | typedef struct 12 | { 13 | // common state 14 | t_l7proto l7proto; 15 | bool bFirstReplyChecked; 16 | bool bTamperInCutoff; 17 | char *hostname; 18 | } t_ctrack; 19 | 20 | void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags); 21 | void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size); 22 | // connection reset by remote leg 23 | void rst_in(t_ctrack *ctrack); 24 | // local leg closed connection (timeout waiting response ?) 25 | void hup_out(t_ctrack *ctrack); 26 | -------------------------------------------------------------------------------- /tpws/tpws.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __linux__ 4 | #define SPLICE_PRESENT 5 | #endif 6 | 7 | #include 8 | 9 | void dohup(void); 10 | -------------------------------------------------------------------------------- /tpws/tpws_conn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "tamper.h" 8 | #include "params.h" 9 | #include "resolver.h" 10 | 11 | #define BACKLOG 10 12 | #define MAX_EPOLL_EVENTS 64 13 | #define IP_TRANSPARENT 19 //So that application compiles on OpenWRT 14 | #define SPLICE_LEN 65536 15 | #define DEFAULT_MAX_CONN 512 16 | #define DEFAULT_MAX_ORPHAN_TIME 5 17 | 18 | int event_loop(const int *listen_fd, size_t listen_fd_ct); 19 | 20 | //Three different states of a connection 21 | enum{ 22 | CONN_UNAVAILABLE=0, // connecting 23 | CONN_AVAILABLE, // operational 24 | CONN_RDHUP, // received RDHUP, only sending unsent buffers. more RDHUPs are blocked 25 | CONN_CLOSED // will be deleted soon 26 | }; 27 | typedef uint8_t conn_state_t; 28 | 29 | // data in a send_buffer can be sent in several stages 30 | // pos indicates size of already sent data 31 | // when pos==len its time to free buffer 32 | struct send_buffer 33 | { 34 | uint8_t *data; 35 | size_t len,pos; 36 | int ttl, flags; 37 | }; 38 | typedef struct send_buffer send_buffer_t; 39 | 40 | enum{ 41 | CONN_TYPE_TRANSPARENT=0, 42 | CONN_TYPE_SOCKS 43 | }; 44 | typedef uint8_t conn_type_t; 45 | 46 | struct tproxy_conn 47 | { 48 | bool listener; // true - listening socket. false = connecion socket 49 | bool remote; // false - accepted, true - connected 50 | int efd; // epoll fd 51 | int fd; 52 | int splice_pipe[2]; 53 | conn_state_t state; 54 | conn_type_t conn_type; 55 | 56 | struct tproxy_conn *partner; // other leg 57 | time_t orphan_since; 58 | 59 | // socks5 state machine 60 | enum { 61 | S_WAIT_HANDSHAKE=0, 62 | S_WAIT_REQUEST, 63 | S_WAIT_RESOLVE, 64 | S_WAIT_CONNECTION, 65 | S_TCP 66 | } socks_state; 67 | uint8_t socks_ver; 68 | struct resolve_item *socks_ri; 69 | 70 | // these value are used in flow control. we do not use ET (edge triggered) polling 71 | // if we dont disable notifications they will come endlessly until condition becomes false and will eat all cpu time 72 | bool bFlowIn,bFlowOut, bFlowInPrev,bFlowOutPrev, bPrevRdhup; 73 | 74 | // total read,write 75 | uint64_t trd,twr, tnrd; 76 | // number of epoll_wait events 77 | unsigned int event_count; 78 | 79 | // connection is either spliced or send/recv 80 | // spliced connection have pipe buffering but also can have send_buffer's 81 | // pipe buffer comes first, then send_buffer's from 0 to countof(wr_buf)-1 82 | // send/recv connection do not have pipe and wr_unsent is meaningless, always 0 83 | ssize_t wr_unsent; // unsent bytes in the pipe 84 | // buffer 0 : send before split_pos 85 | // buffer 1 : send after split_pos 86 | // buffer 2 : after RDHUP read all and buffer to the partner 87 | // buffer 3 : after HUP read all and buffer to the partner 88 | // (2 and 3 should not be filled simultaneously, but who knows what can happen. if we have to refill non-empty buffer its FATAL) 89 | // all buffers are sent strictly from 0 to countof(wr_buf)-1 90 | // buffer cannot be sent if there is unsent data in a lower buffer 91 | struct send_buffer wr_buf[4]; 92 | 93 | t_ctrack track; 94 | 95 | //Create the struct which contains ptrs to next/prev element 96 | TAILQ_ENTRY(tproxy_conn) conn_ptrs; 97 | }; 98 | typedef struct tproxy_conn tproxy_conn_t; 99 | 100 | //Define the struct tailhead (code in sys/queue.h is quite intuitive) 101 | //Use tail queue for efficient delete 102 | TAILQ_HEAD(tailhead, tproxy_conn); 103 | 104 | 105 | bool set_socket_buffers(int fd, int rcvbuf, int sndbuf); 106 | -------------------------------------------------------------------------------- /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 | IPSET_DIR="$EXEDIR/ipset" 8 | ZAPRET_CONFIG="$EXEDIR/config" 9 | ZAPRET_BASE="$EXEDIR" 10 | 11 | [ -f "$ZAPRET_CONFIG" ] || cp "${ZAPRET_CONFIG}.default" "$ZAPRET_CONFIG" 12 | . "$ZAPRET_CONFIG" 13 | . "$ZAPRET_BASE/common/base.sh" 14 | . "$ZAPRET_BASE/common/elevate.sh" 15 | . "$ZAPRET_BASE/common/fwtype.sh" 16 | . "$ZAPRET_BASE/common/dialog.sh" 17 | . "$ZAPRET_BASE/common/ipt.sh" 18 | . "$ZAPRET_BASE/common/nft.sh" 19 | . "$ZAPRET_BASE/common/pf.sh" 20 | . "$ZAPRET_BASE/common/installer.sh" 21 | 22 | remove_systemd() 23 | { 24 | clear_ipset 25 | service_stop_systemd 26 | service_remove_systemd 27 | timer_remove_systemd 28 | nft_del_table 29 | crontab_del 30 | } 31 | 32 | remove_openrc() 33 | { 34 | clear_ipset 35 | service_remove_openrc 36 | nft_del_table 37 | crontab_del 38 | } 39 | 40 | remove_linux() 41 | { 42 | INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret" 43 | 44 | clear_ipset 45 | 46 | echo \* executing sysv init stop 47 | "$INIT_SCRIPT_SRC" stop 48 | 49 | nft_del_table 50 | crontab_del 51 | 52 | echo 53 | echo '!!! WARNING. YOUR UNINSTALL IS INCOMPLETE !!!' 54 | echo 'you must manually remove zapret auto start from your system' 55 | } 56 | 57 | remove_openwrt() 58 | { 59 | OPENWRT_FW_INCLUDE=/etc/firewall.zapret 60 | 61 | clear_ipset 62 | service_remove_sysv 63 | remove_openwrt_firewall 64 | remove_openwrt_iface_hook 65 | nft_del_table 66 | restart_openwrt_firewall 67 | crontab_del 68 | } 69 | 70 | remove_macos() 71 | { 72 | remove_macos_firewall 73 | service_remove_macos 74 | crontab_del 75 | } 76 | 77 | 78 | fix_sbin_path 79 | check_system 80 | require_root 81 | 82 | [ "$SYSTEM" = "macos" ] && . "$EXEDIR/init.d/macos/functions" 83 | 84 | case $SYSTEM in 85 | systemd) 86 | remove_systemd 87 | ;; 88 | openrc) 89 | remove_openrc 90 | ;; 91 | linux) 92 | remove_linux 93 | ;; 94 | openwrt) 95 | remove_openwrt 96 | ;; 97 | macos) 98 | remove_macos 99 | ;; 100 | esac 101 | 102 | 103 | exitp 0 104 | --------------------------------------------------------------------------------