Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Комбинирование листов антизапрета #3

Open
burjuyz opened this issue Jan 24, 2024 · 10 comments
Open

Комбинирование листов антизапрета #3

burjuyz opened this issue Jan 24, 2024 · 10 comments

Comments

@burjuyz
Copy link

burjuyz commented Jan 24, 2024

photo_2024-01-23_20-08-25
Постараюсь тут объяснить мысль, но лучше бы связаться с тобой в телеграмме, найди меня плиз.

У нас есть geoip:ru с РФ сайтами, которые мы пускаем в директ.
Есть остальной зарубежный трафик, который мы пускаем в прокси.

При этом, среди geoip:ru сайтов, есть сайты, которые заблокированы РКН (список антизапрет). Но в этом списке много сайтов, которые не в РУ зоне и мы их и так пускаем в прокси.

Так вот, нам нужно взять небольшую часть сайтов, заблокированных РКН в зоне РФ и пускать их также через прокси. Иначе, у нас сейчас часть сайтов не будет открываться.

Вариантов 2:

  1. Добавить список антизапрета полностью выше других правил и пустить его через прокси, но там 600к строк, а нам они все не нужны.
  2. Взять только кусок из этих правил, который нам нужен (синий на диаграмме) и пустить его в прокси. Допустим, там будет не 600к строк, а 100к. и файл будет весить не 3мб, а 500кб
@Dunamis4tw
Copy link
Owner

Dunamis4tw commented Jan 24, 2024

Не совсем хотелось бы переходить в телеграм. Тем более, вдруг кому-нибудь будет полезно наше обсуждение и решение некоторых вопросов.
Я проблему вашу понял, но мне нужно уточнить пару вопросов:

  1. Я правильно понял, что вы хотите пускать в прокси весь трафик, кроме IP адресов, принадлежащих России? И так как некоторые IP адреса, которые есть в geoip блокаются РКН'ом, вы хотите их оттуда исключить?

  2. Что из себя представляет geoip:ru? Можно источник, откуда вы его берёте? Он там постоянно обновляется?

  3. Если нет необходимости каждый раз подгружать актуальный geoip, то можно очень просто вытащить содержимое этого geoip, удалить из него лишние IP адреса (которые можно взять у того же rublacklist - "Cписок IP-адресов") и сгенерировать один rule-set. Нужно будет создать два списка: include-ip-ru.lst и exclude-ip-ru.lst, где в первом нужно будет положить IP адреса вытащенные из geoip:ru, а во втором IP адреса rublacklist. Source файл для генерации второго списка будет выглядеть следующим образом:

[
  {
    "url": "https://reestr.rublacklist.net/api/v3/ips/",
    "contentType": "JsonListIPs",
    "category": "ru",
    "isExclude": true
  }
]

А достать ip из geoip можно с помощью того же sing-box'а:
sing-box geoip export ru

либо с помощью mmdbinspect:
mmdbinspect --db "path/to/geoip.db" 0.0.0.0/0

  1. Если необходимо, чтоб программа каждый раз брала актуальный geoip, то мне нужно написать очередную функцию, которая будет парсить geoip.db и составлять список, тогда можно будет полностью автоматизировать генерацию итогового rule-set'а, примерно таким конфигом:
[
  {
    "url": "https://reestr.rublacklist.net/api/v3/ips/",
    "contentType": "JsonListIPs",
    "category": "ru",
    "isExclude": true
  },
  {
    "url": "https://url.to/last/geoip.db",
    "contentType": "GeoIP", // Парсинг GeoIP не реализован
    "category": "ru"
  }
]
  1. Ну и чисто ради интереса вопрос. Почему вы решили пробрасывать весь трафик в прокси? Не проще ли в прокси кидать только заблоченные сайты, а всё остальное отправлять напрямую?

@burjuyz
Copy link
Author

burjuyz commented Jan 24, 2024

Артем, в первую очередь большое спасибо Вам, за всегда развернутые ответы.
Постараюсь также ответить на Ваши.

  1. да верно.
  2. https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-ru.srs - список обновляемый именно поэтому ранее я писал ишью чтоб можно было смотреть что включено в srs файлах.
    Также есть официальный список geoip.db:
    https://github.com/SagerNet/sing-geoip/releases - обновляется раз в 2 недели, но он общий и содержит адреса geoip-ru

