Files
Leonid PershinandClaude Opus 5 e6186ba6df
build / build (push) Successful in 20s
feat: один апдейтер на несколько репозиториев
update-geodata.sh теперь ходит по списку SOURCES (строка «URL-базы|имя»),
а не по одной базе: ipcheck.dat и оба discord-.dat обновляются за один
запуск и с одним перезапуском сервиса. Старый вызов с DEST продолжает
работать — каталог берётся из него.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 09:31:14 +03:00

16 KiB
Raw Permalink Blame History

discord-geodata

Домены и сети Discord, собранные в geosite.dat и geoip.dat для Xray/3x-ui — плюс те же списки в форматах sing-box, Clash/mihomo, AdGuard и обычным текстом.

Списки не выдумываются: рукописная база лежит в data/discord-base.txt и data/ip/discord-base.txt, всё остальное tools/sync.py тянет из публичных апстримов (см. Апстримы) и раскладывает по отдельным категориям.

Категории

Домены (geosite.dat):

Категория Что внутри
discord всё вместе — то, что обычно и нужно в роутинге
discord-base рукописный список: домены Discord и его проектов
discord-metacubex из MetaCubeX meta-rules-dat
discord-itdoginfo из itdoginfo/allow-domains
discord-youoops из you-oops-dev/ipranges-singbox, включая имена голосовых узлов

Сети (geoip.dat):

Категория Что внутри Ограничения
discord все безусловные списки вместе
discord-base адреса, снятые резолвом доменов
discord-legiz адреса голосовых узлов (legiz-ru/sb-rule-sets)
discord-youoops диапазоны сетей (you-oops-dev/ipranges-singbox)
discord-vernette-udp голосовой трафик (vernette/rulesets) udp, порты 50000-50099
discord-itdoginfo-udp-* голосовой трафик (itdoginfo) udp, свои диапазоны портов

Категории с ограничениями по протоколу и портам не входят в сводную discord: там широкие сети вроде 172.64.0.0/13 и 162.158.0.0/15, то есть пол-Cloudflare. Без ограничения по UDP-портам такое правило утащило бы в туннель кучу чужого трафика. Точные счётчики по каждой категории — в metadata.json.

Скачать

Ветка release — распакованный dist/, релизы — те же файлы архивом:

  • https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/<файл>
Файл Для чего
discord-geosite.dat Xray / v2ray / 3x-ui — домены, кладётся рядом со штатным geosite.dat
discord-geoip.dat то же для сетей, рядом со штатным geoip.dat
geosite.dat, geoip.dat те же данные под именами по умолчанию — если хотите заменить штатные файлы
*.dat.sha256sum контрольные суммы, по ним работает автообновление
xray/routing.json готовый фрагмент routing со всеми правилами
update-geodata.sh скрипт обновления для cron (см. ниже)
sing-box/site/<категория>.json, .srs sing-box, домены: исходный и скомпилированный rule-set
sing-box/ip/<категория>.json, .srs sing-box, сети — здесь же живут network и port_range
mihomo/site/<категория>.mrs, mihomo/ip/<категория>.mrs mihomo, бинарные rule-provider
clash/site/<категория>.yaml, .list Clash/mihomo, behavior: domain и classical
clash/ip/<категория>.yaml, .list Clash/mihomo, behavior: ipcidr и classical
txt/site/<категория>.txt, txt/ip/<категория>.txt просто домены и сети, по одной на строку
json/… структурированные списки с типами правил и ограничениями
adguard/<категория>.txt AdGuard Home / uBlock — если нужно блокировать, а не роутить
metadata.json, SHA256SUMS время сборки, счётчики, суммы по всем файлам

3x-ui

Положите оба файла рядом с бинарём (обычно /usr/local/x-ui/bin):

cd /usr/local/x-ui/bin
base=https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release
curl -fsSLO "$base/discord-geosite.dat"
curl -fsSLO "$base/discord-geoip.dat"
x-ui restart

Дальше в панели: Настройки → Xray → Маршруты (или прямо в JSON-конфиге). Готовые правила лежат в xray/routing.json, менять там нужно только outboundTag:

