What's new

Реализованы режимы десинхронизации fakeknown и udplen
fakeknown - это то же самое, что fake, только применяется исключительно к распознанным протоколам, даже если выставлено --dpi-desync-any-protocol. При этом вторая фаза десинхронизации применяется как раньше.
udplen - режим, относящийся только к udp. Пакет увеличивается в размере, дополняясь нулями, на указанное в --dpi-desync-udplen-increment количество байт. По умолчанию - 2. Нацелено на обман DPI, ориентирующихся на размеры пакетов. Может сработать при условии, что протокол приложения не завязан жестко на размер udp payload и не обижается на изменение размера.
К сожалению, обмануть таким образом статистическое застревание QUIC на ТСПУ не удается

Сделал инструкцию для быстрого старта

nfqws теперь учитывает fwmark пакетов, попадающих к нему на обработку
если в результате обработки пакета nfqws генерит свой пакет, его fwmark будет не 0x40000000, а 0x40000000 | <original_fwmark>

добавлен алгоритм лечения проблемы неверного выбора исходящего интерфейса для сгенерированных пакетов
параметры --bind-fix4 и --bind-fix6
лечение идет через вызов bind() на raw socket и setsockopt SO_BINDTODEVICE
интерфейс назначения берется из NFQUEUE. куда оригинальный пакет уходил, туда и отправляем сгенеренные. это возможно как для OUTPUT, так и POSTROUTING
linux не был бы linux-ом, если бы это не работало по разному для ipv4 и ipv6

в случае отсутствия опции bind-fix для соответствующего семейства ip отправка идет так, как было раньше. то есть система решает сама
Проблема неверного выбора интерфейса может случиться, когда у вас несколько аплинков или присутствует policy routing на базе source ip.
Причина - особенности маршрутизации пакетов , отправленных через raw sockets.
Для сценария стандартного роутера LAN-WAN это не актуально

Удалось забороть хаотические зависания QUIC на ТСПУ при пробивке udp фейком.
Всего лишь вместо нулей надо слать достаточно длинный пакет с quic short header вместо нулей.

nfqws --qnum=210 --user=daemon --dpi-desync-fwmark=0x40000000 --dpi-desync=fake --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_short_header.bin
iptables -t mangle -I POSTROUTING -p udp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:3 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 210 --queue-bypass

Если использовать скрипты, то вариант custom с файлом custom-nfqws-quic4all
и параметром config

NFQWS_OPT_DESYNC_QUIC=“–dpi-desync=fake --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_short_header.bin”

Шифрованное содержимое особого значения не имеет, потому что DPI все равно не способен его расшифровать. Важен лишь первый байт, а точнее 2 его старших бита, и общая длина пакета.

Обновил инструкции по настройке policy routing openwrt → vps на базе wireguard .
Добавлены правила nftables и способ их прикрутки для новых версий openwrt.
Учтен новый статус wireguard. Он был включен в ядро linux 5.6.
Так же обновлен вариант для redsocks.

Информация для любителей кинетиков на стоковой прошивке, где есть entware.

NDMS имеет проприетарное ядро, где в параллель со стандартными средствами маркировки mark и ct mark имеется в skbuff еще 1 марк - проприетарный ndmmark.
Он был сделан, чтобы управлять логикой iptables, оставляя основной марк полностью свободным для юзера.

В частности, ndmmark используется для ограничения маскарада. Только пакеты с определенным ndmmark идут на маскарад. См iptables-save -t nat

Если вы пытаетесь обойти блокировку quic через nfqws, то nfqws в этом случае дропает первый UDP пакет с quic initial, затем отправляет фейк своими средствами, ничего не зная о ndmmark. Первый пакет создает запись в conntrack, и она будет без маскарада.
Все дальнейшие пакеты будут уходить на внешний интерфейс с source ip 192.168.x.x и дропаться провайдером.

Таким образом, вы заставляете nfqws работать не на обход, а на блокировку QUIC.
И это даже иногда делает экспиренс лучше, если вдруг у провайдера DPI плохо блокирует QUIC, позволяя сеансу пройти дальше initial, а затем обрывая поток.
Того же эффекта вы можете достичь просто блокируя порт udp:443 на выход. Для этого nfqws не нужен.

Для лечения посмотрите как устроены ваши цепочки и добавьте в нужную цепочку маскарад на исходящий интерфейс WAN. Это может быть , например, ppp0, если у вас pppoe.

Если используются скрипты от zapret в варианте sysv, то можно добавить лечение в custom.
Как-то так, но смотрите какие у вас реально цепочки (я за версии прошивок не ручаюсь), и какой внешний интерфейс.
Пример лечащей добавки в скрипт custom-nfqws-quic4all

