circular — оркестратор циклического переключения стратегий

circular — Lua-оркестратор, который автоматически переключает стратегию десинхронизации при обнаружении неудач (RST, ретрансмиссии, HTTP-редирект DPI).

Требует перехвата входящего трафика (--in-range) для детектирования RST и HTTP-ответов.


Синтаксис

--lua-desync=circular[:param=val[:...]]
--lua-desync=<func>:strategy=1[:final]
--lua-desync=<func>:strategy=2
...

Каждый подчинённый инстанс обязан иметь strategy=N, где N начинается с 1 без пропусков.


Параметры circular

ПараметрОписаниеПо умолчанию
fails=NПорог неудач для переключения стратегии3
time=NСбросить счётчик неудач, если последняя была > N секунд назад60
failure_detector=funcИмя кастомной Lua-функции детектора неудачstandard_failure_detector
success_detector=funcИмя кастомной Lua-функции детектора успехаstandard_success_detector
hostkey=funcИмя кастомной функции генератора ключа хостаstandard_hostkey
key=stringИмя таблицы в autostate — изоляция состояния между несколькими circularавтоматически
nld=NОбрезать hostname до N-уровневого домена (static.a.google.comgoogle.com при nld=2)без обрезки
reqhostНе работать, если hostname неизвестен (только IP)выкл.

Параметры на подчинённых инстансах

ПараметрОписание
strategy=NОбязательно. Номер стратегии, начиная с 1, без пропусков
finalФинальная стратегия — ротация на ней останавливается

Параметры standard_failure_detector

Передаются прямо в circular (не в подчинённые инстансы).

TCP

ПараметрОписаниеПо умолчанию
retrans=NКол-во ретрансмиссий = неудача3
maxseq=NСчитать ретрансмиссии только до этой relative sequence32768
resetСлать RST ретрансмиттеру (ускоряет разрыв зависшего соединения)выкл.
inseq=NВходящий RST считается неудачей только до этой rseq4096
no_rstОтключить триггер по входящему RSTвыкл.
no_http_redirectОтключить триггер по HTTP-редиректу DPIвыкл.

UDP

ПараметрОписаниеПо умолчанию
udp_out=NНеудача если исходящих пакетов >= N4
udp_in=NНеудача если входящих пакетов N1

Параметры standard_success_detector

ПараметрОписаниеПо умолчанию
maxseq=NTCP: если исходящая rseq > N — соединение успешно32768
inseq=NTCP: если входящая rseq > N — соединение успешно4096
udp_in=NUDP: если входящих пакетов > N — успех1

Стратегия из нескольких фаз

Одна стратегия может включать несколько инстансов с одинаковым strategy=N. circular проходит весь план и выполняет все инстансы, у которых номер совпадает — по порядку.

--lua-desync=circular:fails=1:time=300
--lua-desync=fake:blob=fake_default_http:repeats=4:strategy=1   # фаза 1
--lua-desync=multisplit:pos=2:seqovl=211:strategy=1             # фаза 2
--lua-desync=multidisorder:pos=host:strategy=2:final

Для стратегии 1 последовательно выполнятся fakemultisplit.

Форматирование в config

Параметры внутри NFQWS2_OPT="..." можно переносить на новые строки и делать отступы — shell разбирает их как обычные пробелы:

NFQWS2_OPT="
--filter-tcp=443 --filter-l7=tls <HOSTLIST> --payload=tls_client_hello
--out-range=-d1000
--in-range=-s5556
--lua-desync=circular:fails=1:time=300:retrans=3:nld=2
  --lua-desync=fake:blob=fake_default_http:repeats=4:strategy=1
  --lua-desync=multisplit:pos=2:seqovl=211:strategy=1
  --lua-desync=multidisorder:pos=host:strategy=2:final
--new
"

Пример

--in-range=-s5556
--out-range=-d1000
--lua-desync=circular:fails=1:time=300:retrans=3:nld=2
--lua-desync=multisplit:pos=2:strategy=1
--lua-desync=fake:blob=fake_default_http:strategy=2
--lua-desync=multidisorder:pos=host:strategy=3:final
  • fails=1 — переключить стратегию после 1 неудачи
  • time=300 — сбросить счётчик если последняя неудача была > 5 мин назад
  • retrans=3 — неудача = 3 ретрансмиссии
  • nld=2 — ключ хоста = 2-уровневый домен (google.com)
  • final на стратегии 3 — остановить ротацию на ней

Как работает

  1. Пакет приходит в circular с ctx
  2. circular берёт план (все подчинённые инстансы) и отменяет нормальный цикл C
  3. Проверяет детектор неудач/успеха для текущего соединения
  4. Если неудач >= fails — переходит к следующей стратегии (N % total) + 1
  5. Если достигнута final-стратегия — ротация останавливается
  6. Выполняет только инстансы с strategy=текущая

Состояние (номер стратегии, счётчик неудач) хранится per-host в глобальной таблице autostate и переживает отдельные соединения.