Zapret: what's new

Мануал дописан в первом приближении.
Получилось техническое руководство, но таким оно и предполагалось. Руководство программиста или сисадмина, справочник.
readme оставлю таким как есть - краткий гайд для миграции с z1, чтобы не талмудить на главной
никаких чайник инструкций не будет

Постоянно этот вопрос. Написал ответ в manual от z2

ПОЧЕМУ БЛОКЧЕК ДА, БРОУЗЕР НЕТ

Сделал анализ DNS ответов и занесение их в --ipcache-hostname.

Имена хостов для кэширования берутся из анализа L7 протоколов и из DNS ответов (не DoH). Извлечение DNS работает только по udp протоколу и требует перенаправления пакетов с порта 53. Нужны только ответы DNS, имеющие source port 53. На Windows это будет --wf-udp-in=53. Скорее всего будет обращение к DNS внутри локальной сети, поэтому нужен параметр --wf-filter-lan=0. На роутере, если используется шифрованный DNS, надо ловить запросы от клиента еще до шифрования - на LAN интерфейсе. Если шифрование не используется, можно ловить и на WAN. Для LAN интерфейса они будут исходящими, для интерфейса WAN - входящими, по направлению conntrack - reply.

С броузером с включенным Doh или с включенным doh на уровне ОС работать не будет

Обертка в linux вокруг функции экстракции dns ответов не совсем тривиальна.

Просто добавить порт 53 не всегда сработает в в openwrt.
Перехват портов NFQWS2_PORTS_UDP идет на wan интерфейсе.
В дефолтной конфигурации клиент получает DNS openwrt, на котором запущен dnsmasq, форвардящий запросы в wan. Тут все нормально.
Но что если на openwrt установлен dnscrypt или doh ? Не будет работать, ведь запросы в открытом виде не идут в wan.
Поэтому их надо перехватывать в lan. Но такой функции готовой нет и обертки в скриптах тоже.

Чтобы ради этого случая не разрабатывать специальную схему, проще все сделать в кастоме с созданием отдельных цепочек.
custom скрипт 80-dns-intercept перехватывает исходящие udp src port 53 на lan интерфейсах, а так же входящие на саму систему и исходящие с нее (input + output). Первый вариант - для роутера, когда клиент запрашивает сторонний dns, а не dns роутера. Второй вариант - для самого роутера или для клиентской системы на linux. Третий вариант - для dns сервера - когда клиент запрашивает dns роутера, например.

Итак,

  1. Если система - роутер, но не openwrt, обязательно прописываем IFACE_LAN в config
  2. Копируем кастом 80-dns-intercept в custom.d
  3. Добавляем параметр --ipcache-hostname в NFQWS2_OPT

А что в винде делать ?

Там --wf-udp-in=53 --wf-filter-lan=0 сработает. Но только если обращение не идет к localhost, на котором крутится dns proxy. В этом случае еще добавляем --wf-filter-loopback=0

Реализовано сжатие gzip через C код. C функции оперируют с частями сжатых и расжатых данных в памяти, с файлами не работают.
В zapret-lib готовые обертки на lua для чтения и создания gzip файлов, а так же для проверки является ли файл gzip

Может быть полезно для чтения гзипованных хостлистов или сохранения больших файлов с произвольными данными в условиях ограниченного места.

кастом скрипт 99-lan-filter

регулярно спрашивают как дурить только определенные IP адреса из локалки

уже довольно давно существует параметр конфига FILTER_MARK
он задает бит, только при установке которого в mark идет дурение
его можно установить по любым критериям через правила таблиц
можно написать хоть каждый четверг с 9 до 18 , с ип адреса раз два три и только с wifi

но для чайников все, что связанное с таблицами, очень сложно
они спрашивают “куда вписать IP, с которых разрешено дурение”.
стандартный ответ : пишите свои таблес и туда вписывайте

теперь есть куда вписывать

  1. копируем 99-lan-filter в custom.d
  2. в сonfig раскомментируем FILTER_MARK=0x10000000
  3. если это не openwrt роутер, раскомментируем IFACE_LAN и вписываем туда lan интерфейсы в кавычках через пробел. IFACE_LAN=“eth0 eth1”
  4. в config : FILTER_LAN_IP=“192.168.1.0/24 192.168.25.12 192.168.25.18”
  5. в config : FILTER_LAN_IP6=“fd88:3e16::/32 fc12::3”
  6. рестарт zapret2

z1 EOL, в нем этого нет и не будет, но умельцы могут адаптировать. правок минимум