zapret_custom_firewall()
{
        # $1 - 1 - run, 0 - stop

        local MODE_OVERRIDE=nfqws
        local f
        local first_packets_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:3"
        local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"

        zapret_do_firewall_rules_ipt $1

        f="-p udp --dport 443"
        fw_nfqws_post $1 "$f $desync $first_packets_only" "$f $desync $first_packets_only" $QNUM2

        # fix NDM kernel masquerade for nfqws
        ipta_add_del $1 _NDM_MASQ -t nat -o ppp0 -j MASQUERADE
}

Попал мне девайс Irbis TZ797 на android 8.1
Если запускать обработчик очереди NFQUEUE на пакеты с интерфейса с сотовой сети, при этом кабель USB не воткнут (нет зарядки), то ядро очень быстро частично виснет, так что перестают работать тач и физические кнопки. При этом в броузере может продолжать анимироваться картинка.
Выяснил, что проблема связана с UID. По умолчанию nfqws назначает себе UID 0x7FFFFFFF. Видимо, в более новых ведроидах (на 5 точно такого не было), процессы с такими UID могут ложиться в suspend, что блокирует обработку очереди , а на это завязаны вызовы ядра. И получаем то, что видим.
Лекарство : nfqws --uid 1
Перепробовал несколько вариантов из низких uid. Все не виснут.
Для nfqws не нужны специальные uid 3003,3004,3005.
Дело в том, что nfqws назначает себе привилегии cap_net_raw, cap_net_admin. Это необходимо для работы с nfqueue и raw sockets. Для android это является одним из разрешающих условий для доступа к сети, вне зависимости от uid.

Добавлена возможность усекания пакетов в режиме udplen (отрицательный increment). Более, чем до 1 байта, усечение не работает.
Может быть полезно, когда прога добавляет паддинг в пакет, который ни на что не влияет, не проверяется, однако DPI проверяет размер пакета на минимальную длину.
Усечение пакетов от стандартных программ может помочь.

Поддержка множественных листов включения и исключения.
Альтернативой ipset является использование tpws или nfqws со списком доменов.
Оба демона принимают неограниченное количество листов include (–hostlist) и exclude (–hostlist-exclude).
Все листы одного типа обьединяются, и таким образом остаются только 2 листа.
Прежде всего проверяется exclude list. При вхождении в него происходит отказ от дурения.
Далее при наличии include list проверяется домен на вхождение в него. При невхождении в список отказ от дурения.
Пустой список приравнивается к его отсутствию.
В иных случаях происходит дурение.
Нет ни одного списка - дурение всегда.
Есть только exclude список - дурение всех, кроме.
Есть только include список - дурение только их.
Есть оба - дурение только include, кроме exclude.
В системе запуска это обыграно следующим образом.
Присутствуют 2 include списка :
ipset/zapret-hosts-users.txt.gz или ipset/zapret-hosts-users.txt
ipset/zapret-hosts.txt.gz или ipset/zapret-hosts.txt
и 1 exclude список
ipset/zapret-hosts-users-exclude.txt.gz или ipset/zapret-hosts-users-exclude.txt
При режиме фильтрации MODE_FILTER=hostlist система запуска передает nfqws или tpws все листы, файлы которых присутствуют.
Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа.
Файл есть, но не смотря на это дурится все, кроме exclude.
Если вам нужен именно такой режим - не обязательно удалять zapret-hosts-users.txt. Достаточно сделать его пустым.
Поддомены учитываются автоматически. Например, строчка “ru” вносит в список “*.ru”. Строчка “*.ru” в списке не сработает.
Список доменов РКН может быть получен скриптами ipset/get_reestr_hostlist.sh или ipset/get_antizapret_domains.sh - кладется в ipset/zapret-hosts.txt.gz.
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).

Обнаружилось, что в openwrt на базе nftables на самой типичной конфигурации реального роутера (bridge lan/wlan), не срабатывала схема включения hardware offload. Причина - проверка, чтобы все компоненты моста поддерживали hw offload. wlan его не поддерживает. Сделал, чтобы из моста выбирались только поддерживающие интерфейсы, и только они добавлялись в flowtable.

Интересная проблема обнаружилась с hardware flow offloading.
Стабильная версия openwrt 22.03 имеет ядро 5.10.
Только начиная с ядра 5.13 автоматически определяются физические интерфейсы под мостами, pppoe и vlan. До этого надо было как-то вручную определять порты моста, базовый ethernet device под vlan или pppoe, и только их совать в flowtable.
Для мостов и VLAN особых проблем нет. /sys/class/net/<iface_name> содержит ссылки lower_* на нужные интерфейсы. common/nft.sh из zapret умеет с таким работать. В случае hardware offload нижние девайсы определяются автоматом и засовываются в flowtable. Скрипт пытается туда засунуть и верхние, и нижние девайсы. Что проглотит - то и хорошо.

