Zapret: what's new

Появился blockcheck2.
Его основное отличие от blockcheck1 - модульность.
Есть директория blockcheck2.d . В ней субдиректории. Каждое имя субдиректории - это имя теста.
Тест выбирается в процессе запуска blockcheck2.
Внутри директории теста в алфавитном порядке выполняются все скрипты. Каждый скрипт может иметь функции, предназначенные для проверки http, tls1.2, tls1.3 и quic.

standard - это тестилка стратегий, похожая на blockcheck1, но разнесенная по файлам.
Все блоки тестов имеют соответствующую переменную для отказа от данного теста. См код *sh скриптов.
Поддерживается передача кастомных блобов на разные случаи жизни. Так же см код скриптов

custom - тестилка стратегий из простого списка из файла. файлы разнесены по протоколам. можно заменить к ним путь.

Параметры PKTWS_EXTRA и PKTWS_EXTRA_N переименованы в PKTWS_EXTRA_POST и PKTWS_EXTRA_POST_N.
PKTWS_EXTRA_PRE и PKTWS_EXTRA_PRE_N остались как есть. В zapret2 порядок вызова lua инстансов имеет принципиальное значение !

Режим quick теперь работает совсем иначе. Единственное, что он дает, это прекращение тестирования следующих попыток после получения отрицательного результата. Выхода по первому успеху больше нет !

Сделал пример кастома для обслуживания типичного веб сервера.
Бывает сложно пробиться только с клиента, потому что секут ответы сервера.
Если сервер под контролем, можно и с него обманывать DPI. Конечно, это не замена клиентскому дурению, а дополнение для точечного пробива. По понятным причинам это невозможно применить ко всем серверам.

В дефолтной стратегии применяется техника tcp split handshake - разбив ответа SYN,ACK на отдельные пакеты SYN и ACK. По http reply и server hello отрабатывает fake+multisplit

Параметр ‘–server’ заменяет логику интерпретации ip/port источника приемника, чтобы корректно матчились ipset-ы и --filter-tcp/–filter-udp. Так же инвертируются логические направления tcp : out по умолчанию считается от источника пакета SYN, а в серверном режиме - наоборот. in, соответственно, тоже инвертируется

# this custom script runs nfqws2 in server mode for typical webserver

WEBSERVER_DEFAULT_STRATEGY="
--server
--payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
--payload empty --lua-desync=synack_split"

# can override in config :
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"
WEBSERVER_PORTS="${WEBSERVER_PORTS:-80,443}"
WEBSERVER_PKT_OUT="${WEBSERVER_PKT_OUT:-15}"

alloc_dnum DNUM_WEBSERVER
alloc_qnum QNUM_WEBSERVER

zapret_custom_daemons()
{
	# $1 - 1 - add, 0 - stop

	local opt="--qnum=$QNUM_WEBSERVER $NFQWS_OPT_DESYNC_WEBSERVER"
	do_nfqws $1 $DNUM_WEBSERVER "$opt"
}
zapret_custom_firewall()
{
        # $1 - 1 - run, 0 - stop

	local PORTS=$(replace_char - : $WEBSERVER_PORTS)
	local first_packets=$(ipt_first_packets $WEBSERVER_PKT_OUT)
	local f="-p tcp -m multiport --sports $PORTS $first_packets"
	fw_nfqws_post $1 "$f" "$f" $QNUM_WEBSERVER
}
zapret_custom_firewall_nft()
{
        # stop logic is not required

	local first_packets=$(nft_first_packets $WEBSERVER_PKT_OUT)
	local f="tcp sport {$WEBSERVER_PORTS} $first_packets"
	nft_fw_nfqws_post "$f" "$f" $QNUM_WEBSERVER
}

Инсталятор и скрипты запуска адаптированы.
Осталась дока.

Задали вопрос как сделать автоматию.
Если что-то там происходит, то применять одну стратегию, а если происходит другое - другое.
Конечно, это все можно написать на LUA.
Но хотелось бы использовать существующие функции без правки.
Придумал вот такую схему. Называется desync orchestration.

C функция execution_plan(ctx) возвращает таблицу с информацией о предстоящих вызовах (имена и номера функций, имена инстансов, аргументы инстансов).
lua-desync функция может отменить текущий execution plan C функцией execution_plan_cancel(ctx). После отмены по текущему пакету все последующие инстансы не будут вызваны.
Функция, отменяющая план выполнения, берет на себя функции планирования (оркестрации) дальнейших действий. Она знает как и с какими параметрами что вызывать (или не вызывать по собственному решению). Конечно, при этом отваливаются фильтры по range и payload на уровне C кода. Точнее, C код ничего не знает об оркестрации, для него все функции идентичны, поэтому по реально вызываемым инстансам будет работать последний фильтр.
Но оркестратор может взять эту функцию на себя, благо ему доступно состояние conntrack и тип пейлоада.
А что делать с cutoff ? cutoff можно вызывать либо по инстансу/направлению индивидуально (только по текущему инстансу) через instance_cutoff(ctx), либо отрубить все направление по соединению через C функцию lua_cutoff(ctx).

