# 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`): ```sh 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`: ```json { "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 разошлись с удалёнными, проверяет сумму до подмены и перезапускает сервис один раз — и только если что-то реально изменилось. ```sh 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 раз в сутки: ```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](https://gitea.hsrv.site/mrleo1nid/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` явно: ```sh 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 ```json { "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 ```yaml 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](https://github.com/MetaCubeX/meta-rules-dat) | домены | | [itdoginfo/allow-domains](https://github.com/itdoginfo/allow-domains) | домены и голосовые сети с портами | | [you-oops-dev/ipranges-singbox](https://github.com/you-oops-dev/ipranges-singbox) | сети и имена голосовых узлов | | [legiz-ru/sb-rule-sets](https://github.com/legiz-ru/sb-rule-sets) | адреса голосовых узлов | | [vernette/rulesets](https://github.com/vernette/rulesets) | голосовой трафик UDP 50000-50099 | ```sh 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. Дальше: ```sh python3 tools/build.py --check ``` `--check` ругается на дубликаты, на домены, уже покрытые суффиксом, на сети, вложенные в другие сети того же файла, на циклы в `include` и на конфликт ограничений. ## Локальная сборка ```sh 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 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](LICENSE). Списки собраны из публичных источников, перечисленных выше; лицензии апстримов смотрите в их репозиториях.