Нужна помощь программистов с оптимизацией PAC-файла

Не только на питоне это делается ProxyAutoConfig.cpp - mozsearch

Я вижу несколько вариантов:

  1. разбить скрипт на несколько скриптов: отдельный скрипт для .ru зоны, отдельный для .com, отдельный для .org и т.д. Подгружать динамически в зависимости от запрашиваемого домена
  2. хранить в файле хеши в бинарном виде
  3. хранить в файле бинарный бор:
    Если в списке домены “aaa”, “aab”, “aba”, “caa” то нужно хранить структуру вида
    {“a”: {“a”: {“a”: true, “b”: true}, “b”: {“a”: true} }, “c”: {“a”: {“a”: true} } }
  4. сжать список алгоритмом хаффмана (вариация бора когда преждевременно анализируем потенциально самые частоиспользуемые ребра)
    Плюсы подхода 3 и 4 это то что мы явно не храним весь список и нам не нужно его полностью восстанавливать для проверки на вхождение. При этом не возможны коллизии.

Немного оффтоп. Но с чем связаны такие строгие ограничения на IE7 и Windows XP?
Казалось бы сами заблокирвоанные сайты не очень умеют с ним работать.
Для таких старых устройств есть смысл делать обход блокировки средствами роутера или гейтвея или через операционную систему, не через браузер

Такой возможности нет, PAC-файлы не могут загружать сторонние ресурсы.

Только ASCII 7-бит, не все браузеры поддерживают не-однобитные кодировки.

Сервисом до сих пор пользуются со старых компьютеров, не хотелось бы ломать доступ без сильной на то необходимости.
Но даже если ориентироваться на Windows 7 и его версию IE, там тоже не получится использовать современные технологии.

Я не знаю насколько моё мнение важно, но
Мне кажется что если выбирать между

  1. поддерживать для 99% пользователей (а есть ли статистика?) браузер которых выпущен в последние 2 года
  2. не поддерживать из-за 1% пользователей которые пользуются морально устаревшими технологиями

всегда нужно выбирать первое

В текущем виде выглядит расточительно, нужно придумывать алгоритм паковки данных.
Я думал для сжатия IP-адресов реализовать Elias gamma coding.

Пользователи, добавляющие PAC-файл в ОС, начинают использовать его в браузере ОС (старые версии IE и wininet, основанный на нём).

Как насчёт взять GitHub - LZMA-JS/LZMA-JS: A JavaScript implementation of the Lempel-Ziv-Markov (LZMA) chain compression algorithm (декомпрессор весит 6.8 КБ) и зипануть все домены?

кстати, а если выделить в общую кучу Cloudflare, по идее его может быть довольно много (из-за казино), и заменить общим правилом “если адрес ресолвится в клаудфлер, то проксировать”

Нельзя ли на сервере проверять домены по тому же фильтру?

Здесь уместен вопрос. Дергается ли прокси пак каждый раз при обращении к URL или есть какое-то кэширование результатов ? Может в разных броузерах по разному ?
Если на каждое обращение, то будет тяжеловато, особенно на старых компах.
lzma 1 мб в нативном варианте разжимается около 50 мсек даже на 12700K
JS - сразу в несколько раз минуc. Если вызов идет при каждом дергании URL, на селероне 15 летней давности будете ждать секунды, если не 10+ секунд, а ноут будет выть
Сюда же в копилку гораздо более слабая оптимизация JS на старых броузерах типа iE

Потому есть предложение дифференцировать размер proxy.pac в зависимости от user-agent. Если броузер не налагает жестких ограничений, использовать лайтовую версию

Скрипт исполняется целиком при инициализации контекста js (на каждый поток/процесс, полагаю), в это время можно однократно выполнить какую-то затратную по CPU/RAM операцию. Затем на каждый запрос вызывается функция, которая возвращает результат необходимости проксирования.

По мере прочтения темы, появилось несколько мыслей:

  1. Если проблема ограничения размера pac-файла в 1 MB касается только браузеров на основе Chrome, можно ли автоматически собирать отдельную неурезанную версию pac-файла для свежих Firefox, где таких ограничений нет?

  2. Не совсем понятно, зачем привязываться к ограничениям в Windows 7 и её версии IE, если сам IE не способен нормально отобразить современные сайты?
    Изобретать способ уменьшения размера pac-файла для браузера, который не может отобразить большую часть разблокированных сайтов, выглядит нелогичной тратой людских ресурсов, которые могли бы быть использованы в других вопросах касательно обхода блокировок.

Там еще вроде бы есть ограничения на RAM. Разжать и все хранить в виде JS переменных может быть тоже проблемно

Я ранее предлагал эту идею насчет дифференциации размера в зависимости user-agent.Но думаю не взлетит из-за излишней нагрузки на сервер.Здесь важно понимание того до какого верхнего предела по кол-ву записей можно достигнуть.Если их сейчас 1,7, то на следующий год может оказаться в три раза выше.Рост в геометрической прогрессии( хуже в экспоненциальной)

Нагрузка ложится на прокси, и она не особо зависит от размера proxy.pac
Она зависит от количества значимых доменов. Всякий мусор типа проституток новосибирска практически никому не интересен, а он как раз и составляет основу.
Сам веб сервер, выдающий прокси пак, вообще минимален по нагрузке. Статическая выдача или простейший скрипт - разницы почти нет

У меня есть вариант, который конкретно домены жмет лучше, чем текущий. Получается около 870 KиБ данных в самом proxy.pac (считая код, нужный для распаковки). Я не пробовал включить в него IP-адреса, и не проверял, сколько он потребляет памяти; буду благодарен, если кто-то с этим поможет.

Сам код сжатия работает в Node.js (почти любой версии). Он ожидает в файле src.txt в текущей директории список доменов, и выдает готовый out.pac.

Алгоритм основан на трех идеях:

  • хосты для матчинга переворачиваются, т.е. с последнего по первый символ
  • на перевернутых хостах строится, фактически, бор, но упаковывается в RegExp
  • сам RegExp затем сжимается заменой диграмм, примерно так, как сжимаются хосты в текущем репо

compress.js (2.2 KB)

Если в качестве входных данных беру result/hostlist_zones.txt из репо, то out.pac имеет размер 875 КиБ. Прикрепляю также его, чтобы легче было тестировать потребление памяти - буду рад, если кто-то с этим поможет. На саму правильность матчинга я тестировал, но в Node.js (т.е. без учета ограничений PAC-файлов).

out.pac (874.2 KB)

Подход интересный, но regexp — точно не самое быстрое решение.

Там основная стоимость на компиляцию при первом запуске скрипта. Потом, когда функция вызывается - она дешёвая; линейная относительно длины host, если прямо заморачиваться асимптотикой.

Не знаю, насколько это приемлемо, плюс не измерял по абсолютным цифрам.

Учитывая, что сам регексп получается без бектрекинга - можно накидать простой алгоритм, который будет матчить его без именно использования RegExp. Попробую в ближайшие дни сделать.

Идея на подумать:

Произвольно руками посмотрел на cloudfront в списке, его есть смысл пытаться резолвить и выкидывать строки не резолвящиеся в какой-либо IP. Одного этого уже может быть достаточно на какое-то время

А есть какой-то сакральный смысл в том, чтобы использовать исключительно один только PAC-файл? Если добавить в инструкцию для пользователей, кроме пункта “укажите в настройках URL PAC-файла” второй пункт “а в другом месте настроек укажите адрес нашего DoH-сервера” - дальше можно реализовать ту же самую подмену IP, как и в VPN-версии, а весь PAC-файл при этом сведётся к нескольким строчкам кода, проверяющим попадание отресолвленного IP для домена в наш подменный диапазон.