{
  "type": "field",
  "domain": ["ext:discord-geosite.dat:discord"],
  "outboundTag": "proxy"
},
{
  "type": "field",
  "ip": ["ext:discord-geoip.dat:discord"],
  "outboundTag": "proxy"
},
{
  "type": "field",
  "network": "udp",
  "port": "50000-50099",
  "ip": ["ext:discord-geoip.dat:discord-vernette-udp"],
  "outboundTag": "proxy"
}

ext:<файл>:<тег> работает и для domain, и для ip — файл ищется в XRAY_LOCATION_ASSET (по умолчанию каталог с бинарём). Тег — имя категории, регистр не важен.

Порядок правил — это приоритет: Xray берёт первое подошедшее, поэтому ограниченные по портам правила идут последними, чтобы более общие не перехватывали их раньше.

Автообновление на сервере

update-geodata.sh качает файлы, только если их sha256 разошлись с удалёнными, проверяет сумму до подмены и перезапускает сервис один раз — и только если что-то реально изменилось.

base=https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release
curl -fsSLo /usr/local/bin/update-geodata.sh "$base/update-geodata.sh"
chmod +x /usr/local/bin/update-geodata.sh
RESTART_CMD='x-ui restart' /usr/local/bin/update-geodata.sh

cron раз в сутки:

23 4 * * * RESTART_CMD='x-ui restart' /usr/local/bin/update-geodata.sh >> /var/log/discord-geodata.log 2>&1

Скрипт умеет тянуть файлы из нескольких репозиториев сразу — один cron-job вместо двух. По умолчанию это ipcheck.dat из ipcheck-domains и оба .dat отсюда; перезапуск при этом один на все файлы.

Переменная По умолчанию Значение
SOURCES три строки ниже что качать, по строке на файл: URL-базы|имя-файла
BASE_URL …/ipcheck-domains/raw/branch/release база для строк без |
DISCORD_URL …/discord-geodata/raw/branch/release база для файлов этого репозитория
DEST_DIR /usr/local/x-ui/bin куда класть файлы
RESTART_CMD пусто что выполнить после успешного обновления
TIMEOUT 30 таймаут curl, секунды

Нужны только файлы Discord — задайте SOURCES явно:

SOURCES='https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release|discord-geosite.dat
https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release|discord-geoip.dat' \
  RESTART_CMD='x-ui restart' /usr/local/bin/update-geodata.sh

Старый вызов с DEST=/путь/файл.dat продолжает работать: каталог берётся из него, а имя файла подставляется в первую строку SOURCES.

Если 3x-ui в Docker — укажите DEST_DIR на смонтированный каталог и RESTART_CMD='docker restart 3x-ui'.

sing-box

{
  "route": {
    "rule_set": [
      {
        "type": "remote",
        "tag": "discord",
        "format": "binary",
        "url": "https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/sing-box/site/discord.srs"
      },
      {
        "type": "remote",
        "tag": "discord-ip",
        "format": "binary",
        "url": "https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/sing-box/ip/discord.srs"
      },
      {
        "type": "remote",
        "tag": "discord-voice",
        "format": "binary",
        "url": "https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/sing-box/ip/discord-vernette-udp.srs"
      }
    ],
    "rules": [{"rule_set": ["discord", "discord-ip", "discord-voice"], "outbound": "proxy"}]
  }
}

network и port_range зашиты внутрь самого rule-set — отдельно в правиле их указывать не нужно.

Clash / mihomo

rule-providers:
  discord:
    type: http
    behavior: domain
    format: yaml
    url: https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/clash/site/discord.yaml
    path: ./providers/discord.yaml
    interval: 86400
  discord-ip:
    type: http
    behavior: ipcidr
    format: yaml
    url: https://gitea.hsrv.site/mrleo1nid/discord-geodata/raw/branch/release/clash/ip/discord.yaml
    path: ./providers/discord-ip.yaml
    interval: 86400

rules:
  - RULE-SET,discord,PROXY
  - RULE-SET,discord-ip,PROXY