Но в случае pppoe не так все просто. Видимо нет очевидного способа определить что лежит под pppoe. В fw4 девайс определяется через вызов к netifd
“ifstatus wan” возвращает
“l3-device”: “pppoe-wan”
“device”: “eth0”
он и берется для засовывания в flow table

Пришлось и мне сделать нечто подобное. Но это работает только в openwrt.
Если вдруг каким-то образом у вас старенькая традиционная linux система с hw offload, которая не умеет засовывать в hw offload pppoe, то вам придется самому вписать добавление в flowtable физического интерфейса. Например, через hook. Впрочем, это весьма маловероятный случай
Лучшим решением будет проапгрейдить ядро.

Другое изменение : для традиционных linux и macos в конфиге теперь можно использовать отдельный список IFACE_WAN6 для исходящих ipv6 интерфейсов.

В правила nft внесен тестовый счетчик для проверки flow offload

nft list chain inet zapret  flow_offload

table inet zapret {
        chain flow_offload {
                oifname @wanif tcp dport 80 ip daddr @zapret ip daddr != @nozapret return comment "direct flow offloading exemption"
                oifname @wanif tcp dport 443 ct original packets 1-4 ip daddr @zapret ip daddr != @nozapret return comment "direct flow offloading exemption"
                meta l4proto { tcp, udp } flow add @ft
                meta l4proto { tcp, udp } counter packets 1227 bytes 75527 comment "if offload works here must not be too much traffic"
        }
}

Посмотрите текущий counter. Запустите speedtest. counter не должен увеличиваться сильно. Не должно быть никаких увеличивающихся мегабайтов.
Если они там есть - offload не работает.
Посмотрите какие интерфейсы занесены в flowtable.
Для software offload должны быть высокоуровневые интерфейсы (мосты, pppoe, vpn, …). Для hardware могут потребоваться лежащие под ними низкоуровневые интерфейсы (lan1, lan2, lan3, lan4). Общее правило - должны быть и входящие, и исходящие интерфейсы.
Если там их нет - значит что-то работает не так.

nft list flowtable inet zapret ft
table inet zapret {
        flowtable ft {
                hook ingress priority filter - 1
                devices = { br-lan, wan }
        }
}

Решил сделать свой сервис по обработке выгрузки реестра РКН.
Главная мотивация - отсутствие ipv6 в решениях от antifilter.network
Для получения листов используйте get_reestr_preresolved.sh и get_reestr_preresolved_smart.sh
Подробности тут https://github.com/bol-van/zapret/issues/130

В mdig добавлены опции --log-resolved и --log-failed
для создания логов успешных и провальных доменов

На http://list.nethub.fi появились листы проверенных доменов из реестра РКН, которые ресолвятся по ipv4, ipv6 и “ipv4 или ipv6” .
Как оказалось, примерно половина доменов из реестра не ресолвятся никак, фактические являясь трэшем

Блокировка QUIC все больше начала оформляться у провайдеров во что-то законченно-логичное вместо хаотических попыток что-то там заткнуть или заткнуть вообще весь протокол или порт.

На большинстве провайдеров сделана блокировка по SNI (идет расшифровка на DPI) как на ipv4, так и на ipv6, по списку заблокированных доменов.
Однако, модули распознавания QUIC initial видимо еще старые и кривые, потому могут сечь, например, curl с nghttp3 и chromium, но не сечь curl с quiche или firefox, потому блокировка может быть не видна с первого взгляда.
Как правило блокировки QUIC по SNI - stateful, поскольку анализировать каждый пакет в соединении чревато гигабитным флудом и залеганием DPI в bypass. Расшифровка QUIC - непростая операция. Это значит, что если DPI в сеансе UDP первым пакетом не видит ничего осудительного, то все остальное не анализируется.

Итак, QUIC внесен полностью в основные скрипты и инсталятор с поддежкой фильтрации по ipset/hostlist, аналогично http/https.
Особого смысла менять режим десинхронизации нет. Просто выбираете MODE=nfqws и отвечаете yes или no на “enable QUIC”. Дальше все само. По понятным причинам QUIC работает только с nfqws и не работает с tpws.

К сожалению, пока внести автопроверку на QUIC в blockcheck не представляется возможным, поскольку поддержка quic экспериментальна, и стандартные курлы http3 не поддерживают.
Потому можно посмотреть по F12 в броузере на facebook.com перешел ли он на HTTP3 после включения обхода.
Или лучше всего через curl --http3-only или посмотреть в wireshark udp port 443.
Прекомпиленые бинарики с поддержкой http3 можно загуглить для linux x86_64 и windows.
Если не обходится - выключайте.