черного списка “не дури с этих” не реализовано, но можно белопушисто-православных заDHCPить в определенный range - 192.168.1.128/25, а нормальных в 192.168.1.0/25. назначить диапазон dhcp до .127, а статические лизы выдавать с 128.
для ipv6 нужно отключать slaac и оставлять только dhcpv6, в нем и делать белопушистые leases

Давно не менявшийся mdig получил функцию управления поведением при получении EAI_AGAIN от getaddrinfo()

EAI_AGAIN - system-level error that indicates a temporary failure in name resolution (DNS issue). The system is unable to resolve a given hostname to an IP address at that moment

Обычно случается, когда используется свой DNS ресолвер, в котором еще не закэшировалось все, что только возможно, как это может произойти с 1.1.1.1 или 8.8.8.8.
DNS - система иерархическая. Чтобы отресолвить www.microsoft.com, надо сначала отресолвить com, на root серверах , потом microsoft.com, потом www.microsoft.com.
Все это сопряжено с обращением к разным DNS серверам по ip4 или ip6.
Часто бывает, что некоторые сервера сломаны, не отвечают или имеется блокировка по IP.
У DNS ресолвера есть таймаут. Он пытается дернуть другие IP , другую версию ip. Он не ждет и возвращает ошибку “попробуй позже, а пока я тут долблюсь”
Это и есть EAI_AGAIN

Раньше mdig выполнял всего 2 попытки без задержки. Очень много хостов не могло отресолвиться.
Теперь по умолчанию 10 попыток с задержкой 0.5 сек. Параметры настраиваются. Степень успешности ресолвинга значительно возросла, но так же увеличилось и требуемое время.

Сейчас держать в России рекурсивный ресолвер - проблемно, потому что много блокировок по IP. Много куда не доходит, и это видно по результату ресолвинга большого листа. За бугром он почти весь ресолвится, здесь же куча ерроров

Сделан английский readme. Переводил Gemini 3.
Может где-то и не очень литературно, но смысл вполне должен дойти.
Не знаю насколько актуально, будет ли кто-то вне RU это юзать, но пусть будет

Параметр --payload-disable берет список пейлоадов через запятую, которые не надо детектить.
Если нет аргумента - не детектить ничего.

Бывают ложные детекты. Например, игра roblox выдает udp пакеты длиной 148, начинающиеся на 0x01. Слабая сигнатура wireguard срабатывает, хотя там нет wireguard.
Проверять последующие 3 байта на ноль - значит не будет детектить wg от сторонних клиентов - xray.

Если когда-либо будет мешать детектор какого-то пейлоада - его можно избирательно отключить
Протоколы потока детектятся на базе пейлоадов. Без пейлоадов нет и --filter-l7

Решил все-таки отказаться от детекта wireguard с нестандартными reserved bytes 1..3
Слишком уж слабая сигнатура получается по первому байту и длине, если какая-то игруха ломает детект.
ndpi так же детектит по 4 байтам

win bundle постепенно переходит на z2 как основу, хотя и сохраняет в себе z1.

service1, example1 - это zapret1
service2, example2 - это zapret2

убрано подобие простых инструкций, полный отказ от пошаговости
Это только комплект для уже понимающих что с ним делать, не сборка в смысле одной кнопки

Попытка привнести oob из tpws в z2.

Основная проблема oob в том, что он всовывает лишний байт в tcp, тем самым сдвигая все sequence numbers вправо. Без коррекции до скончания соединения оно не выживет.
Но можно сдвинуть seq на этапе handshake влево на 1 байт. Это потребует “ведения” нескольких пакетов, но потом можно отпускать.

Выглядит оно как-то так
--in-range=-s1 --out-range=-d3 --lua-desync=oob:urp=0:byte=255

Ему нужны входящие для коррекции ack.
urp - это маркер положения oob байта, либо символы e или b
На мультипакетных пейлоадах th_urp автоматически нормализуется и всовывается в тот сегмент, в который попадает, в остальных флаг URG снимается.
Есть 2 специальных значения - e - это байт за последним байтом пейлоада. Маркеры не могут ресолвиться в позиции за пределами пейлоада, потому специальное значение.
b - это как 0, но th_urp ставится 0 вместо 1. Существует 2 стандарта OOB data. По одному th_urp указывает на oob, по другому - тому, что реализован в современных ОС, - на следующий байт за ним.
Значение 0 поддерживают только Linux сервера, остальные ломаются.
При использовании b могут возникнуть проблемы с оффлоадами сегментации

Работает только по первому пейлоаду вне зависимости от его типа. Дальше уходит в cutoff
Проверка типа пейлоада не имеет смысла, поскольку отмена OOB невозможна из-за порчи sequence, случившейся на нулевой фазе.

