🪟 wssize в zapret — крайняя мера: без хостлистов, без l7-фильтра, в конце лога blockcheck

О чём заметка

Что делает параметр --wssize в zapret, почему это стратегия последней надежды, а не «ещё одна галочка», и почему blockcheck показывает wssize-стратегии в самом конце лога. Ключевые факты — из ответов разработчика zapret (ник bolvan) на форуме ntc.party, август 2026.

TL;DR

  • --wssize уменьшает TCP window size на этапе установления соединения — до того, как zapret узнаёт hostname или протокол.
  • Поэтому wssize не работает с хостлистами (--hostlist) и не работает с l7-фильтром — сработает только фильтрация по l3/l4: IP-адреса (ipset) и порты. Единственное исключение для хостлистов — --ipcache-hostname.
  • Blockcheck в режиме standard проверяет wssize только для TLS 1.2 и только если весь перебор без wssize не дал ни одной рабочей стратегии; в режиме force дублирует с wssize всю простыню. В обоих случаях wssize-стратегии попадают в конец лога — и их бездумно копируют, не зная об ограничениях.
  • Рекомендация разработчика: от wssize лучше избавиться и найти другой вариант обхода.

Что делает wssize

TCP window size — это поле в заголовке TCP-пакета, которым получатель сообщает отправителю, сколько байт он готов принять. --wssize=<размер>[:<scale>] заставляет zapret подменять это поле в исходящих пакетах: сервер видит крошечное «окно» и вынужден отправлять свой ответ маленькими кусочками, ожидая подтверждения после каждого.

Проще говоря: wssize врёт серверу «я могу принимать только по чуть-чуть», и сервер нарезает свой ответ на мелкие фрагменты. DPI, который не пересобирает TCP-поток, не видит целиком серверные сообщения TLS-рукопожатия и не может сработать по ним.

Практический смысл у этого в основном для TLS 1.2: там сертификат сервера передаётся открытым текстом, и цензор может блокировать соединение по содержимому серверного ответа. В TLS 1.3 сертификат зашифрован, поэтому там обычно хватает стратегий, работающих по ClientHello, и wssize не нужен. Отсюда и логика blockcheck ниже: wssize — инструмент для случаев вроде старой техники, которая умеет только TLS 1.2.

Смежные флаги (полный список — в Zapret flags): --wssize-cutoff задаёт, когда прекратить подмену окна, а --wssize-forced-cutoff=0|1 (появился в Zapret v72.2) управляет автоотключением wssize при обнаружении известного протокола. Для работы wssize нужен внутренний conntrack zapret — с --ctrack-disable он несовместим.

Почему wssize — плохо

Главная проблема — момент срабатывания. Все обычные desync-стратегии работают, когда клиент уже отправил данные (HTTP-запрос или TLS ClientHello): в этот момент zapret знает hostname из SNI и может опознать протокол. wssize же должен подменить окно ещё на этапе установления соединения — когда никаких данных приложения нет.

Из этого следуют два ограничения:

  • Хостлисты не работают. На момент TCP-рукопожатия SNI ещё не передан, поэтому --hostlist отфильтровать wssize не может. Исключение одно: флаг --ipcache-hostname включает кэш соответствий IP → hostname, и тогда для повторных соединений к уже виденному IP хостлист применить получится. Первое соединение к каждому IP всё равно пройдёт без опознания — та же проблема «нулевой фазы», что подробно разобрана для syndata.
  • l7-фильтр не работает. Опознавание протокола (HTTP, TLS, QUIC…) происходит на этапе передачи данных, а wssize отрабатывает раньше — при установлении соединения. Значит, ограничить wssize «только для TLS» нельзя: доступна лишь фильтрация по l3/l4 — IP-адреса (ipset) и порты.

Проще говоря: wssize нельзя нацелить на конкретные заблокированные сайты — он бьёт по всем соединениям, попавшим под фильтр порта/IP. А поскольку каждый такой сервер начинает слать данные крошечными порциями с ожиданием подтверждений, старт каждого соединения замедляется — в том числе к сайтам, которые вообще не заблокированы.

wssize в blockcheck: почему он в конце лога

Blockcheck перебирает стратегии по уровням сканирования, и wssize там включён с осторожностью (по ответам bolvan на ntc.party, август 2026):

  • standard — wssize-стратегии проверяются только для TLS 1.2 и только если весь цикл перебора без wssize не выявил ни одной рабочей стратегии.
  • force — сканируется всё подряд: полный дубль всей простыни стратегий ещё раз, уже с wssize.

В обоих режимах wssize-варианты оказываются в конце списка проверок и в конце лога.

Ловушка для копипастеров

«Последняя стратегия в логе» — не значит «лучшая». Человек, который бездумно копирует строки из конца blockcheck.log, получает wssize-стратегию со всеми её проблемами: замедлением всех соединений на отфильтрованных портах и невозможностью ограничить её хостлистом. Если в логе есть рабочие стратегии без wssize — брать нужно их.

Что делать вместо wssize

Рекомендация разработчика zapret однозначна: от wssize лучше избавиться и искать другой вариант. На практике это значит:

  • Сначала перебрать все стратегии без wssize — в Zapret GUI или через blockcheck.
  • Если у DPI проблемы именно с серверным ответом TLS 1.2 — проверить, не решается ли вопрос переходом клиента на TLS 1.3 (обновление браузера/системы), тогда wssize не понадобится вовсе.
  • Если wssize всё же единственное, что работает (старая техника, только TLS 1.2), — максимально сузить зону поражения: фильтровать по IP через ipset и портам, включить --ipcache-hostname с хостлистом, оставить автоотключение --wssize-forced-cutoff=1 (значение по умолчанию).

📚 См. также

  • Zapret flags — справочник флагов nfqws/winws, включая --wssize, --wssize-cutoff, --wssize-forced-cutoff и --ipcache-hostname
  • Blockcheck — как запускать автоперебор стратегий и читать его лог
  • syndata — другая стратегия «нулевой фазы» с той же проблемой хостлистов и обходом через --ipcache-hostname
  • desync-функции zapret2 — lua-аналоги wsize/wssize в zapret2
  • Zapret v72.2 — версия, где появился --wssize-forced-cutoff

🤖 Эти статьи открыты — можно обучать на них ИИ

При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование доступно в Forgejo: исходник этой заметки · скачать весь репозиторий одним zip-архивом.