Ограничения по протоколу и портам в форматы Clash не переносятся — в шапке таких файлов об этом написано прямо. Нужен голосовой трафик с портами — берите sing-box или Xray.

Апстримы

tools/sources.json — список источников, tools/sync.py их синхронизирует:

Источник Что берём
MetaCubeX/meta-rules-dat домены
itdoginfo/allow-domains домены и голосовые сети с портами
you-oops-dev/ipranges-singbox сети и имена голосовых узлов
legiz-ru/sb-rule-sets адреса голосовых узлов
vernette/rulesets голосовой трафик UDP 50000-50099
python3 tools/sync.py                 # синхронизировать всё
python3 tools/sync.py --only legiz     # только один источник
python3 tools/sync.py --strict         # падать, если хоть один источник недоступен

Что происходит внутри:

  • каждый источник кладётся в свой файл data/discord-<источник>.txt — так видно, кто что принёс, и можно выключить конкретный список;
  • правила с network/port_range уезжают в отдельную категорию с директивами !network и !port в шапке; если у источника таких наборов несколько, в имя добавляются порты (discord-itdoginfo-udp-19000-20000);
  • сводные data/discord.txt и data/ip/discord.txt пересобираются как список include: — руками их править бесполезно;
  • недоступный источник не обнуляет свой файл: остаются прежние данные и печатается предупреждение. Устаревший список лучше пустого;
  • источники в формате .srs скомпилированы, для них нужен бинарь sing-box (tools/fetch-tools.sh его ставит). Без него они просто пропускаются.

Файлы, которые пишет sync.py, помечены шапкой # GENERATED — файл без такой шапки скрипт не тронет. Поэтому рукописный discord-base.txt в безопасности.

Как добавить домен или сеть руками

Правьте data/discord-base.txt (домены) и data/ip/discord-base.txt (сети) — они попадут в сводные категории автоматически.

Формат доменного файла: example.com — суффикс (сам домен и все поддомены), full:example.com — точное совпадение, keyword:, regexp:, include:другая-категория. Атрибуты — через @: example.com @ads.

Формат IP-файла: 1.2.3.4 или 1.2.3.0/24 (IPv6 тоже), include:, и директивы в шапке:

!network: udp
!port: 50000-50099

Ограничения действуют на весь файл. include: разрешён только между категориями с одинаковыми ограничениями, иначе сборка упадёт: так не выйдет случайно снять «только UDP на голосовых портах» с половины Cloudflare.

Дальше:

python3 tools/build.py --check

--check ругается на дубликаты, на домены, уже покрытые суффиксом, на сети, вложенные в другие сети того же файла, на циклы в include и на конфликт ограничений.

Локальная сборка

python3 tools/build.py --check              # проверить исходники
python3 tools/build.py                      # собрать dist/
python3 -m unittest discover -s tools -t tools

Зависимостей нет — только стандартная библиотека Python 3.10+. Для .srs и .mrs нужны бинарники sing-box и mihomo; без них сборка проходит, просто эти файлы не появляются:

sh tools/fetch-tools.sh ./bin && export PATH="$PWD/bin:$PATH"

Полезные флаги: --out <каталог>, --sing-box <путь>, --mihomo <путь>, --outbound <тег> (какой outboundTag подставить в xray/routing.json).

Сборка детерминирована: одни и те же данные дают побайтово одинаковый .dat. Оба файла после записи читаются обратно и сверяются с исходными правилами.

CI

.gitea/workflows/build.yml на каждый push в main, на PR и ежедневно по cron: ставит внешние инструменты, синхронизирует апстримы, проверяет исходники, гоняет тесты, собирает dist/, скармливает оба .dat настоящему Xray и проверяет, что в скомпилированных .srs доехали протокол и порты. После этого коммитит обновлённый data/ обратно в main, обновляет ветку release и публикует релиз.

Если автокоммит в main не нужен — удалите шаг «Обновление data/ в main»: сборка от этого не сломается, просто списки в репозитории останутся прежними.

Лицензия

MIT — см. LICENSE. Списки собраны из публичных источников, перечисленных выше; лицензии апстримов смотрите в их репозиториях.