Формат --out-range / --in-range:

--out-range=[(n|a|d|s|b|x)<int>](-|<)[(n|a|d|s|b|x)<int>]
             ───────────────────────────────────────────
                  FROM          SEPARATOR      TO

Префиксы (режимы счёта):

ПрефиксЗначениеЧто считает
npacket numberПорядковый номер перехваченного пакета (в выбранном направлении)
ddata packetТолько пакеты с payload (данными)
ssequenceОтносительный TCP sequence number
bbyte countКоличество переданных байт
aalwaysВсегда (без числа)
xnext/neverНикогда (без числа)

Важно: все счётчики (n/d/b/s/p) считаются только по тем пакетам, которые реально попали в движок (перехвачены NFQUEUE/WinDivert и не отфильтрованы раньше). Если какой-то пакет “мимо” (не перехвачен или отсеян, например пустые ACK в winws2), он не увеличит n, и “номер пакета” для --out-range сместится.

Разделители:

РазделительЗначение
-Включает конечную позицию
<Не включает конечную позицию

Как считаются пакеты в --out-range: n и d Счётчик n считает все пакеты нужного направления, счётчик d — только пакеты с данными. SYN и пустой ACK дают d=0, ClientHello — d=1. --out-range считает только исходящие пакеты, --in-range — только входящие. Ниже — какие d попадают под -d10, d1-d10, d1<d10 и d5-. исходящие (--out-range) входящие (--in-range) SYNn=1 d=0 ACK, пустойn=2 d=0 ClientHello / HTTPn=3 d=1 SYN-ACKn=1 d=0 для --out-range не считается:это входящий пакет data-пакет (d) — тот, где есть данные приложения; пустые ACK, FIN и RST d не получают. какие data-пакеты попадают в диапазон d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 -d10 d1-d10 d1<d10 d5- … winws2 по умолчанию не перехватывает пустые ACK (--wf-tcp-empty=0): n «перескакивает», и условия по n сдвигаются.

Примеры с d:

ЗначениеРасшифровка
d1-d10С 1-го по 10-й data-пакет включительно
d1<d10С 1-го по 9-й data-пакет (10-й не включён)
-d10С начала (always) по 10-й data-пакет включительно
d5-С 5-го data-пакета и до конца (бесконечно)

Что такое “data packet”?

Data packet (d) — это пакет, содержащий payload (данные L7). Пустые ACK, FIN, RST без данных не считаются.

out (клиент → сервер):
  1) SYN               → n=1, d=0
  2) ACK (пустой)      → n=2, d=0   (если этот ACK перехвачен)
  3) ClientHello/HTTP  → n=3, d=1
 
in (сервер → клиент):
  1) SYN-ACK           → n=1, d=0   (для --in-range, т.к. это входящее направление)

Частая ловушка: пытаться считать n “глобально по соединению” и включать туда SYN-ACK. На самом деле --out-range считает только outgoing, а --in-range — только incoming.

Важно про Windows / winws2: --wf-tcp-empty=0 ломает ожидания по n

В winws2 по умолчанию обычно включено --wf-tcp-empty=0 — это не перехватывает пустые ACK ради экономии CPU. Следствие: второй исходящий пакет TCP (handshake ACK) часто не попадает в движок, n “перескакивает”, и n2<n3 может сработать на ClientHello.

Что делать:

  • если тебе нужен именно пустой ACK — включай --wf-tcp-empty=1
  • если тебе нужно целиться в “первый пакет с данными”, используй d (он стабильнее при отсеивании пустых ACK)

Практический пример:

--out-range=d1-d3 --lua-desync=my_func

→ my_func будет вызываться только для 1-го, 2-го и 3-го исходящих пакетов с данными в соединении.

--out-range=d10-d10    # ровно 10-й data packet
--out-range=d10-       # с 10-го и до бесконечности  
--out-range=-d10       # с начала до 10-го включительно
--out-range=d10<d11    # только 10-й (11-й исключён)