Функция работает с нулевой фазы, поэтому хостлисты отлетают.
Без нулевки - только tpws использовать, но в нем несколько иной расклад по сегментам

TLS 1.2 не пробивается

Функция не работает с multisplit, multidisorder, fakedsplit, fakeddisorder и тому подобными
Потому что oob берет на себя ведение соединения от начала до приема первого пейлоада и сам его как надо меняет и отправляет. multidisorder лишь еще раз отправит то же самое, только без oob и в своем порядке

ЕЩЕ ОДНО ВАЖНОЕ ИЗМЕНЕНИЕ. Сделан выбор mss как минимума обоих концов.
Если mss разный, может начаться ip фрагментация или “message too long”.
Если хотя бы с одного конца неизвестен mss, например, потому что не перехвачен входящий трафик совсем, берется значение по умолчанию 1220

FreeBSD 15

Релиз по мне так крайне глючный
Много раз видел kernel panic в связи с сетевой активностью. До 15 - ни разу.

А это меня вообще добивает.
Он в divert socket пихает пакет, который не пройдет MTU, реинжектнуть который невозможно без “packet too long”, а в следующий раз исправляется и шлет по новой. Но если вдруг часть уже отослана через dvtws, допустим 2 байта, то следующая попытка начинается с seq=3 вместо seq=1, и она не схватывается, потому что протокол не определяется

packet: id=4 len=1537 ifin= ifout=unknown
IP4: 192.168.1.86 => 151.101.64.81 proto=tcp ttl=64 sport=51813 dport=443 flags=AP seq=2328003713 ack_seq=1221249254
TCP: len=1485 : 16 03 01 xxxxxxx
client mode desync profile/ipcache search target ip=151.101.64.81 port=443
LUA: tcpseg: pos: 0,1
LUA: tcpseg: resolved range: 0 1
LUA: tcpseg: sending 0-1 len=2 seqovl=0 : 16 03  ..
rawsend_dissect repeats=1 size=54 badsum=0 ifout=unknown fwmark=00000200
packet: id=4 reinject unmodified
reinject sendto: Message too long

packet: id=5 len=1500 ifin= ifout=unknown
IP4: 192.168.1.86 => 151.101.64.81 proto=tcp ttl=64 sport=51813 dport=443 flags=A seq=2328003715 ack_seq=1221249254
TCP: len=1448 : 01 05 C8 ...

blockcheck2 выглядит уныло

curl: (35) Recv failure: Connection reset by peer
UNAVAILABLE code=35
- curl_test_https_tls13 ipv4 bbc.com : dvtws2 --debug --payload=tls_client_hello --lua-desync=multisplit:blob=fake_default_tls:ip_ttl=1:pos=2:nodrop:repeats=1
reinject sendto: Message too long
curl: (35) Recv failure: Connection reset by peer
UNAVAILABLE code=35
- curl_test_https_tls13 ipv4 bbc.com : dvtws2 --debug --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:ip_ttl=1:tls_mod=rnd,dupsid,padencap:repeats=1
reinject sendto: Message too long
curl: (35) Recv failure: Connection reset by peer
UNAVAILABLE code=35
- curl_test_https_tls13 ipv4 bbc.com : dvtws2 --debug --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:ip_ttl=1:repeats=1 --payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip_ttl=1
reinject sendto: Message too long
curl: (35) Recv failure: Connection reset by peer
UNAVAILABLE code=35
- curl_test_https_tls13 ipv4 bbc.com : dvtws2 --debug --payload=tls_client_hello --lua-desync=fake:blob=0x00000000:ip_ttl=1:repeats=1 --payload=empty --out-range=s1<d1 --lua-desync=pktmod:ip_ttl=1
reinject sendto: Message too long
curl: (35) Recv failure: Connection reset by peer
UNAVAILABLE code=35

UPD. Кажется проблема в vmxnet3 драйвере vmware. На e1000 норм.
Или ifconfig vmx0 -tso

Для страждущих от чрезмерно долгого сканирования хостов в blockcheck2 добавлена возможность параллельного запуска нескольких инстансов на разные хосты.
В winws для этого введен параметр --wf-dup-check, позволяющий отключить проверку на инстансы с теми же параметрами --wf

Должно работать на всех системах, кроме OpenBSD. Из-за особенностей pf там это сделать сложновато и неудобно

Все правила редиректа на unix системах снабжаются фильтром по ip , в которые ресолвится хост. На windows используется неявный --ipset, поэтому конфликтов между инстансами не должно быть. Естественно, если домены не сидят на пересекающихся IP.