Compare commits

..

23 Commits

Author SHA1 Message Date
GitHub Action
e57de37782 Update subnet 2026-03-23 08:08:38 +00:00
Kirill Sobakin
74cd5a4767 Feat: add mihomo MRS format 2026-03-22 00:04:43 +03:00
GitHub Action
d5ff6c38dd Update lists 2026-03-16 21:12:39 +00:00
Kirill Sobakin
ed91b10a8a Re-run 2026-03-17 00:12:08 +03:00
GitHub Action
3307c1404d Update subnet 2026-03-16 21:05:22 +00:00
Kirill Sobakin
bd6f07f971 Merge pull request #152 from itdoginfo/refactor
Refactor 16.02.2026
2026-03-17 00:05:03 +03:00
Kirill Sobakin
315d118c17 Fix: protobuf version specify 2026-03-17 00:04:20 +03:00
Kirill Sobakin
fee4746b57 Fix: fix from copilot 2026-03-16 23:54:56 +03:00
Kirill Sobakin
689a9ea755 Fix: strict and sys 1 2026-03-16 23:40:46 +03:00
Kirill Sobakin
1a6e1cf718 Feat: add links 2026-03-16 23:11:45 +03:00
Kirill Sobakin
98fb1ca2df Ref: no docker 2026-03-16 23:01:36 +03:00
Kirill Sobakin
2868f4576e Ref: no docker 2026-03-16 22:55:17 +03:00
Kirill Sobakin
76f8f79434 Ref: add protobuf 2026-03-16 21:29:55 +03:00
Kirill Sobakin
623b97ff1b Ref: deduplicate convert funcs, generate DAT with pyhton protobuf 2026-03-16 21:29:15 +03:00
Kirill Sobakin
6d441b4cbf Ref: some fixes 2026-03-16 20:48:16 +03:00
Kirill Sobakin
8ca8769a77 Ref: to API stat.ripe.net. Some fixes 2026-03-16 19:32:14 +03:00
GitHub Action
a06c1739a4 Update subnet 2026-03-16 15:18:38 +00:00
Kirill Sobakin
b8fe629d16 Feat: Add ASN Telegram. Fix meet hardcode #110 2026-03-16 18:12:46 +03:00
GitHub Action
ccedd6cfac Update lists 2026-03-16 15:03:51 +00:00
Kirill Sobakin
96e00053c4 Merge pull request #110 from DrRamm/google_meet_list
Feat: Добавлен список Google Meet
2026-03-16 18:03:29 +03:00
GitHub Action
e0d48d4e1e Update subnet 2026-03-16 08:15:30 +00:00
GitHub Action
660a70f731 Update subnet 2026-03-09 07:57:56 +00:00
DrRamm
b7ff4adda5 Добавлен список Google Meet
На основе
https://support.google.com/a/answer/1279090?hl=en
2026-01-31 17:06:39 +03:00
27 changed files with 545 additions and 528 deletions

View File

@@ -1 +1,8 @@
blank_issues_enabled: false
blank_issues_enabled: false
contact_links:
- name: Предложить домен или сервис
url: https://github.com/itdoginfo/allow-domains/discussions/categories/general
about: Добавление доменов и сервисов производится через Discussions, а не Issues.
- name: Вопрос по использованию
url: https://t.me/itdogchat
about: С вопросами в Telegram-чат.

View File

