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.com → google.com при nld=2) | без обрезки |
reqhost | Не работать, если hostname неизвестен (только IP) | выкл. |
Параметры на подчинённых инстансах
| Параметр | Описание |
|---|---|
strategy=N | Обязательно. Номер стратегии, начиная с 1, без пропусков |
final | Финальная стратегия — ротация на ней останавливается |
Параметры standard_failure_detector
Передаются прямо в circular (не в подчинённые инстансы).
TCP
| Параметр | Описание | По умолчанию |
|---|---|---|
retrans=N | Кол-во ретрансмиссий = неудача | 3 |
maxseq=N | Считать ретрансмиссии только до этой relative sequence | 32768 |
reset | Слать RST ретрансмиттеру (ускоряет разрыв зависшего соединения) | выкл. |
inseq=N | Входящий RST считается неудачей только до этой rseq | 4096 |
no_rst | Отключить триггер по входящему RST | выкл. |
no_http_redirect | Отключить триггер по HTTP-редиректу DPI | выкл. |
UDP
| Параметр | Описание | По умолчанию |
|---|---|---|
udp_out=N | Неудача если исходящих пакетов >= N | 4 |
udp_in=N | Неудача если входящих пакетов ⇐ N | 1 |
Параметры standard_success_detector
| Параметр | Описание | По умолчанию |
|---|---|---|
maxseq=N | TCP: если исходящая rseq > N — соединение успешно | 32768 |
inseq=N | TCP: если входящая rseq > N — соединение успешно | 4096 |
udp_in=N | UDP: если входящих пакетов > 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 последовательно выполнятся fake → multisplit.
Форматирование в 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 — остановить ротацию на ней
Как работает
- Пакет приходит в
circularсctx circularберёт план (все подчинённые инстансы) и отменяет нормальный цикл C- Проверяет детектор неудач/успеха для текущего соединения
- Если неудач >=
fails— переходит к следующей стратегии(N % total) + 1 - Если достигнута
final-стратегия — ротация останавливается - Выполняет только инстансы с
strategy=текущая
Состояние (номер стратегии, счётчик неудач) хранится per-host в глобальной таблице autostate и переживает отдельные соединения.