Вот, например, неофициальный. Обновляется раз в сутки без проверки на то, есть там новые данные или нет:
https://github.com/lyc8503/sing-box-rules/releases

или вот:
https://github.com/Loyalsoldier/v2ray-rules-dat/releases - в формате .dat
3. лучше наверное реализовать 4 сценарий по одному из предложенных вариантов из п.2 возможно вы увидите наиболее подходящий вариант.
4. отличный вариант, а он разберет файл geoip-ru.srs, или из п.2.
5. помимо заболоченных сайтов РКН есть также и другие которые нужны людям (чатжпт, бард, medium и прочие и прочие)

@zaskochill
Copy link

Спасибо за реализацию скрипта! Вариантов есть несколько, вот пример двух из них:

  1. Делаем облегченный вариант geoip:ru без заблокированных адресов
  2. Пускаем весь geoip:ru в директ и сверху прописываем правило какие адреса пускать с прокси. В данном случае, это пересечение двух списков (например, geoip:ru и Антизапрет). В данном случае, geoip:ru мы можем обновлять хоть каждый день, а дополнительный список на прокси подкидывать на сервер раз в 2 недели.

Соответсвенно, сначала необходимо спарсить из общего geoip файла только нужный нам кусок (:ru, .ir или любой другой) и уже потом с этим списком работать

2024-01-24 21 23 57
2024-01-24 21 24 29

@Dunamis4tw
Copy link
Owner

Теперь я понял для чего вам понадобилось парсить srs) В целом, да, неплохо бы научиться парсить srs, но на данный момент проще всего будет распарсить geoip.db. Да, там много стран помимо ru, но это не проблема. Парсер можно какой угодно написать.

Тут обнаружилась другая проблема, куда посерьёзней. Дело в том, что в geoip.db указываются в основном не единичные IP-адреса, а целые подсети, и далеко не маленькие. А в списках rublacklist в основном единичные IP адреса указаны. Как в таком случае исключать из подсетей один ip-адрес?

  1. Полностью убирать всю подсеть? - Тогда возможно очень много адресов исключится.
  2. Делить сеть на подсети, чтобы исключить один адрес? - Тогда у нас geoip список вырастет в разы, да и алгоритм написать тоже придётся постараться.

Скорее всего, лучшим вариантом будет сделать менее оптимизированный, но более простой в реализации способ. Тем более, раз вы решаете использовать список антизапрета, не думаю что вас волнует производительность))
Просто в конфиге сделать рулсеты в следующем порядке:

  1. Рулсет Антизапрета -> proxy
  2. Рулсет Geoip -> direct
  3. Default -> proxy

И что насчёт того, что вы хотите заворачивать всё в проксю, и только РУшные адреса напрямую. Считаю что у этого подхода есть несколько минусов:

  1. Бо́льшая часть всего интернет-трафика будет идти через прокси, что увеличит нагрузку на сервер с прокси, а также замедлит сёрфинг в интернете из-за того что скорость интернета через прокси будет меньше. (Я тестил скорость мобильного интернета с sing-box'ом и без, и хотя сервер у меня гигабитный, почему то скорость через мобильную сеть с включенным sing-box'ом заметно снижает скорость)
  2. Некоторые сайты, ориентируются по вашему IP, чтобы определить ваш регион, например тот же ютуб начнёт показывать вам рекламу (в России же её отключили)
  3. У меня точного подтверждения нет, но думаю что далеко не все российские сайты хостятся на российских адресах. При этом настроить фильтр, что можно зайти на их сайт только с российских адресов им никто не мешает. С вашим подходом вы не зайдёте на такие сайты.
  4. Игры, особенно шутеры, которые требуют минимальный пинг. Лишний посредник в виде прокси сервера явно добавит десяток, а то и сотню миллисекунд к общей задержке.