@@ -19,19 +19,40 @@ jobs:
generate-lists:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4.3.0
- name: Compile ruleset srs
- uses: actions/checkout@v6.0.2
- name: Cache sing-box
uses: actions/cache@v5.0.3
id: cache-singbox
with:
path: /usr/local/bin/sing-box
key: sing-box-1.12.25
- name: Install sing-box
if: steps.cache-singbox.outputs.cache-hit != 'true'
run: |
docker run --rm \
-v ${{ github.workspace }}/src:/app/src \
-v ${{ github.workspace }}/Subnets:/app/Subnets \
-v ${{ github.workspace }}/Russia:/app/Russia \
-v ${{ github.workspace }}/Ukraine:/app/Ukraine \
-v ${{ github.workspace }}/Categories:/app/Categories \
-v ${{ github.workspace }}/Services:/app/Services \
-v ${{ github.workspace }}/SRS:/app/SRS \
-v ${{ github.workspace }}/DAT:/app/DAT \
itdoginfo/compilesrs:0.1.22
wget -qO- https://github.com/SagerNet/sing-box/releases/download/v1.12.25/sing-box-1.12.25-linux-amd64.tar.gz | tar xz
sudo mv sing-box-*/sing-box /usr/local/bin/
- name: Cache mihomo
uses: actions/cache@v5.0.3
id: cache-mihomo
with:
path: /usr/local/bin/mihomo
key: mihomo-1.19.8
- name: Install mihomo
if: steps.cache-mihomo.outputs.cache-hit != 'true'
run: |
wget -qO- https://github.com/MetaCubeX/mihomo/releases/download/v1.19.8/mihomo-linux-amd64-v1.19.8.gz | gunzip > mihomo
chmod +x mihomo
sudo mv mihomo /usr/local/bin/
- name: Install Python dependencies
run: pip install -r requirements.txt
- name: Generate lists
run: python3 convert.py
- name: Check Russia/inside-dnsmasq-ipset
uses: itdoginfo/dnsmasq-action@0.1
@@ -81,5 +102,6 @@ jobs:
with:
files: |
${{ github.workspace }}/SRS/*.srs
${{ github.workspace }}/MRS/*.mrs
${{ github.workspace }}/DAT/*.dat
tag_name: ${{ env.TAG_NAME }}

View File

@@ -14,13 +14,13 @@ permissions:
jobs:
generate-subnet:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4.1.7
- uses: actions/checkout@v6.0.2
- name: Generate subnets
uses: actions/setup-python@v5.1.0
uses: actions/setup-python@v6.2.0
with:
python-version: '3.10'
python-version: '3.13'
- run: |
python get-subnets.py
- name: Push subnets

4
.gitignore vendored
View File

@@ -2,6 +2,8 @@ antifilter-domains.lst
uablacklist-domains.lst
zaboronahelp-domains.lst
SRS
MRS
JSON
DAT
geosite_data
geosite_data
proto/__pycache__

View File

@@ -1,22 +0,0 @@
FROM ghcr.io/sagernet/sing-box:v1.11.15 AS sing-box
FROM golang:1.25.5-alpine3.23 AS go-builder
RUN CGO_ENABLED=0 GOOS=linux go install -ldflags="-s -w" \
github.com/v2fly/domain-list-community@20251222003838
FROM python:3.12.12-alpine3.23
COPY --from=sing-box /usr/local/bin/sing-box /bin/sing-box
COPY --from=go-builder /go/bin/domain-list-community /bin/domain-list-community
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r /app/requirements.txt
WORKDIR /app
COPY convert.py /app/convert.py
CMD ["python3", "convert.py"]

View File

@@ -7,6 +7,7 @@
- Dnsmasq ipset. Для Dnsmasq в формате ipset (OpenWrt <= 21.02) `ipset=/showip.net/vpn_domains`
- Sing-box Source. Для Sing-box версии 1.11.0 и выше.
- Xray Dat. Общий файл geosite.dat с разбивкой по категориям.
- Mihomo MRS. Бинарные rule-set для Mihomo (Clash Meta). Файлы с суффиксом `_domain` для доменов, `_ipcidr` для подсетей.
- ClashX `DOMAIN-SUFFIX,showip.net`
- Mikrotik FWD `/ip dns static add name=fast.com type=FWD...`
- Kvas. Для Kvas 1.1.8 и новее. Просто отсортированный список доменов.
@@ -34,6 +35,7 @@
- Tik-Tok
- Twitter
- YouTube
- Google Meet
## Страны
### Россия
@@ -74,6 +76,7 @@
- [Kvas](https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-kvas.lst)
- [Mikrotik](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Russia/inside-mikrotik-fwd.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/russia_inside.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/russia_inside_domain.mrs)
- geosite:russia-inside
</details>
@@ -88,6 +91,7 @@
- [Kvas](https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-kvas.lst)
- [Mikrotik](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Russia/outside-mikrotik-fwd.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/russia_outside.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/russia_outside_domain.mrs)
- geosite:russia-outside
</details>
@@ -101,6 +105,7 @@
- [Kvas](https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-kvas.lst)
- [Mikrotik](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Ukraine/inside-mikrotik-fwd.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/ukraine_inside.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/ukraine_inside_domain.mrs)
- geosite:ukraine
</details>
@@ -110,6 +115,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/anime.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/anime.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/anime_domain.mrs)
- geosite:russia-inside@anime
</details>
@@ -119,6 +125,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/block.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/block.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/block_domain.mrs)
- geosite:russia-inside@block
</details>
@@ -128,6 +135,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/geoblock.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/geoblock.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/geoblock_domain.mrs)
- geosite:russia-inside@geoblock
</details>
@@ -137,6 +145,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/news.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/news.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/news_domain.mrs)
- geosite:russia-inside@news
</details>
@@ -146,6 +155,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/porn.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/porn.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/porn_domain.mrs)
- geosite:russia-inside@porn
</details>
@@ -155,6 +165,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Categories/hodca.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/hodca.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/hodca_domain.mrs)
- geosite:russia-inside@hodca
</details>
@@ -164,6 +175,8 @@
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/cloudflare.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/cloudflare.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/cloudflare_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/cloudflare_ipcidr.mrs)
</details>
@@ -173,6 +186,8 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/discord.lst)
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/discord.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/discord.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/discord_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/discord_ipcidr.mrs)
</details>
@@ -181,6 +196,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/hdrezka.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/hdrezka.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/hdrezka_domain.mrs)
- geosite:russia-inside@hdrezka
</details>
@@ -191,6 +207,8 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/meta.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/meta.srs)
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/meta.lst)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/meta_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/meta_ipcidr.mrs)
- geosite:russia-inside@meta
</details>
@@ -201,6 +219,8 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/telegram.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/telegram.srs)
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/telegram.lst)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/telegram_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/telegram_ipcidr.mrs)
</details>
@@ -209,6 +229,7 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/tiktok.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/tiktok.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/tiktok_domain.mrs)
- geosite:russia-inside@tiktok
</details>
@@ -219,6 +240,8 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/twitter.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/twitter.srs)
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/twitter.lst)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/twitter_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/twitter_ipcidr.mrs)
- geosite:russia-inside@twitter
</details>
@@ -228,10 +251,22 @@
- [RAW](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/youtube.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/youtube.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/youtube_domain.mrs)
- geosite:russia-inside@youtube
</details>
<details>
<summary>Google Meet</summary>
- [Subnets](https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/google_meet.lst)
- [SRS](https://github.com/itdoginfo/allow-domains/releases/latest/download/google_meet.srs)
- [MRS domain](https://github.com/itdoginfo/allow-domains/releases/latest/download/google_meet_domain.mrs)
- [MRS ipcidr](https://github.com/itdoginfo/allow-domains/releases/latest/download/google_meet_ipcidr.mrs)
</details>
# Как найти все-все домены ресурса?
https://itdog.info/analiziruem-trafik-i-opredelyaem-domeny-kotorye-ispolzuyut-sajty-i-prilozheniya/
@@ -292,6 +327,16 @@ service firewall restart && service dnsmasq restart
*Meta признана экстремистской и террористической организацией в России
# Разработка
```bash
nix-shell
python3 get-subnets.py
python3 convert.py
```
---
[Telegram-канал с обновлениями](https://t.me/itdoginfo)

5
Services/google_meet.lst Normal file
View File

@@ -0,0 +1,5 @@
meetings.clients6.google.com
meetings.googleapis.com
hangouts.googleapis.com
meet.google.com
stream.meet.google.com

View File

@@ -16,4 +16,5 @@ telegram.space
telesco.pe
tg.dev
tx.me
usercontent.dev
usercontent.dev
ton.org

View File

@@ -22,6 +22,7 @@
103.4.96.0/22
129.134.0.0/17
129.134.130.0/24
129.134.132.0/24
129.134.135.0/24
129.134.136.0/22
129.134.140.0/24
@@ -46,6 +47,7 @@
157.240.139.0/24
157.240.156.0/22
157.240.169.0/24
157.240.170.0/24
157.240.175.0/24
157.240.177.0/24
157.240.179.0/24

View File

@@ -9,6 +9,7 @@
205.251.252.0/23
54.192.0.0/16
204.246.173.0/24
23.228.244.0/24
54.230.200.0/21
120.253.240.192/26
23.234.192.0/18
@@ -17,6 +18,8 @@
3.173.192.0/18
108.156.0.0/14
99.86.0.0/16
23.228.214.0/24
23.228.213.0/24
13.32.0.0/15
120.253.245.128/26
13.224.0.0/14
@@ -87,6 +90,7 @@
205.251.204.0/23
130.176.192.0/19
23.228.223.0/24
23.228.212.0/24
52.124.128.0/17
204.246.164.0/22
13.35.0.0/16

View File

@@ -1,5 +1,6 @@
5.101.96.0/20
24.144.64.0/21
24.144.72.0/24
24.144.76.0/22
24.144.80.0/20
24.144.96.0/19
@@ -32,6 +33,7 @@
104.248.0.0/16
107.170.0.0/16
128.199.0.0/16
129.212.129.0/24
129.212.130.0/24
129.212.132.0/22
129.212.136.0/21
@@ -99,6 +101,7 @@
159.89.0.0/19
159.89.32.0/20
159.89.48.0/21
159.89.56.0/24
159.89.58.0/23
159.89.60.0/22
159.89.64.0/18
@@ -131,10 +134,9 @@
165.232.32.0/19
165.232.64.0/18
165.232.128.0/18
165.245.128.0/20
165.245.144.0/21
165.245.152.0/22
165.245.160.0/19
165.245.128.0/18
165.245.192.0/21
165.245.208.0/20
167.71.0.0/16
167.99.0.0/16
167.172.0.0/16
@@ -142,6 +144,7 @@
168.144.12.0/22
168.144.16.0/20
168.144.32.0/20
168.144.48.0/22
170.64.128.0/17
174.138.0.0/17
178.62.0.0/16

View File

@@ -0,0 +1,3 @@
74.125.247.128/32
74.125.250.0/24
142.250.82.0/24

View File

@@ -22,6 +22,7 @@
103.4.96.0/22
129.134.0.0/17
129.134.130.0/24
129.134.132.0/24
129.134.135.0/24
129.134.136.0/22
129.134.140.0/24
@@ -46,6 +47,7 @@
157.240.139.0/24
157.240.156.0/22
157.240.169.0/24
157.240.170.0/24
157.240.175.0/24
157.240.177.0/24
157.240.179.0/24

View File

@@ -1,7 +1,9 @@
2.27.243.0/24
2.58.172.0/24
5.39.0.0/17
5.83.153.0/24
5.102.39.0/24
5.135.0.0/16
5.144.182.0/24
5.175.168.0/24
5.175.195.0/24
5.178.106.0/24
@@ -37,13 +39,11 @@
31.56.219.0/24
31.57.161.0/24
31.57.199.0/24
31.58.88.0/24
31.59.68.0/24
37.59.0.0/16
37.60.48.0/20
37.139.130.0/24
37.187.0.0/16
37.252.26.0/24
40.160.0.0/17
40.160.128.0/19
40.160.224.0/22
@@ -67,8 +67,7 @@
45.92.60.0/22
45.94.49.0/24
45.112.195.0/24
45.138.190.0/24
45.140.36.0/24
45.140.187.0/24
45.149.63.0/24
45.149.185.0/24
45.149.243.0/24
@@ -114,7 +113,9 @@
64.83.69.0/24
64.94.92.0/23
64.95.150.0/23
64.205.192.0/24
64.225.244.0/23
65.86.32.0/24
66.70.128.0/17
66.92.11.0/24
66.92.25.0/24
@@ -126,6 +127,7 @@
68.232.108.0/24
69.17.37.0/24
69.72.31.0/24
72.244.39.0/24
72.251.0.0/17
77.73.34.0/24
77.74.120.0/23
@@ -134,7 +136,9 @@
77.81.138.0/24
77.83.244.0/24
77.87.123.0/24
77.107.88.0/24
77.246.211.0/24
78.108.59.0/24
79.110.61.0/24
79.137.0.0/17
80.71.226.0/24
@@ -187,7 +191,6 @@
82.152.8.0/24
82.152.57.0/24
82.152.58.0/24
82.152.68.0/24
82.152.73.0/24
82.152.75.0/24
82.152.98.0/24
@@ -199,18 +202,20 @@
82.153.205.0/24
83.136.214.0/23
83.143.16.0/21
83.175.167.0/24
83.175.173.0/24
84.19.167.0/24
85.217.144.0/23
86.38.187.0/24
86.54.26.0/24
87.98.128.0/17
87.229.51.0/24
87.229.64.0/24
87.232.75.0/24
88.216.221.0/24
88.218.34.0/24
89.19.44.0/24
89.21.84.0/24
89.106.2.0/24
89.125.172.0/24
89.251.28.0/24
91.90.88.0/21
91.121.0.0/16
91.124.192.0/24
@@ -220,6 +225,7 @@
91.199.32.0/24
91.213.192.0/24
91.224.117.0/24
91.233.11.0/24
91.246.38.0/24
92.62.117.0/24
92.62.241.0/24
@@ -228,6 +234,7 @@
92.118.168.0/24
92.222.0.0/16
92.246.224.0/19
92.249.62.0/24
93.88.206.0/24
93.114.69.0/24
93.174.111.0/24
@@ -238,8 +245,10 @@
103.5.12.0/22
103.82.16.0/22
103.167.178.0/23
103.189.191.0/24
103.199.80.0/24
103.206.156.0/23
103.239.50.0/24
104.164.137.0/24
104.167.16.0/24
104.222.182.0/24
@@ -262,7 +271,7 @@
117.18.104.0/24
123.100.227.0/24
128.0.118.0/24
130.49.217.0/24
132.243.197.0/24
135.125.0.0/16
135.148.0.0/16
136.0.95.0/24
@@ -273,6 +282,7 @@
138.249.135.0/24
139.99.0.0/16
141.11.18.0/24
141.11.21.0/24
141.11.31.0/24
141.11.39.0/24
141.11.74.0/23
@@ -314,7 +324,10 @@
144.31.149.0/24
144.172.73.0/24
144.217.0.0/16
144.225.112.0/24
144.225.123.0/24
144.225.162.0/24
144.225.178.0/24
145.79.151.0/24
145.239.0.0/16
146.19.38.0/24
@@ -322,6 +335,7 @@
146.59.0.0/16
146.103.10.0/24
147.79.31.0/24
147.90.234.0/24
147.135.0.0/16
147.185.197.0/24
148.113.0.0/18
@@ -334,7 +348,6 @@
149.202.0.0/16
151.80.0.0/16
151.240.1.0/24
151.240.17.0/24
151.240.24.0/24
151.241.8.0/24
151.241.68.0/24
@@ -366,11 +379,11 @@
162.212.35.0/24
163.5.62.0/24
163.5.131.0/24
163.5.149.0/24
163.5.187.0/24
163.223.88.0/24
164.132.0.0/16
166.0.112.0/24
166.1.88.0/24
166.1.90.0/24
166.1.231.0/24
167.94.252.0/24
@@ -388,10 +401,10 @@
172.83.201.0/24
173.211.127.0/24
176.31.0.0/16
176.105.229.0/24
178.32.0.0/15
180.131.145.0/24
184.174.96.0/23
184.174.99.0/24
185.5.39.0/24
185.10.200.0/22
185.12.32.0/23
@@ -408,6 +421,7 @@
185.127.28.0/24
185.129.220.0/24
185.129.222.0/24
185.133.74.0/24
185.135.188.0/24
185.137.181.0/24
185.146.195.0/24
@@ -420,6 +434,7 @@
185.225.74.0/23
185.226.181.0/24
185.228.207.0/24
185.240.238.0/24
185.241.50.0/23
185.244.29.0/24
185.244.30.0/23
@@ -463,8 +478,7 @@
195.20.146.0/24
195.62.72.0/23
195.66.30.0/23
195.88.71.0/24
195.206.242.0/24
195.226.93.0/24
198.27.64.0/18
198.49.103.0/24
198.50.128.0/17
@@ -500,6 +514,7 @@
212.74.39.0/24
212.100.171.0/24
212.134.90.0/24
212.134.97.0/24
212.135.160.0/24
212.192.253.0/24
213.32.0.0/17
@@ -511,6 +526,7 @@
213.218.214.0/24
213.251.128.0/18
216.24.220.0/23
216.132.95.0/24
216.183.120.0/24
216.203.15.0/24
216.211.218.0/24

View File

@@ -1,9 +1,8 @@
91.108.56.0/22
91.108.4.0/22
91.108.8.0/22
91.108.16.0/22
91.108.12.0/22
149.154.160.0/20
91.105.192.0/23
91.108.20.0/22
91.108.4.0/22
91.108.8.0/21
91.108.16.0/21
91.108.56.0/22
95.161.64.0/20
149.154.160.0/20
185.76.151.0/24

View File

@@ -2,7 +2,7 @@
2620:10d:c090::/44
2a03:2880::/32
2a03:2887:ff00::/48
2a03:2887:ff02::/48
2a03:2887:ff02::/47
2a03:2887:ff04::/46
2a03:2887:ff09::/48
2a03:2887:ff0a::/48

View File

@@ -3,8 +3,7 @@
2400:6180:100::/40
2604:a880::/47
2604:a880:2::/48
2604:a880:4::/47
2604:a880:6::/48
2604:a880:4::/46
2604:a880:400::/48
2604:a880:800::/48
2604:a880:cad::/48

View File

@@ -0,0 +1,3 @@
2001:4860:4864:4:8000::/128
2001:4860:4864:5::/64
2001:4860:4864:6::/64

View File

@@ -2,7 +2,7 @@
2620:10d:c090::/44
2a03:2880::/32
2a03:2887:ff00::/48
2a03:2887:ff02::/48
2a03:2887:ff02::/47
2a03:2887:ff04::/46
2a03:2887:ff09::/48
2a03:2887:ff0a::/48

View File

@@ -1,5 +1,4 @@
2001:b28:f23d::/48
2001:b28:f23f::/48
2001:67c:4e8::/48
2001:b28:f23c::/48
2001:b28:f23c::/47
2001:b28:f23f::/48
2a0a:f280::/32

View File

@@ -6,7 +6,9 @@ import re
from pathlib import Path
import json
import os
import shutil
import subprocess
import sys
rusDomainsInsideOut='Russia/inside'
rusDomainsInsideSrcSingle='src/Russia-domains-inside-single.lst'
@@ -16,70 +18,49 @@ rusDomainsOutsideSrc='src/Russia-domains-outside.lst'
rusDomainsOutsideOut='Russia/outside'
uaDomainsSrc='src/Ukraine-domains-inside.lst'
uaDomainsOut='Ukraine/inside'
DiscordSubnets = 'Subnets/IPv4/discord.lst'
MetaSubnets = 'Subnets/IPv4/meta.lst'
TwitterSubnets = 'Subnets/IPv4/twitter.lst'
TelegramSubnets = 'Subnets/IPv4/telegram.lst'
CloudflareSubnets = 'Subnets/IPv4/cloudflare.lst'
HetznerSubnets = 'Subnets/IPv4/hetzner.lst'
OVHSubnets = 'Subnets/IPv4/ovh.lst'
DigitalOceanSubnets = 'Subnets/IPv4/digitalocean.lst'
CloudfrontSubnets = 'Subnets/IPv4/cloudfront.lst'
RobloxSubnets = 'Subnets/IPv4/roblox.lst'
ExcludeServices = {"telegram.lst", "cloudflare.lst", "google_ai.lst", "google_play.lst", 'hetzner.lst', 'ovh.lst', 'digitalocean.lst', 'cloudfront.lst', 'hodca.lst', 'roblox.lst'}
SUBNET_SERVICES = [
'discord', 'meta', 'twitter', 'telegram',
'cloudflare', 'hetzner', 'ovh', 'digitalocean',
'cloudfront', 'roblox', 'google_meet',
]
ExcludeServices = {"telegram.lst", "cloudflare.lst", "google_ai.lst", "google_play.lst", 'hetzner.lst', 'ovh.lst', 'digitalocean.lst', 'cloudfront.lst', 'hodca.lst', 'roblox.lst', 'google_meet.lst'}
def collect_files(src):
files = []
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
return files
def collect_domains(src, dot_prefix=True):
domains = set()
for f in collect_files(src):
if not f.is_file():
continue
with open(f) as infile:
for line in infile:
ext = tldextract.extract(line.rstrip())
if not ext.suffix:
continue
if re.search(r'[^а\-]', ext.domain):
domains.add(ext.fqdn)
elif not ext.domain:
prefix = '.' if dot_prefix else ''
domains.add(prefix + ext.suffix)
return domains
def raw(src, out):
domains = set()
files = []
if isinstance(src, list):
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
for f in files:
if f.is_file():
with open(f) as infile:
for line in infile:
if tldextract.extract(line).suffix:
if re.search(r'[^а\-]', tldextract.extract(line).domain):
domains.add(tldextract.extract(line.rstrip()).fqdn)
if not tldextract.extract(line).domain and tldextract.extract(line).suffix:
domains.add("." + tldextract.extract(line.rstrip()).suffix)
domains = sorted(domains)
domains = sorted(collect_domains(src))
with open(f'{out}-raw.lst', 'w') as file:
for name in domains:
file.write(f'{name}\n')
def dnsmasq(src, out, remove={'google.com'}):
domains = set()
files = []
if isinstance(src, list):
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
for f in files:
if f.is_file():
with open(f) as infile:
for line in infile:
if tldextract.extract(line).suffix:
if re.search(r'[^а\-]', tldextract.extract(line).domain):
domains.add(tldextract.extract(line.rstrip()).fqdn)
if not tldextract.extract(line).domain and tldextract.extract(line).suffix:
domains.add("." + tldextract.extract(line.rstrip()).suffix)
domains = domains - remove
domains = sorted(domains)
domains = sorted(collect_domains(src) - remove)
with open(f'{out}-dnsmasq-nfset.lst', 'w') as file:
for name in domains:
@@ -90,84 +71,21 @@ def dnsmasq(src, out, remove={'google.com'}):
file.write(f'ipset=/{name}/vpn_domains\n')
def clashx(src, out, remove={'google.com'}):
domains = set()
files = []
if isinstance(src, list):
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
for f in files:
with open(f) as infile:
for line in infile:
if tldextract.extract(line).suffix:
if re.search(r'[^а\-]', tldextract.extract(line).domain):
domains.add(tldextract.extract(line.rstrip()).fqdn)
if not tldextract.extract(line).domain and tldextract.extract(line).suffix:
domains.add("." + tldextract.extract(line.rstrip()).suffix)
domains = domains - remove
domains = sorted(domains)
domains = sorted(collect_domains(src) - remove)
with open(f'{out}-clashx.lst', 'w') as file:
for name in domains:
file.write(f'DOMAIN-SUFFIX,{name}\n')
def kvas(src, out, remove={'google.com'}):
domains = set()
files = []
if isinstance(src, list):
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
for f in files:
with open(f) as infile:
for line in infile:
if tldextract.extract(line).suffix:
if re.search(r'[^а\-]', tldextract.extract(line).domain):
domains.add(tldextract.extract(line.rstrip()).fqdn)
if not tldextract.extract(line).domain and tldextract.extract(line).suffix:
domains.add(tldextract.extract(line.rstrip()).suffix)
domains = domains - remove
domains = sorted(domains)
domains = sorted(collect_domains(src, dot_prefix=False) - remove)
with open(f'{out}-kvas.lst', 'w') as file:
for name in domains:
file.write(f'{name}\n')
def mikrotik_fwd(src, out, remove={'google.com'}):
domains = set()
files = []
if isinstance(src, list):
for dir_path in src:
path = Path(dir_path)
if path.is_dir():
files.extend(f for f in path.glob('*') if f.name not in ExcludeServices)
elif path.is_file() and path.name not in ExcludeServices:
files.append(path)
for f in files:
with open(f) as infile:
for line in infile:
if tldextract.extract(line).suffix:
if re.search(r'[^а\-]', tldextract.extract(line).domain):
domains.add(tldextract.extract(line.rstrip()).fqdn)
if not tldextract.extract(line).domain and tldextract.extract(line).suffix:
domains.add("." + tldextract.extract(line.rstrip()).suffix)
domains = domains - remove
domains = sorted(domains)
domains = sorted(collect_domains(src) - remove)
with open(f'{out}-mikrotik-fwd.lst', 'w') as file:
for name in domains:
@@ -176,213 +94,75 @@ def mikrotik_fwd(src, out, remove={'google.com'}):
else:
file.write(f'/ip dns static add name={name} type=FWD address-list=allow-domains match-subdomain=yes forward-to=localhost\n')
def domains_from_file(filepath):
domains = []
try:
with open(filepath, 'r', encoding='utf-8') as file:
for line in file:
domain = line.strip()
if domain:
domains.append(domain)
except FileNotFoundError:
print(f"File not found: {filepath}")
return domains
def lines_from_file(filepath):
if not os.path.exists(filepath):
print(f"Warning: input file not found: {filepath}", file=sys.stderr)
return []
with open(filepath, 'r', encoding='utf-8') as f:
return [line.strip() for line in f if line.strip()]
def generate_srs_domains(domains, output_name):
output_directory = 'JSON'
compiled_output_directory = 'SRS'
def compile_mrs(domains, name, mrs_dir='MRS', behavior='domain'):
os.makedirs(mrs_dir, exist_ok=True)
os.makedirs(output_directory, exist_ok=True)
os.makedirs(compiled_output_directory, exist_ok=True)
txt_path = os.path.join(mrs_dir, f"{name}.txt")
mrs_path = os.path.join(mrs_dir, f"{name}.mrs")
data = {
"version": 3,
"rules": [
{"domain_suffix": domains}
]
}
json_file_path = os.path.join(output_directory, f"{output_name}.json")
srs_file_path = os.path.join(compiled_output_directory, f"{output_name}.srs")
with open(txt_path, 'w', encoding='utf-8') as f:
for d in domains:
f.write(f"{d}\n")
try:
with open(json_file_path, 'w', encoding='utf-8') as json_file:
json.dump(data, json_file, indent=4)
print(f"JSON file generated: {json_file_path}")
subprocess.run(
["sing-box", "rule-set", "compile", json_file_path, "-o", srs_file_path], check=True
["mihomo", "convert-ruleset", behavior, "text", txt_path, mrs_path], check=True
)
print(f"Compiled .srs file: {srs_file_path}")
print(f"Compiled: {mrs_path}")
except subprocess.CalledProcessError as e:
print(f"Compile error {json_file_path}: {e}")
except Exception as e:
print(f"Error while processing {output_name}: {e}")
print(f"Compile error {txt_path}: {e}")
sys.exit(1)
def generate_srs_for_categories(directories, output_json_directory='JSON', compiled_output_directory='SRS'):
os.makedirs(output_json_directory, exist_ok=True)
os.makedirs(compiled_output_directory, exist_ok=True)
def compile_srs(data, name, json_dir='JSON', srs_dir='SRS'):
os.makedirs(json_dir, exist_ok=True)
os.makedirs(srs_dir, exist_ok=True)
exclude = {"meta", "twitter", "discord", "telegram", "hetzner", "ovh", "digitalocean", "cloudfront", "roblox"}
json_path = os.path.join(json_dir, f"{name}.json")
srs_path = os.path.join(srs_dir, f"{name}.srs")
with open(json_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)
try:
subprocess.run(
["sing-box", "rule-set", "compile", json_path, "-o", srs_path], check=True
)
print(f"Compiled: {srs_path}")
except subprocess.CalledProcessError as e:
print(f"Compile error {json_path}: {e}")
sys.exit(1)
def srs_rule(name, rules):
compile_srs({"version": 3, "rules": rules}, name)
def generate_srs_for_categories(directories):
exclude = {"meta", "twitter", "discord", "telegram", "hetzner", "ovh", "digitalocean", "cloudfront", "roblox", "google_meet"}
for directory in directories:
for filename in os.listdir(directory):
if any(keyword in filename for keyword in exclude):
continue
file_path = os.path.join(directory, filename)
if os.path.isfile(file_path):
domains = []
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
domain = line.strip()
if domain:
domains.append(domain)
data = {
"version": 3,
"rules": [
{
"domain_suffix": domains
}
]
}
output_file_path = os.path.join(output_json_directory, f"{os.path.splitext(filename)[0]}.json")
with open(output_file_path, 'w', encoding='utf-8') as output_file:
json.dump(data, output_file, indent=4)
print(f"JSON file generated: {output_file_path}")
print("\nCompile JSON files to .srs files...")
for filename in os.listdir(output_json_directory):
if filename.endswith('.json'):
json_file_path = os.path.join(output_json_directory, filename)
srs_file_path = os.path.join(compiled_output_directory, f"{os.path.splitext(filename)[0]}.srs")
try:
subprocess.run(
["sing-box", "rule-set", "compile", json_file_path, "-o", srs_file_path], check=True
)
print(f"Compiled .srs file: {srs_file_path}")
except subprocess.CalledProcessError as e:
print(f"Compile error {json_file_path}: {e}")
def generate_srs_subnets(input_file, output_json_directory='JSON', compiled_output_directory='SRS'):
os.makedirs(output_json_directory, exist_ok=True)
os.makedirs(compiled_output_directory, exist_ok=True)
subnets = []
with open(input_file, 'r', encoding='utf-8') as file:
for line in file:
subnet = line.strip()
if subnet:
subnets.append(subnet)
data = {
"version": 3,
"rules": [
{
"ip_cidr": subnets
}
]
}
filename = os.path.splitext(os.path.basename(input_file))[0]
output_file_path = os.path.join(output_json_directory, f"{filename}.json")
with open(output_file_path, 'w', encoding='utf-8') as output_file:
json.dump(data, output_file, indent=4)
print(f"JSON file generated: {output_file_path}")
srs_file_path = os.path.join(compiled_output_directory, f"{filename}.srs")
try:
subprocess.run(
["sing-box", "rule-set", "compile", output_file_path, "-o", srs_file_path], check=True
)
print(f"Compiled .srs file: {srs_file_path}")
except subprocess.CalledProcessError as e:
print(f"Compile error {output_file_path}: {e}")
def generate_srs_combined(input_subnets_file, input_domains_file, output_json_directory='JSON', compiled_output_directory='SRS'):
os.makedirs(output_json_directory, exist_ok=True)
os.makedirs(compiled_output_directory, exist_ok=True)
domains = []
if os.path.exists(input_domains_file):
with open(input_domains_file, 'r', encoding='utf-8') as file:
domains = [line.strip() for line in file if line.strip()]
subnets = []
if os.path.exists(input_subnets_file):
with open(input_subnets_file, 'r', encoding='utf-8') as file:
subnets = [line.strip() for line in file if line.strip()]
if input_subnets_file == "Subnets/IPv4/discord.lst":
data = {
"version": 3,
"rules": [
{
"domain_suffix": domains
},
{
"network": ["udp"],
"ip_cidr": subnets,
"port_range": ["50000:65535"]
}
]
}
elif input_subnets_file == "Subnets/IPv4/telegram.lst" and input_domains_file == "voice_messengers":
data = {
"version": 3,
"rules": [
{
"network": ["udp"],
"ip_cidr": subnets,
"port": [1400],
"port_range": ["596:599"]
}
]
}
else:
data = {
"version": 3,
"rules": [
{
"domain_suffix": domains,
"ip_cidr": subnets
}
]
}
if input_domains_file == "voice_messengers":
filename = "voice_messengers"
else:
filename = os.path.splitext(os.path.basename(input_subnets_file))[0]
output_file_path = os.path.join(output_json_directory, f"{filename}.json")
with open(output_file_path, 'w', encoding='utf-8') as output_file:
json.dump(data, output_file, indent=4)
print(f"JSON file generated: {output_file_path}")
srs_file_path = os.path.join(compiled_output_directory, f"{filename}.srs")
try:
subprocess.run(
["sing-box", "rule-set", "compile", output_file_path, "-o", srs_file_path], check=True
)
print(f"Compiled .srs file: {srs_file_path}")
except subprocess.CalledProcessError as e:
print(f"Compile error {output_file_path}: {e}")
domains = lines_from_file(file_path)
name = os.path.splitext(filename)[0]
srs_rule(name, [{"domain_suffix": domains}])
def prepare_dat_domains(domains, output_name, dirs=[]):
def prepare_dat_domains(domains, output_name, dirs=None):
output_lists_directory = 'geosite_data'
os.makedirs(output_lists_directory, exist_ok=True)
domain_attrs = {domain: [] for domain in domains}
for directory in dirs:
for directory in (dirs or []):
if not os.path.isdir(directory):
continue
for filename in os.listdir(directory):
@@ -407,8 +187,6 @@ def prepare_dat_domains(domains, output_name, dirs=[]):
out_f.write(f"{line}\n")
def prepare_dat_combined(dirs):
import shutil
output_lists_directory = 'geosite_data'
os.makedirs(output_lists_directory, exist_ok=True)
@@ -426,18 +204,65 @@ def prepare_dat_combined(dirs):
shutil.copyfile(source_path, destination_path)
def parse_geosite_line(line):
from proto import geosite_pb2
parts = line.split()
raw_domain = parts[0]
attrs = [p.lstrip('@') for p in parts[1:] if p.startswith('@')]
if raw_domain.startswith('full:'):
domain_type = geosite_pb2.Domain.Full
value = raw_domain[5:]
elif raw_domain.startswith('regexp:'):
domain_type = geosite_pb2.Domain.Regex
value = raw_domain[7:]
elif raw_domain.startswith('keyword:'):
domain_type = geosite_pb2.Domain.Plain
value = raw_domain[8:]
else:
domain_type = geosite_pb2.Domain.RootDomain
value = raw_domain.lstrip('.')
return domain_type, value, attrs
def generate_dat_domains(data_path='geosite_data', output_name='geosite.dat', output_directory='DAT'):
from proto import geosite_pb2
os.makedirs(output_directory, exist_ok=True)
try:
subprocess.run(
["domain-list-community", f"-datapath={data_path}", f"-outputname={output_name}", f"-outputdir={output_directory}"],
check=True,
stdout=subprocess.DEVNULL
)
print(f"Compiled .dat file: {output_directory}/{output_name}")
except subprocess.CalledProcessError as e:
print(f"Compile error {data_path}: {e}")
geo_site_list = geosite_pb2.GeoSiteList()
for filename in sorted(os.listdir(data_path)):
file_path = os.path.join(data_path, filename)
if not os.path.isfile(file_path):
continue
geo_site = geo_site_list.entry.add()
geo_site.country_code = filename.upper()
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line or line.startswith('#'):
continue
domain_type, value, attrs = parse_geosite_line(line)
domain = geo_site.domain.add()
domain.type = domain_type
domain.value = value
for attr in attrs:
attribute = domain.attribute.add()
attribute.key = attr
attribute.bool_value = True
output_path = os.path.join(output_directory, output_name)
with open(output_path, 'wb') as f:
f.write(geo_site_list.SerializeToString())
print(f"Compiled .dat file: {output_path}")
if __name__ == '__main__':
# Russia inside
@@ -482,31 +307,55 @@ if __name__ == '__main__':
Path(temp_file).unlink()
# Sing-box ruleset main
russia_inside = domains_from_file('Russia/inside-raw.lst')
russia_outside = domains_from_file('Russia/outside-raw.lst')
ukraine_inside = domains_from_file('Ukraine/inside-raw.lst')
generate_srs_domains(russia_inside, 'russia_inside')
generate_srs_domains(russia_outside, 'russia_outside')
generate_srs_domains(ukraine_inside, 'ukraine_inside')
russia_inside = lines_from_file('Russia/inside-raw.lst')
russia_outside = lines_from_file('Russia/outside-raw.lst')
ukraine_inside = lines_from_file('Ukraine/inside-raw.lst')
srs_rule('russia_inside', [{"domain_suffix": russia_inside}])
srs_rule('russia_outside', [{"domain_suffix": russia_outside}])
srs_rule('ukraine_inside', [{"domain_suffix": ukraine_inside}])
# Sing-box categories
directories = ['Categories', 'Services']
generate_srs_for_categories(directories)
# Sing-box subnets + domains
generate_srs_combined(DiscordSubnets, "Services/discord.lst")
generate_srs_combined(TwitterSubnets, "Services/twitter.lst")
generate_srs_combined(MetaSubnets, "Services/meta.lst")
generate_srs_combined(TelegramSubnets, "Services/telegram.lst")
generate_srs_combined(CloudflareSubnets, "Services/cloudflare.lst")
generate_srs_combined(HetznerSubnets, "Services/hetzner.lst")
generate_srs_combined(OVHSubnets, "Services/ovh.lst")
generate_srs_combined(DigitalOceanSubnets, "Services/digitalocean.lst")
generate_srs_combined(CloudfrontSubnets, "Services/cloudfront.lst")
generate_srs_combined(RobloxSubnets, "Services/roblox.lst")
for service in SUBNET_SERVICES:
if service == 'discord':
continue
subnets = lines_from_file(f'Subnets/IPv4/{service}.lst')
domains = lines_from_file(f'Services/{service}.lst')
srs_rule(service, [{"domain_suffix": domains, "ip_cidr": subnets}])
# Sing-box voice for messengers
generate_srs_combined(TelegramSubnets, "voice_messengers")
# Discord (domains + UDP subnets on high ports)
discord_subnets = lines_from_file('Subnets/IPv4/discord.lst')
discord_domains = lines_from_file('Services/discord.lst')
srs_rule('discord', [
{"domain_suffix": discord_domains},
{"network": ["udp"], "ip_cidr": discord_subnets, "port_range": ["50000:65535"]},
])
# Mihomo main
to_mrs = lambda domains: [f'+.{d.lstrip(".")}' for d in domains]
mrs_russia_inside = to_mrs(russia_inside)
mrs_russia_outside = to_mrs(russia_outside)
mrs_ukraine_inside = to_mrs(ukraine_inside)
compile_mrs(mrs_russia_inside, 'russia_inside_domain')
compile_mrs(mrs_russia_outside, 'russia_outside_domain')
compile_mrs(mrs_ukraine_inside, 'ukraine_inside_domain')
# Mihomo categories
for directory in ['Categories', 'Services']:
for filename in os.listdir(directory):
file_path = os.path.join(directory, filename)
if os.path.isfile(file_path):
domains = to_mrs(lines_from_file(file_path))
name = os.path.splitext(filename)[0]
compile_mrs(domains, f'{name}_domain')
# Mihomo subnets
for service in SUBNET_SERVICES:
subnets = lines_from_file(f'Subnets/IPv4/{service}.lst')
compile_mrs(subnets, f'{service}_ipcidr', behavior='ipcidr')
# Xray domains
prepare_dat_domains(russia_inside, 'russia-inside', directories)

View File

@@ -1,30 +1,28 @@
#!/usr/bin/python3.10
#!/usr/bin/env python3
import ipaddress
import urllib.request
import os
import shutil
import json
import sys
BGP_TOOLS_URL = 'https://bgp.tools/table.txt'
HEADERS = { 'User-Agent': 'itdog.info - hi@itdog.info' }
AS_FILE = 'AS.lst'
RIPE_STAT_URL = 'https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS{}'
USER_AGENT = 'allow-domains/1.0'
IPv4_DIR = 'Subnets/IPv4'
IPv6_DIR = 'Subnets/IPv6'
AS_META = ['32934','63293','54115','149642']
AS_TWITTER = ['13414']
AS_HETZNER = ['24940']
AS_OVH = ['16276']
AS_DIGITALOCEAN = ['14061']
ASN_SERVICES = {
'meta.lst': ['32934', '63293', '54115', '149642'],
'twitter.lst': ['13414'],
'hetzner.lst': ['24940'],
'ovh.lst': ['16276'],
'digitalocean.lst': ['14061'],
}
META = 'meta.lst'
TWITTER = 'twitter.lst'
ASN_TELEGRAM = ['44907', '59930', '62014', '62041', '211157']
TELEGRAM = 'telegram.lst'
CLOUDFLARE = 'cloudflare.lst'
HETZNER = 'hetzner.lst'
OVH = 'ovh.lst'
DIGITALOCEAN = 'digitalocean.lst'
CLOUDFRONT = 'cloudfront.lst'
# From https://iplist.opencck.org/
@@ -38,93 +36,103 @@ TELEGRAM_CIDR_URL = 'https://core.telegram.org/resources/cidr.txt'
CLOUDFLARE_V4='https://www.cloudflare.com/ips-v4'
CLOUDFLARE_V6='https://www.cloudflare.com/ips-v6'
AWS_IP_RANGES_URL='https://ip-ranges.amazonaws.com/ip-ranges.json'
# https://support.google.com/a/answer/1279090
GOOGLE_MEET = 'google_meet.lst'
GOOGLE_MEET_V4 = [
'74.125.247.128/32',
'74.125.250.0/24',
'142.250.82.0/24',
]
GOOGLE_MEET_V6 = [
'2001:4860:4864:4:8000::/128',
'2001:4860:4864:5::/64',
'2001:4860:4864:6::/64',
]
subnet_list = []
AWS_CIDR_URL='https://ip-ranges.amazonaws.com/ip-ranges.json'
def make_request(url):
req = urllib.request.Request(url)
req.add_header('User-Agent', USER_AGENT)
return req
def subnet_summarization(subnet_list):
subnets = [ipaddress.ip_network(subnet) for subnet in subnet_list]
subnets = [ipaddress.ip_network(subnet, strict=False) for subnet in subnet_list]
return list(ipaddress.collapse_addresses(subnets))
def process_subnets(subnet_list, target_as):
def fetch_asn_prefixes(asn_list):
ipv4_subnets = []
ipv6_subnets = []
for subnet_str, as_number in subnet_list:
for asn in asn_list:
url = RIPE_STAT_URL.format(asn)
req = make_request(url)
try:
subnet = ipaddress.ip_network(subnet_str)
if as_number in target_as:
if subnet.version == 4:
ipv4_subnets.append(subnet_str)
elif subnet.version == 6:
ipv6_subnets.append(subnet_str)
except ValueError:
print(f"Invalid subnet: {subnet_str}")
sys.exit(1)
ipv4_merged = subnet_summarization(ipv4_subnets)
ipv6_merged = subnet_summarization(ipv6_subnets)
return ipv4_merged, ipv6_merged
def download_ready_subnets(url_v4, url_v6):
ipv4_subnets = []
ipv6_subnets = []
urls = [(url_v4, 4), (url_v6, 6)]
for url, version in urls:
req = urllib.request.Request(url, headers=HEADERS)
try:
with urllib.request.urlopen(req) as response:
if response.status == 200:
subnets = response.read().decode('utf-8').splitlines()
for subnet_str in subnets:
try:
subnet = ipaddress.ip_network(subnet_str)
if subnet.version == 4:
ipv4_subnets.append(subnet_str)
elif subnet.version == 6:
ipv6_subnets.append(subnet_str)
except ValueError:
print(f"Invalid subnet: {subnet_str}")
sys.exit(1)
with urllib.request.urlopen(req, timeout=30) as response:
data = json.loads(response.read().decode('utf-8'))
for entry in data['data']['prefixes']:
prefix = entry['prefix']
try:
network = ipaddress.ip_network(prefix)
if network.version == 4:
ipv4_subnets.append(prefix)
else:
ipv6_subnets.append(prefix)
except ValueError:
print(f"Invalid subnet: {prefix}")
sys.exit(1)
except Exception as e:
print(f"Query error: {e}")
print(f"Error fetching AS{asn}: {e}")
sys.exit(1)
return ipv4_subnets, ipv6_subnets
def download_ready_split_subnets(url):
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as response:
subnets = response.read().decode('utf-8').splitlines()
def download_subnets(*urls):
ipv4_subnets = []
ipv6_subnets = []
for url in urls:
req = make_request(url)
try:
with urllib.request.urlopen(req, timeout=30) as response:
subnets = response.read().decode('utf-8').splitlines()
for subnet_str in subnets:
try:
network = ipaddress.ip_network(subnet_str, strict=False)
if network.version == 4:
ipv4_subnets.append(subnet_str)
else:
ipv6_subnets.append(subnet_str)
except ValueError:
print(f"Invalid subnet: {subnet_str}")
sys.exit(1)
except Exception as e:
print(f"Query error {url}: {e}")
sys.exit(1)
ipv4_subnets = [cidr for cidr in subnets if isinstance(ipaddress.ip_network(cidr, strict=False), ipaddress.IPv4Network)]
ipv6_subnets = [cidr for cidr in subnets if isinstance(ipaddress.ip_network(cidr, strict=False), ipaddress.IPv6Network)]
return ipv4_subnets, ipv6_subnets
def download_aws_cloudfront_subnets():
ipv4_subnets = []
ipv6_subnets = []
req = urllib.request.Request(AWS_IP_RANGES_URL, headers=HEADERS)
req = make_request(AWS_CIDR_URL)
try:
with urllib.request.urlopen(req) as response:
if response.status == 200:
data = json.loads(response.read().decode('utf-8'))
for prefix in data.get('prefixes', []):
if prefix.get('service') == 'CLOUDFRONT':
ipv4_subnets.append(prefix['ip_prefix'])
for prefix in data.get('ipv6_prefixes', []):
if prefix.get('service') == 'CLOUDFRONT':
ipv6_subnets.append(prefix['ipv6_prefix'])
with urllib.request.urlopen(req, timeout=30) as response:
data = json.loads(response.read().decode('utf-8'))
for prefix in data.get('prefixes', []):
if prefix.get('service') == 'CLOUDFRONT':
ipv4_subnets.append(prefix['ip_prefix'])
for prefix in data.get('ipv6_prefixes', []):
if prefix.get('service') == 'CLOUDFRONT':
ipv6_subnets.append(prefix['ipv6_prefix'])
except Exception as e:
print(f"Error downloading AWS CloudFront ranges: {e}")
sys.exit(1)
return ipv4_subnets, ipv6_subnets
def write_subnets_to_file(subnets, filename):
@@ -138,63 +146,47 @@ def copy_file_legacy(src_filename):
shutil.copy(src_filename, os.path.join(os.path.dirname(src_filename), new_filename))
if __name__ == '__main__':
request = urllib.request.Request(BGP_TOOLS_URL, headers=HEADERS)
with urllib.request.urlopen(request) as response:
for line in response:
decoded_line = line.decode('utf-8').strip()
subnet, as_number = decoded_line.split()
subnet_list.append((subnet, as_number))
# Meta
ipv4_merged_meta, ipv6_merged_meta = process_subnets(subnet_list, AS_META)
write_subnets_to_file(ipv4_merged_meta, f'{IPv4_DIR}/{META}')
write_subnets_to_file(ipv6_merged_meta, f'{IPv6_DIR}/{META}')
# Twitter
ipv4_merged_twitter, ipv6_merged_twitter = process_subnets(subnet_list, AS_TWITTER)
write_subnets_to_file(ipv4_merged_twitter, f'{IPv4_DIR}/{TWITTER}')
write_subnets_to_file(ipv6_merged_twitter, f'{IPv6_DIR}/{TWITTER}')
# Hetzner
ipv4_merged_hetzner, ipv6_merged_hetzner = process_subnets(subnet_list, AS_HETZNER)
write_subnets_to_file(ipv4_merged_hetzner, f'{IPv4_DIR}/{HETZNER}')
write_subnets_to_file(ipv6_merged_hetzner, f'{IPv6_DIR}/{HETZNER}')
# OVH
ipv4_merged_ovh, ipv6_merged_ovh = process_subnets(subnet_list, AS_OVH)
write_subnets_to_file(ipv4_merged_ovh, f'{IPv4_DIR}/{OVH}')
write_subnets_to_file(ipv6_merged_ovh, f'{IPv6_DIR}/{OVH}')
# Digital Ocean
ipv4_merged_digitalocean, ipv6_merged_digitalocean = process_subnets(subnet_list, AS_DIGITALOCEAN)
write_subnets_to_file(ipv4_merged_digitalocean, f'{IPv4_DIR}/{DIGITALOCEAN}')
write_subnets_to_file(ipv6_merged_digitalocean, f'{IPv6_DIR}/{DIGITALOCEAN}')
# Services from ASN (meta, twitter, hetzner, ovh, digitalocean)
for filename, asn_list in ASN_SERVICES.items():
print(f'Fetching {filename}...')
ipv4, ipv6 = fetch_asn_prefixes(asn_list)
write_subnets_to_file(subnet_summarization(ipv4), f'{IPv4_DIR}/{filename}')
write_subnets_to_file(subnet_summarization(ipv6), f'{IPv6_DIR}/{filename}')
# Discord voice
ipv4_discord, ipv6_discord = download_ready_subnets(DISCORD_VOICE_V4, DISCORD_VOICE_V6)
print(f'Fetching {DISCORD}...')
ipv4_discord, ipv6_discord = download_subnets(DISCORD_VOICE_V4, DISCORD_VOICE_V6)
write_subnets_to_file(ipv4_discord, f'{IPv4_DIR}/{DISCORD}')
write_subnets_to_file(ipv6_discord, f'{IPv6_DIR}/{DISCORD}')
# Telegram
ipv4_telegram, ipv6_telegram = download_ready_split_subnets(TELEGRAM_CIDR_URL)
print(f'Fetching {TELEGRAM}...')
ipv4_telegram_file, ipv6_telegram_file = download_subnets(TELEGRAM_CIDR_URL)
ipv4_telegram_asn, ipv6_telegram_asn = fetch_asn_prefixes(ASN_TELEGRAM)
ipv4_telegram = subnet_summarization(ipv4_telegram_file + ipv4_telegram_asn)
ipv6_telegram = subnet_summarization(ipv6_telegram_file + ipv6_telegram_asn)
write_subnets_to_file(ipv4_telegram, f'{IPv4_DIR}/{TELEGRAM}')
write_subnets_to_file(ipv6_telegram, f'{IPv6_DIR}/{TELEGRAM}')
# Cloudflare
ipv4_cloudflare, ipv6_cloudflare = download_ready_subnets(CLOUDFLARE_V4, CLOUDFLARE_V6)
print(f'Fetching {CLOUDFLARE}...')
ipv4_cloudflare, ipv6_cloudflare = download_subnets(CLOUDFLARE_V4, CLOUDFLARE_V6)
write_subnets_to_file(ipv4_cloudflare, f'{IPv4_DIR}/{CLOUDFLARE}')
write_subnets_to_file(ipv6_cloudflare, f'{IPv6_DIR}/{CLOUDFLARE}')
# Google Meet
print(f'Writing {GOOGLE_MEET}...')
write_subnets_to_file(GOOGLE_MEET_V4, f'{IPv4_DIR}/{GOOGLE_MEET}')
write_subnets_to_file(GOOGLE_MEET_V6, f'{IPv6_DIR}/{GOOGLE_MEET}')
# AWS CloudFront
print(f'Fetching {CLOUDFRONT}...')
ipv4_cloudfront, ipv6_cloudfront = download_aws_cloudfront_subnets()
write_subnets_to_file(ipv4_cloudfront, f'{IPv4_DIR}/{CLOUDFRONT}')
write_subnets_to_file(ipv6_cloudfront, f'{IPv6_DIR}/{CLOUDFRONT}')
# Legacy name
copy_file_legacy(f'{IPv4_DIR}/{META}')
copy_file_legacy(f'{IPv6_DIR}/{META}')
copy_file_legacy(f'{IPv4_DIR}/{TWITTER}')
copy_file_legacy(f'{IPv6_DIR}/{TWITTER}')
copy_file_legacy(f'{IPv4_DIR}/{DISCORD}')
copy_file_legacy(f'{IPv6_DIR}/{DISCORD}')
# Legacy copies with capitalized names (e.g. meta.lst -> Meta.lst)
LEGACY_FILES = ['meta.lst', 'twitter.lst', 'discord.lst']
for legacy_file in LEGACY_FILES:
copy_file_legacy(f'{IPv4_DIR}/{legacy_file}')
copy_file_legacy(f'{IPv6_DIR}/{legacy_file}')

0
proto/__init__.py Normal file
View File

37
proto/geosite.proto Normal file
View File

@@ -0,0 +1,37 @@
// Source: github.com/v2fly/v2ray-core/app/router/routercommon/common.proto
syntax = "proto3";
package geosite;
option go_package = "geosite";
message Domain {
enum Type {
Plain = 0;
Regex = 1;
RootDomain = 2;
Full = 3;
}
Type type = 1;
string value = 2;
message Attribute {
string key = 1;
oneof typed_value {
bool bool_value = 2;
int64 int_value = 3;
}
}
repeated Attribute attribute = 3;
}
message GeoSite {
string country_code = 1;
repeated Domain domain = 2;
}
message GeoSiteList {
repeated GeoSite entry = 1;
}

45
proto/geosite_pb2.py Normal file
View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: proto/geosite.proto
# Protobuf Python Version: 6.32.1
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import runtime_version as _runtime_version
from google.protobuf import symbol_database as _symbol_database
from google.protobuf.internal import builder as _builder
_runtime_version.ValidateProtobufRuntimeVersion(
_runtime_version.Domain.PUBLIC,
6,
32,
1,
'',
'proto/geosite.proto'
)
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13proto/geosite.proto\x12\x07geosite\"\xf5\x01\n\x06\x44omain\x12\"\n\x04type\x18\x01 \x01(\x0e\x32\x14.geosite.Domain.Type\x12\r\n\x05value\x18\x02 \x01(\t\x12,\n\tattribute\x18\x03 \x03(\x0b\x32\x19.geosite.Domain.Attribute\x1aR\n\tAttribute\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x42\r\n\x0btyped_value\"6\n\x04Type\x12\t\n\x05Plain\x10\x00\x12\t\n\x05Regex\x10\x01\x12\x0e\n\nRootDomain\x10\x02\x12\x08\n\x04\x46ull\x10\x03\"@\n\x07GeoSite\x12\x14\n\x0c\x63ountry_code\x18\x01 \x01(\t\x12\x1f\n\x06\x64omain\x18\x02 \x03(\x0b\x32\x0f.geosite.Domain\".\n\x0bGeoSiteList\x12\x1f\n\x05\x65ntry\x18\x01 \x03(\x0b\x32\x10.geosite.GeoSiteB\tZ\x07geositeb\x06proto3')
_globals = globals()
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'proto.geosite_pb2', _globals)
if not _descriptor._USE_C_DESCRIPTORS:
_globals['DESCRIPTOR']._loaded_options = None
_globals['DESCRIPTOR']._serialized_options = b'Z\007geosite'
_globals['_DOMAIN']._serialized_start=33
_globals['_DOMAIN']._serialized_end=278
_globals['_DOMAIN_ATTRIBUTE']._serialized_start=140
_globals['_DOMAIN_ATTRIBUTE']._serialized_end=222
_globals['_DOMAIN_TYPE']._serialized_start=224
_globals['_DOMAIN_TYPE']._serialized_end=278
_globals['_GEOSITE']._serialized_start=280
_globals['_GEOSITE']._serialized_end=344
_globals['_GEOSITELIST']._serialized_start=346
_globals['_GEOSITELIST']._serialized_end=392
# @@protoc_insertion_point(module_scope)

View File

@@ -1 +1,2 @@
tldextract
protobuf>=6.32.1

View File

@@ -4,12 +4,15 @@ pkgs.mkShell {
buildInputs = with pkgs; [
python312
python312Packages.tldextract
python312Packages.protobuf
sing-box
mihomo
];
shellHook = ''
echo "Environment ready!"
echo "Python version: $(python --version)"
echo "sing-box version: $(sing-box version 2>/dev/null || echo 'not available')"
echo "mihomo version: $(mihomo -v 2>/dev/null || echo 'not available')"
'';
}