Уже обсуждалось несколько раз. Невозможно.
Итоговую версию передает сервер, а не клиент
@bolvan в свежем zapret-win-bundle winws2 поломался, не стартует, взял из релизов запрета2, там ок.
уже исправлено.
новых фич больше не собираюсь делать пока , все уже сделал, что хотел
надеюсь, теперь будут одни лишь притирочки
последний релиз злосчастный какой-то
проблема за проблемой, все по мелочи, но критически. 4 раза отзывал
del
В качестве тренировки сделал динамическую менялку sni, в зависимости от совпадения по префиксу ставится свой домен в sni. Если кому надо в сборки, можете пользоваться.
(несколькими постами ниже есть версия свежее)
slib.lua (4,8 КБ)
Пример файла test.list, матчит первый подходящий в порядке как записано:
127.0.0.0/8 domain.local
2606:4700::/32 one.one.one.one
::/0 google.com
0.0.0.0/0 google.com
# any comment
Пример использования:
--lua-init=@lua/zapret-lib.lua
--lua-init=@lua/zapret-antidpi.lua
--lua-init=@slib.lua
--payload=tls_client_hello
--lua-desync=slib_tlsmod_by_prefix:blob=fake_default_tls:targetblob=dynfake:filename=test.list
--lua-desync=fake:blob=dynfake:ip_ttl=1:ip6_ttl=1
Для отслеживания изменений файла читается содержимое файла с суффиксом .key, например для test.list будет читаться test.list.key. Если содержимое key-файла отличается от прошлого прочитанного значения, test.list перечитается и распарсится целиком заново.
Несколькими постами ниже есть версия, в которой отслеживаются изменения
test.listнапрямую без key-файла.
@bolvan, исходя из задачи есть несколько вопросов:
- Спасибо за гибкий фреймворк

- Как правильно отслеживать изменение кастомных файлов настроек? Не нашел в api ничего похожего на stat по файлу, чтоб взять последнее время изменения, пока изобрел такой вот костыль с key-файлом.
- Есть очень тяжелая задача по парсингу файла при его изменениях, которую не хотелось бы делать во время десинка, но никакого другого способа вынести в фон эту работу не вижу. Возможно стоит что-то предусмотреть в api для такого?
В lua сильно ограничены встроенные файловые операции. Там нет ничего, кроме create/read/write/delete.
Даже chdir и mkdir нет.
stat - ok, вынесу в api. действительно для внешних файлов будет норм.
по времени + размеру надо завязываться и кэшировать в памяти
либо собирать динамику и пользоваться lfs
UPD. См stat() luacall. На современных unix fs mtime может быть дробным, на старых fs и на винде - только секунды, только целое. Поэтому надежнее завязываться на mtime+size
От stat на каждый пакет он не умрет, но читать и парсить придется синхронно с пакетом. Иных событийных моделей не предусмотрено, как и многопоточности - в lua ее просто нет.
Если файл меняется нечасто - проблем не должно быть. В nfqws с листами точно так же сделано. Проверка модтайма и чтение по событию прихода пакета
Благодарю, попробую. Там еще и band добавился, которого мне как раз не хватало, чтобы нормальный матчинг ipv6 префиксов сделать. Костыли на u32 выглядят страшно)
Жаль еще нет quicmod как аналог tlsmod, но quic так менять похоже миссия невыполнима
а зачем нужно динамически менять SNI и по какому префиксу? Если можно, объясните на примере.
Тут каждому виднее. У кого-то может быть половина интернета в 16кб блоке, и на каждую подсеть каждого популярного хостинга свой белый список доменов, общий sni на все не прокатывает. Например, для cloudflare подсетей один sni, для akamai другой sni, для hetzner третий и т.д. Можно сделать десятки фильтров по ipset прямо в аргументы запуска nfqws и десятки разных блобов, а можно вот таким скриптом быстро добавлять еще белые домены на подсети. Изначально это больше проба пера. Мне бы хотелось, чтобы мой скрипт вообще никогда никому не понадобился для решения каких-то проблем, но реальность может быть иной
Выполнима, но сложно. Все придется переконструировать и перешифровывать
Обновил на stat, проверил, больше key-files не нужны.
(для zapret2 >=0.9.1) slib.lua (4,8 КБ)
А вот от band пришлось отказаться - он аллоцирует память на каждый вызов в отличие от bitand, что для матчинга префиксов может оказаться губительно.
В lua все так. Там любой чих аллоцирует память, вызовы C кода тоже тратят ресурсы.
Особенно что касается immutable strings.
band на 16 байт ipv6 адреса - это такая смертельная затрата, когда каждая конкатенация делает тоже самое ? таблицу масок подсетей можно пред-создать, чтобы не считать каждый раз
Профайлером смотрел, график делал, top сравнивал.
lua там занимает не слишком значительную часть, основа нагрузки - перенаправление трафика.
C код - минимально, lua - 95% от C+LUA, поэтому cutoff и важны, но еще важнее iptables. монстр - это редирект, мелкий монстр - это lua, а C - на закуску
Именно профайлером я не проходился, изучил C-реализации, и bitand на вид выглядела как без аллокаций. Может там пуш в lua-стек и аллоцирует чего-то из своего gc пула, но там за короткий промежуток эти страницы должны эффективно переиспользоваться. У band на самом деле целых две аллокации: явный malloc для dest строки и неявная аллокация при копировании в стек lua. Вторая может как-то и переиспользуется, а вот первая будет вообще всегда. На этом фоне для ipv6 4 вызова bitand для уже разобранных и готовых в памяти u32 чисел должны себя показать значительно лучше на сотнях префиксов. А ipv4 однозначно в выигрыше. Были бы в luajit явные битовые операции, еще бы и jit ощутимо помог, но увы.
При желании большей оптимизации можно вообще 4 u32 превратить в u48+u48+u32. Еще один вызов сэкономим
Это реально мелочь, не принципиально.
В скриптовых языках что-то оптимизировать до такой степени стоит при реальных выявляемых проблемах, а если считать каждый аллок, надо сразу на C клепать. Говорю же - это мелочь на фоне редиректа. И неизвестно еще что дороже - пару аллоков или множественные вызовы C кода вместо одного вызова. Надо сперва доказать преимущество в тестовом примере. В цикле сделать миллион раз под time. intercept=0, чтобы вышло
битовые операции есть в lua 5.3+, но там в разы упадет скорость из-за отсутствия jit
Попарсил все 54 упоминания hostlist в мануале и не понял, такое поведение - норма:
Summary
profile 3 (noname) include hostlist /tmp/dvtws2/lists/my-hosts.txt (empty)
hostname: self.events.data.microsoft.com
discovered l7 protocol
discovered hostname
desync profile search for tcp ip=52.168.117.169 port=443 icmp=255:255 l7proto=tls ssid=‘’ hostname=‘self.events.data.microsoft.com’
desync profile 3 (noname) matches
desync profile changed by revealed l7 protocol or hostname !
?
множественные фейки указываются видом blob=1:blob=2, да?
нет
Если в профиле все листы одного типа пусты, это равносильно их отсутствию
Фильтрация по листам
Если имеются фильтры по хостлистам, и есть хотя бы один домен в любом хостлисте или указан автохостлист, то профиль никогда не будет выбран при отсутствующем имени хоста. Случай, когда нет автохостлиста, а все файлы листов пустые, приравнивается к отсутствию фильтра по хостлисту.
Я, наверное, мало дал вводной информации, думал части лога достаточно. Суть в чём, есть профиль с фильтром по именам хостов: –hostlist=/tmp/dvtws2/lists/my-hosts.txt. Если он пустой (нет в нём записей), то по какой-то причине он применяется к проходящему трафику. Если туда вбить любое имя, то профиль не применяется. Странно ещё и то, что он не первый в списке и не последний:
Summary
profile 1 (noname) include hostlist /tmp/dvtws2/lists/list-youtube.txt
profile 2 (noname) include hostlist /tmp/dvtws2/lists/list-youtube.txt
profile 3 (noname) include hostlist /tmp/dvtws2/lists/my-hosts.txt
profile 12 (noname) include hostlist /tmp/dvtws2/lists/zapret-hosts.txt.gz
profile 4 (noname) include ipset /tmp/dvtws2/lists/cdn-AKAMAI-ASN1.txt (ipv4)
profile 5 (noname) include ipset /tmp/dvtws2/lists/cdn-Amazon.txt (ipv4)
profile 6 (noname) include ipset /tmp/dvtws2/lists/cdn-Cloudflare.txt (ipv4)
profile 7 (noname) include ipset /tmp/dvtws2/lists/cdn-Constant.txt (ipv4)
profile 8 (noname) include ipset /tmp/dvtws2/lists/cdn-Contabo.txt (ipv4)
profile 9 (noname) include ipset /tmp/dvtws2/lists/cdn-Datacamp.txt (ipv4)
profile 10 (noname) include ipset /tmp/dvtws2/lists/cdn-Hetzner.txt (ipv4)
profile 11 (noname) include ipset /tmp/dvtws2/lists/cdn-Oracle.txt (ipv4)
Так о чем и толк
–hostlist=empty_file
это все равно что без фильтра.
нет такого, что пустой лист означает НИЧЕГО. Наоборот, он значит ВСЕ