Я сам настроил у себя так, что отправляю в прокси только указанные мною домены. IP вообще не трогаю, т.к. не вижу смысла. Поэтому, у меня уже накопился небольшой список самых часто посещаемых мною сайтов. В скором будущем планирую начать собирать так называемый список "токсичных" сайтов, где будут указываться домены сайтов, которые не были заблокированы РКН'ом, но при этом они сами блокируют доступ к себе с российских IP. Т.е. сюда попадут все те самые ЧатGPT, intel.com и т.д. Придётся только такой список собирать, пополнять и актуализировать самому, т.к. нигде подобных готовых списков мною найдено не было, за исключением toxic-repos, который и был взят за основу для составления списка "токсичных" сайтов.
В итоге получится два основных списка:

  1. Рулсет Антизапрета -> proxy
  2. Рулсет Токсичных сайтов -> proxy
  3. Default -> direct

@zaskochill
Copy link

zaskochill commented Jan 24, 2024

Действительно, самый оптимальный способ, это просто пустить список с заблокированными ресурсами в РФ выше остальных и не делать никаких сложных списков. Так это сейчас и реализовано. Просто планировалось именно уменьшить в размере список Антизапрета/ Антифильтра / Роскомсвободы или других аналогов. Условно, сейчас список весит 3мб, а мог бы весить 500кб. Не проблема и все 3мб оставить в правилах, как есть.

И мы сейчас говорим лишь о небольшом куске правил из общего списка. Конечно, сверху мы можем надстраивать дополнительные правила. Нам никто не мешает пустить в DIRECT youtube, twitch и другие ресурсы, которые сжирают трафик, плюс, к тому же избавимся от рекламы на этих ресурсах.

Эти списки "ДИРЕКТА" идут уже отдельно и не относятся конкретно к задаче уменьшить список заблокированных в РФ сайтов для синг-бокса). Схема роутинга на деле может быть масштабирована куда больше, чем на блок-схемах выше в примере.

Задача была просто оптимизировать в размере то, что уже используется)

@Dunamis4tw
Copy link
Owner

В итоге, к какому решению мы пришли? Если вы хотите исключать из geoip адреса из антизапрета, надо решить проблему с сетями. Приведу пример. В списках РКН имеется ip адрес: 194.84.56.170. Также, в списках geoip имеется подсеть 194.84.0.0/16. Как можно заметить, данный хост принадлежит этой подсети, следовательно из всей подсети необходимо исключить этот один IP адрес. Как преобразовать запись 194.84.0.0/16 так, чтобы в итоге из всех IP адресов в подсети только один был исключён?
Переделывать сеть в список одиночных IPшников - бред полный, т.к. одна только подсеть увеличит итоговый файл в разы.
Разбивать сеть на подсети? Тогда тоже получится не мало подсетей.
Я не вижу варианта лучше, чем то что у вас есть сейчас)

Можно поинтересоваться, как вы собираетесь уменьшать в размере список антизапрета? У меня есть одна мысль по этому поводу. Я как то писал программу, которая в течении 2 недель сканировала все домены из антизапрета. Вначале, программа смотрела какие IP адреса принадлежат домену (A-записи на ДНС сервере). Если в ДНС нет таких записей нет, домен добавлялся в список "Домены без IP". Остальные же домены пропрялись на предмет наличия веб сервера, а именно проверялось, слушаются ли 80 и 443 порты по данным IP адресам. Если веб сервер не был найден, домен попадает в список "Домены без веб-сервера". Если же веб сервер находится, то домен добавляется в общий файлик, куда добавляется вся информация о итогах скана. В итоге, имеется 2 списка доменов, которые можно смело исключать из списков антизапрета. В общей сложности, около 73к строк из ~400к получится сократить.
Плюс, не забываем про исключения регулярками, которые также убирают много доменов, где в названии встречается казинo, трaва, поpнуха и т.п.
В итоге, только с регулярками 400к строк превращаются в 325к, а со списком нерабочих сайтов выходит 277к строк.
Пока результаты сканирования я никуда не загружал, в скором времени постараюсь создать репозиторий, где будут вообще всевозможные списки.

@zaskochill
Copy link