Допустим, надо сечь ретрансмисии. Ретрансмиссия - это повторная передача пакетов в том же диапазоне sequence numbers.
Для анализа sequence numbers есть desync.track.tcp, для подсчета ретрансмиссий можно использовать desync.track.lua_state - persistent таблицу по соединению.
Для пометки инстансов одной стратегии использовать тэг-аргументы типа --lua-desync=func:args...:tag=strategy1

Оркестратор считает ретрансмиссии. Пока счетчик не превысил порог - вызывает инстансы с аргументом tag=strategy1, после - инстансы с tag=strategy2.
Если еще что-то случается, и он решает, что дальше делать нечего, делает соединению lua_cutoff. Так рубится вся цепочка инстансов по соединению. Но можно использовать и range/payload фильтры из C кода перед оркестратором - они так же будут работать. Не будут работать только индивидуальные range/payload фильтры по истансам после оркестратора, поскольку они не вызываются из C кода.

Пример простейшего оркестратора добавлен в zapret-lib.lua. Он ничего не делает, просто вызывает все последующие инстансы, подготавливая для них корректную desync таблицу.

MDIG cache был давно сломан в blockcheck1, проблема перешла и в blockcheck2
fixed now

Вопрос комьюнити по около-запрету.
Я не знаю как пробиваться к разработчикам подсистем linux. Надо пробиться к разрабам wireless subsystem. На багтрак никто не реагирует. Куда стучать ?

С ядра 5.19 сломалась выдача SSID через nl80211, хотя через wext работает.
но wext скоро совсем отдохнет, --filter-ssid превратится в тыкву. он уже превратился на дистрибутивах, где выключают wext. На android это легко может случиться по мере обновления ядер, спасает только пока, что в основном ядра там достаточно старые

# iwgetid
wlan0     ESSID:"my_cool_wifi"

# iw dev wlan0 info
Interface wlan0
        ifindex 4
        wdev 0x1
        addr 00:11:22:33:44:55
        type managed
        wiphy 0
        channel 13 (2472 MHz), width: 20 MHz, center1: 2472 MHz
        txpower 20.00 dBm
        multicast TXQ:
                qsz-byt qsz-pkt flows   drops   marks   overlmt hashcol tx-bytes        tx-packets
                0       0       0       0       0       0       0       0               0

На более старых ядрах на том же железе во-второй команде выдается ssid. 6.17 - все еще сломано

Реализована поддержка имен профилей (names) и шаблонов профилей (templates).
template - это тоже профиль, принимающий в себя все настройки профиля, но он не идет в список рабочих профилей. Профиль является шаблонными, если в пределах его определения (между --new) присутствует параметр --template.
templates выносятся в отдельный список, чтобы потом из него можно было импортировать настройки. Шаблонному профилю обязательно назначается уникальное имя (–name), после чего его можно импортировать в рабочий профиль (–import=name). Процедура импорта стирает все данные текущего профиля, замещая данными шаблона (включая имя), поэтому --import надо указывать в самом начале после --new. Остальные настройки добавляются к импортированным.

Импорт нескольких шаблонов с наложением не реализован. Однако, шаблоны - тоже полноправные профили и могут импортировать другие шаблоны. Здесь будет 2 шаблона и 1 рабочий профиль, который выполнит 3 инстанса

--template --name t1 --lua-desync=pass --new
--template --import t1 --name t2 --lua-desync=posdebug --new
--import t2 --name template_test --lua-desync=argdebug:test1=1:test2=2
profile 1 (template_test) lua pass( range_in=x0-x0 range_out=a0-a0 payload_type= all)
profile 1 (template_test) lua posdebug( range_in=x0-x0 range_out=a0-a0 payload_type= all)
profile 1 (template_test) lua argdebug(test2="2",test1="1" range_in=x0-x0 range_out=a0-a0 payload_type= all)
template 1 (t1) lua pass( range_in=x0-x0 range_out=a0-a0 payload_type= all)
template 2 (t2) lua pass( range_in=x0-x0 range_out=a0-a0 payload_type= all)
template 2 (t2) lua posdebug( range_in=x0-x0 range_out=a0-a0 payload_type= all)

Убрана детализация пейлоада stun_binding_req.
Любые stun сообщения теперь имеют пейлоад “stun”.