Неплохой проект ByeDPI
Работает как прокси и не требует дополнительных привилегий в системе, тем не менее реализует режимы disorder2 и fake (последний может быть ненадежно).
Тем не менее содержит очень интересные идеи, до которых я бы раньше не догадался. Спасибо разработчику.
Вариант --disorder перенесен в tpws, обновлен blockcheck.
tpws имеет преимущества : работает в MacOS и не требует привилегий в режиме socks
Режим работает не так, как хотелось бы, в FreeBSD, OpenBSD и Windows вследствие особенностей ядра.

От переноса fake в tpws пока воздержался. Необходимо тестировать как он себя поведет на разных системах, поскольку используются потенциально ненадежные хаки.

Добавил в nfqws определение wireguard handshake initiation.
По крайней мере с тем блоком, что был недавно включен на ТСПУ, больше не потребуется --dpi-desync-any-protocol.
Что касается openvpn, то глубоко не изучал особенности его блокировки. Включат опять - будут смотреть имеет ли смысл добавлять определение протокола в nfqws

Заодно проверил работает ли увеличение длины пакета с wireguard. Не работает. Wg отбрасывает эти пакеты, так что --dpi-desync=udplen для wg не подходит. А было бы здорово, если бы работал. Диссектор из NDPI четко проверяет udplen==148

Сегодня стали блочить DHT.
Блокируются исходящие udp пакеты с длиной 101…399 , начинающиеся с “d1” и заканчивающиеся на “e”, с номерами src port 1025…65536. <=1024 не блокируются.
Блокировка stateful, но только в одну сторону. После пробивки с одной стороны аналогичные пакеты с другой стороны ходить не начинают.
Возможно, это связано с несколькими ТСПУ на пути : у исходящего провайдера, у входящего провайдера и на магистрали.
Некоторые DHT все же доходят с разных IP адресов. Предполагаю, что не на всех путях установлен ТСПУ, который считает пакет исходящим. Бывает не доходит даже из-за бугра, где нет ТСПУ (но может быть на магистрали).

Создан custom script custom-nfqws-dht4all.

nftables фильтр : ct original packets 1 meta length 109-407 meta l4proto udp @th,64,16 0x6431
iptables фильтр : -p udp -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:1 -m length --length 109:407 -m u32 --u32 ‘0>>22&0x3C@8>>16=0x6431’
ip6tables фильтр : -p udp -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:1 -m length --length 109:407 -m u32 --u32 ‘48>>16=0x6431’
nfqws : --dpi-desync=fake --dpi-desync-any-protocol --dpi-desync-cutoff=d2 --dpi-desync-ttl=5

(длина считается вместе с udp заголовком 8 байт)

Возможно, ситуация связана с выборами, и скоро отключат, но надо быть готовым

Сделал поддержку параметра nfqws --dpi-desync-udplen-pattern.
Можно задать файл или hex строку, которой добиваются udp пакеты при режиме десинхронизации udplen.
Теперь везде, где nfqws раньше читал файл, можно указывать как имя файла, так и HEX строку, которая начинается с 0x

Сделал распознавание протокола DHT. Распознается как udp, начинающийся с d1, кончающийся e (соответствует фильтру ТСПУ).
Новый режим десинхронизации tamper.
Этот режим предназначен для корректной модификации известных пейлоадов, чтобы DPI их не распознавал, но пейлоад оставался корректным и нес ту же смысловую нагрузку.
Для DHT это вставление строки “2:001:x” после “d” в начале. Вставляется ничего не значащий элемент в bencode dictionary с длиной ключа 2, вместо 1. Таким образом dht начинается с d2.

Этот метод может помочь, если вдруг сделают блокировку stateless. fake против stateless не работает

Нашел средство обьединять подсети.
ip2net работает только с отдельными IP адресами, пропуская подсети как есть.
Это позволило существенно сократить размер листов с list.nethub.fi
Для роутеров с nft и обьемом памяти <256 Mb это крайне актуально

Принципиально новый способ дурения через tpws : --tlsrec
Разбиение ClientHello на уровне TLS Record. Одну TLS record нарезаем на две в одном TCP сегменте (при желании потом и это можно разделить на 2 tcp сегмента через --split-pos и перепутать порядок пакетов --disorder).
Режем или прямо по хосту в SNI, что исключает бинарный поиск паттерна без парсинга протокола, или на указанной байтовой позиции.
Говорят, работает даже на китайском фаерволе.

Метод хороший, но ломает различные ddos защиты, потому где-то 10% сайтов обломаются. gosuslugi не работают. Без фильтра использовать нецелесообразно.

В России не работает на TLS 1.2, поскольку rdp-шный DPI еще смотрит на сертификат из ответа сервера TLS ServerHello. Это можно обойти через комбо с nfqws --wssize.

Удивительно, но многие серьезные сайты все еще не поддерживают TLS 1.3
Среди них сбер, другие банки, гос услуги, mail.ru
Среди заблокированных точно не поддерживает lostfilm.tv