Пока точно не знаю, что лучше использовать.
Мы же можем брать список IP адресов (любой список с заблокированными сайтами) и проверять подходит ли каждый IP адрес к одной из подсетей из geoip.db. Если подходит— оставляем. Таким образом, получаем список пересечение двух списков. Для работы с адресами на python есть библиотека ipaddress. Вчера набросал простой скрипт, в целом, он работает, но на больших списках парсинг будет делаться очень долго. Если взять список geoip:ru, там почти 17к строк. Если взять список блокированных IP адресов, там также десятки тысяч строк.
Скрипт на python будет обрабатывать информацию крайне долго. Возможно на GO это будет как-то быстрее, я с ним не знаком.

Плюс, у того же антифильтра есть списки с объединенными адресами, так список становится уже куда меньше по размеру. Возможно будет быстрее работать с таким списком. (allyouneed.lst:

1706285379670

Также, есть еще одна "народная версия" списка:
https://community.antifilter.download

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

@Dunamis4tw
Copy link
Owner

Dunamis4tw commented Jan 27, 2024

В общем, релизнул новую версию v1.3.0, в которой допилил нормальную проверку на вхождения IP адресов в сети, чтобы правильно исключать их (раньше было тупое сравнение строк). Более подробно как оно теперь исключается написал в примечаниях к релизу. Но если грубо говоря, он ищет любое совпадение адресов/сетей в включающем списке с адресами/сетями исключающих адресов. Т.е. в вашем случае, он исключит любые совпадения закрашенной области:

image

Что по производительности... Взял включающий список geoip:ru с 17к строками и исключающий список ip.lst с ~400к строк. На моём ПК (R7 5700X) исключение занимает чуть меньше 1 минуты. Довольно долго получается, и дольше всего занимает проверка всех 17к сетей на включение в них одного из 400к IPшников. И как раз на этой проверке больше всего IP сетей исключается из geoip:ru. В итоге получается около 15.5к записей.

Данную операцию явно можно ускорить, использовав горутины, которые будут не в одном потоке всё это обрабатывать. Но пока что я не достаточно с ними поработал, чтобы мог сразу всё правильно сделать. Хотя вроде как ничего сложного нет)

Парсинг geoip я ещё не реализовывал, так что вам необходимо самим его преобразовать в обычный список, он должен быть "Включающим" (include-ip-geoip.lst), а исключающий можно автоматически качать с помощью source файла:

[
  {
    "url": "https://antifilter.download/list/ip.lst",
    "contentType": "DefaultList",
    "category": "geoip",
    "isExclude": true
  }
]

За народную версию списка спасибо, не замечал как то его раньше. Посмотрю что с ним можно будет сделать.

@zaskochill
Copy link

zaskochill commented Jan 27, 2024

Супер! Спасибо за релиз, будем изучать.
Можно чуть более подробно рассказать как мы работаем со списками, чтобы найти их пересечения или исключения?

Думаю, многим будет полезно для понимания. Прикрепляю картинку для примера:

spiski

В данном случае, имеем 2 списка:
— Список 1 (на диаграмме зеленого цвета)
— Список 2 (на диаграмме красного цвета)

Как нам на данном примере получить область (1) — это СПИСОК1 за вычетом пересечения со СПИСКОМ2?

spiski1

Как нам получить область (2) — это СПИСОК2 за вычетом пересечения со СПИСКОМ1?

spiski2

И последнее, как нам получить область (3), как перечение первого и второго списка?

spisok3

На примере с geoip:ru и списками блокировок нам, по-хорошему, находить как раз пересечение двух списков, чтобы добавить его в исключение на —> PROXY. Или мы сейчас не можем найти пересечение двух списков? только исключение одного из другого? То есть, чтобы найти их пересечение, нужно будет найти исключение второго списка из первого и потом получившийся список исключить из первого полного? Не можем сразу найти пересечение?

Спасибо.

@Dunamis4tw
Copy link
Owner

Dunamis4tw commented Jan 28, 2024

Да, вы правильно поняли, сразу найти пересечение двух списков не получится, потому что программа может только исключать пересечение одного списка из другого.

Можете пояснить, зачем вам находить пересечение?

Вам же достаточно составить всего 1 список, и направить его в директ, а весь остальной трафик пускать в прокси:

  1. Рулсет GeoIP:ru с исключёнными из него IP'шниками Антизапрета -> direct
  2. Default -> proxy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants