This commit is contained in:
Ground-Zerro
2024-08-12 22:14:25 +11:00
parent dadeeebd43
commit 172d1026c2
6 changed files with 182 additions and 47 deletions

View File

@@ -46,8 +46,17 @@ pip3 install -r requirements.txt
**Использование:** Запустить с помощью Python. Для работы необходим только "main.py" и (по желанию) файл "config.ini".
**Использование:**
- Запустить с помощью Python. Для работы необходим только "main.py" и (по желанию) файл "config.ini".
- *Beta:* Запустить PowerShell и выполнить команду:
```
irm https://github.com/Ground-Zerro/DomainMapper/raw/main/Win.bat -OutFile "$env:TEMP\Win.bat"; cmd /c "$env:TEMP\Win.bat"
```
###### Протестировано в Ubuntu 20.04 и Windows 10/11

81
Win.bat Normal file
View File

@@ -0,0 +1,81 @@
@echo off
setlocal enabledelayedexpansion
chcp 65001 > NUL
REM Проверяем, установлен ли Python 3
python --version 2>NUL | findstr /I "Python 3" >NUL
if ERRORLEVEL 1 (
echo Python 3 не установлен.
choice /C YN /M "Установить?"
if ERRORLEVEL 2 (
echo Без Python 3 ничего не получится...
pause
exit /b 1
) else (
echo Загрузка дистрибутива...
powershell -Command "if ($PSVersionTable.PSVersion.Major -ge 3) {Invoke-WebRequest -Uri 'https://www.python.org/ftp/python/3.12.5/python-3.12.5-amd64.exe' -OutFile 'python_installer.exe'} else {Start-BitsTransfer -Source 'https://www.python.org/ftp/python/3.12.5/python-3.12.5-amd64.exe' -Destination 'python_installer.exe'}"
REM Проверяем, был ли успешно скачан файл
if not exist "python_installer.exe" (
echo Ошибка загрузки установщика Python 3.
pause
exit /b 1
)
REM Установка Python 3
echo Установка...
echo PS - не забудьте ее разрешить в соседнем окне
python_installer.exe /quiet InstallAllUsers=1 PrependPath=1
del /q /f python_installer.exe
REM Нужно обновить системные PATH, но в этом сеансе не получится
echo Вроде бы все прошло удачно, но нужно обновить окружение,
echo закройте это окно и запустите скрипт еще раз.
pause
exit
)
) else (
echo Похоже Python 3 имеется в системе.
)
REM Проверяем наличие необходимых библиотек
set "modules=requests dnspython ipaddress configparser httpx"
for %%m in (%modules%) do (
pip show %%m >NUL 2>&1
if ERRORLEVEL 1 (
echo Установка библиотеки %%m...
pip install %%m
if ERRORLEVEL 1 (
echo Не удалось установить библиотеку %%m. Проверьте pip.
exit /b 1
)
)
)
REM Скачиваем main.py
echo Загрузка Domain Mapper...
powershell -Command "if ($PSVersionTable.PSVersion.Major -ge 3) {Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/main.py' -OutFile 'main.py'} else {Start-BitsTransfer -Source 'https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/main.py' -Destination 'main.py'}"
if not exist "main.py" (
echo Ошибка загрузки Domain Mapper.
pause
exit /b 1
)
cls
REM Запуск main.py в Python 3
echo Запускаем...
python main.py
if ERRORLEVEL 1 (
echo Ошибка выполнения main.py.
pause
del /q /f main.py
exit /b 1
)
move /y domain-ip-resolve.txt %UserProfile%\Desktop\domain-ip-resolve.txt
echo Программа завершена.
endlocal
del /q /f main.py
exit

130
main.py
View File

@@ -8,9 +8,25 @@ from collections import defaultdict
import dns.asyncresolver
import httpx
from colorama import Fore, Style
from colorama import init
#Цвета
init(autoreset=True)
def yellow(text):
return f"{Fore.YELLOW}{text}{Style.RESET_ALL}"
def green(text):
return f"{Fore.GREEN}{text}{Style.RESET_ALL}"
def cyan(text):
return f"{Fore.CYAN}{text}{Style.RESET_ALL}"
def red(text):
return f"{Fore.RED}{text}{Style.RESET_ALL}"
# Read configuration file
# Читаем конфигурацию
def read_config(filename):
try:
config = configparser.ConfigParser()
@@ -27,37 +43,37 @@ def read_config(filename):
run_command = config.get('run') or ''
dns_server_indices = list(map(int, config.get('dnsserver', '').split())) if config.get('dnsserver') else []
print("\033[33mЗагружена конфигурация из config.ini:\033[0m")
print(f"{yellow('Загружена конфигурация из config.ini:')}")
print(f"Сервисы для проверки: {service if service else 'не указаны'}")
print(f"Использовать DNS сервер: {dns_server_indices if dns_server_indices else 'не указано'}")
print(f"Количество потоков: {request_limit}")
print(f"Фильтр Cloudflare: {'включен' if cloudflare == 'yes' else 'вЫключен' if cloudflare == 'no' else 'не указано'}")
print(f"Фильтр Cloudflare: {'включен' if cloudflare == 'yes' else 'выключен' if cloudflare == 'no' else 'не указано'}")
print(f"Файл результатов: {filename}")
print(f"Формат сохранения: {'только IP' if filetype == 'ip' else 'Linux route' if filetype == 'unix' else 'CIDR-нотация' if filetype == 'cidr' else 'Windows route' if filetype == 'win' else 'не указан'}")
print(f"Шлюз для маршрутов: {gateway if gateway else 'не указан'}")
print(f"Выполнить при заврешении: {run_command if run_command else 'не указано'}")
print(f"Выполнить при завершении: {run_command if run_command else 'не указано'}")
return service, request_limit, filename, cloudflare, filetype, gateway, run_command, dns_server_indices
except Exception as e:
print(f"\033[33mОшибка загрузки config.ini:\033[0m {e}\nИспользуются настройки 'по умолчанию'.")
print(f"{yellow('Ошибка загрузки config.ini:')} {e}\nИспользуются настройки 'по умолчанию'.")
return '', 20, 'domain-ip-resolve.txt', '', '', '', '', []
def gateway_input(gateway):
if not gateway:
input_gateway = input(f"Укажите \033[32mшлюз\033[0m или \033[32mимя интерфейса\033[0m: ")
input_gateway = input(f"Укажите {green('шлюз')} или {green('имя интерфейса')}: ")
if input_gateway:
return input_gateway.strip()
else:
return gateway
# Function to limit requests
# Ограничение числа запросов
def get_semaphore(request_limit):
return defaultdict(lambda: Semaphore(request_limit))
# Initialize semaphore for limiting requests
# Инициализация semaphore для ограничения запросов
def init_semaphores(request_limit):
return get_semaphore(request_limit)
@@ -80,6 +96,7 @@ async def load_urls(url):
return {}
# Загрузка списка DNS серверов
async def load_dns_servers(url):
try:
async with httpx.AsyncClient() as client:
@@ -98,6 +115,7 @@ async def load_dns_servers(url):
return {}
# Загрузка IP-адресов cloudflare
async def get_cloudflare_ips():
try:
async with httpx.AsyncClient() as client:
@@ -128,22 +146,17 @@ async def resolve_domain(domain, resolver, semaphore, dns_server_name, null_ips_
elif ip_address in cloudflare_ips:
cloudflare_ips_count[0] += 1
else:
print(f"\033[36m{domain} IP адрес: {ip_address} получен от {dns_server_name}\033[0m")
print(f"{Fore.CYAN}{domain} IP адрес: {ip_address} получен от - {dns_server_name}{Style.RESET_ALL}")
return ips
except Exception as e:
print(f"\033[31mНе удалось разрешить {domain} через {dns_server_name}\033[0m")
print(f"{Fore.RED}Не удалось разрешить {domain} через {dns_server_name}{Style.RESET_ALL}")
return []
async def resolve_dns(service, url, dns_servers, cloudflare_ips, unique_ips_all_services, semaphore, null_ips_count,
async def resolve_dns(service, dns_names, dns_servers, cloudflare_ips, unique_ips_all_services, semaphore, null_ips_count,
cloudflare_ips_count):
try:
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
dns_names = response.text.split('\n')
print(f"\033[33mАнализ DNS имен платформы {service}...\033[0m")
print(f"{Fore.YELLOW}Анализ DNS имен платформы {service}...{Style.RESET_ALL}")
tasks = []
for server_name, servers in dns_servers:
@@ -170,41 +183,51 @@ async def resolve_dns(service, url, dns_servers, cloudflare_ips, unique_ips_all_
return ""
def check_service_config(service, urls):
def check_service_config(service, urls, local_dns_names):
if service:
if service.strip().lower() == "all":
return list(urls.keys())
services = list(urls.keys())
if local_dns_names:
services.append("Мой список DNS")
return services
else:
return [s.strip() for s in service.split(',')]
else:
selected_services = []
while True:
print("\n\033[33mВыберите сервисы:\033[0m")
print(f"\n{yellow('Выберите сервисы:')}")
print("0. Выбрать все")
for idx, (service, url) in enumerate(urls.items(), 1):
print(f"{idx}. {service.capitalize()}")
if local_dns_names:
print(f"{len(urls) + 1}. Мой список DNS")
selection = input("\nУкажите номера сервисов через пробел и нажмите \033[32mEnter\033[0m: ")
selection = input(f"\nУкажите номера сервисов через пробел и нажмите {green('Enter')}: ")
if selection.strip():
selections = selection.split()
if '0' in selections: # User selected all services
selected_services = list(urls.keys())
if local_dns_names:
selected_services.append('Мой список DNS')
break
else:
selected_services = [list(urls.keys())[int(sel) - 1] for sel in selections if sel.isdigit()
and 1 <= int(sel) <= len(urls)]
if str(len(urls) + 1) in selections and local_dns_names:
selected_services.append('Мой список DNS')
break
return selected_services
# Промт на исключение IP-адресов cloudflare
def check_include_cloudflare(cloudflare):
if cloudflare.lower() == 'yes':
return True
elif cloudflare.lower() == 'no':
return False
else:
return input("\nИсключить IP адреса Cloudflare из итогового списка? (\033[32myes\033[0m "
"- исключить, \033[32mEnter\033[0m - оставить): ").strip().lower() == "yes"
return input(f"\nИсключить IP адреса Cloudflare из итогового списка? ({green('yes')} "
f"- исключить, ({green('Enter')} - оставить): ").strip().lower() == "yes"
def check_dns_servers(dns_servers, dns_server_indices):
@@ -220,15 +243,15 @@ def check_dns_servers(dns_servers, dns_server_indices):
return selected_dns_servers
while True:
print("\n\033[33mКакие DNS сервера использовать?\033[0m")
print(f"\n{yellow('Какие DNS сервера использовать?')}")
print("0. Выбрать все")
for idx, (name, servers) in enumerate(dns_server_options, 1):
print(f"{idx}. {name}: {', '.join(servers)}")
selection = input("\nУкажите номера DNS серверов через пробел и нажмите \033[32mEnter\033[0m: ")
selection = input(f"\nУкажите номера DNS серверов через пробел и нажмите {green('Enter')}: ")
if selection.strip():
selections = selection.split()
if '0' in selections: # User selected all DNS servers
if '0' in selections:
selected_dns_servers = dns_server_options
break
else:
@@ -243,14 +266,15 @@ def check_dns_servers(dns_servers, dns_server_indices):
return selected_dns_servers
# Выбор формата сохранения списка разрешенных DNS имен
def process_file_format(filename, filetype, gateway):
if not filetype:
filetype = input("\n\033[33mВ каком формате сохранить файл?\033[0m"
"\n\033[32mwin\033[0m - route add IP mask MASK GATEWAY"
"\n\033[32munix\033[0m - ip route IP/MASK GATEWAY"
"\n\033[32mcidr\033[0m - IP/MASK"
"\n\033[32mПустое значение\033[0m - только IP"
"\nВаш выбор: ")
filetype = input(f"\n{yellow('В каком формате сохранить файл?')}"
f"\n{green('win')} - route add IP mask MASK GATEWAY"
f"\n{green('unix')} - ip route IP/MASK GATEWAY"
f"\n{green('cidr')} - IP/MASK"
f"\n{green('Пустое значение')} - только IP"
f"\nВаш выбор: ")
if filetype.lower() in ['win', 'unix']:
gateway = gateway_input(gateway)
@@ -285,28 +309,36 @@ def process_file_format(filename, filetype, gateway):
pass
# Ну чо, погнали?!
async def main():
# Load configuration
# Инициализация настроек из config.ini
service, request_limit, filename, cloudflare, filetype, gateway, run_command, dns_server_indices = read_config('config.ini')
# Load URLs
platform_db_url = "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platformdb"
urls = await load_urls(platform_db_url)
# Get selected services from user
selected_services = check_service_config(service, urls)
# Load local DNS names from "my-dns-list.txt" if it exists
local_dns_names = []
if os.path.exists('my-dns-list.txt'):
with open('my-dns-list.txt', 'r', encoding='utf-8-sig') as file:
local_dns_names = [line.strip() for line in file if line.strip()]
# Load DNS servers
# Выбор сервисов
selected_services = check_service_config(service, urls, local_dns_names)
# Загрузка списка DNS-серверов
dns_db_url = "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/dnsdb"
dns_servers = await load_dns_servers(dns_db_url)
# Get selected DNS servers from config or user
# Выбор DNS-серверов
selected_dns_servers = check_dns_servers(dns_servers, dns_server_indices)
# Get Cloudflare IP addresses
# Инициализация IP-адресов Cloudflare
cloudflare_ips = await get_cloudflare_ips()
# Check if Cloudflare IPs should be included or excluded
# Фильтр Cloudflare
include_cloudflare = check_include_cloudflare(cloudflare)
unique_ips_all_services = set()
@@ -316,8 +348,18 @@ async def main():
tasks = []
for service in selected_services:
tasks.append(resolve_dns(service, urls[service], selected_dns_servers, cloudflare_ips, unique_ips_all_services,
semaphore, null_ips_count, cloudflare_ips_count))
if service == 'Мой список DNS':
tasks.append(resolve_dns(service, local_dns_names, selected_dns_servers, cloudflare_ips, unique_ips_all_services,
semaphore, null_ips_count, cloudflare_ips_count))
else:
# Загрузка DNS имен служб
dns_names_url = urls[service]
async with httpx.AsyncClient() as client:
response = await client.get(dns_names_url)
response.raise_for_status()
dns_names = response.text.splitlines()
tasks.append(resolve_dns(service, dns_names, selected_dns_servers, cloudflare_ips, unique_ips_all_services,
semaphore, null_ips_count, cloudflare_ips_count))
results = await asyncio.gather(*tasks)
@@ -325,7 +367,7 @@ async def main():
for result in results:
file.write(result)
print("\n\033[33mПроверка завершена.\033[0m")
print(f"\n{yellow('Проверка завершена.')}")
print("Использовались DNS сервера: " + ', '.join(
[f'{pair[0]} ({", ".join(pair[1])})' for pair in selected_dns_servers]))
if include_cloudflare:
@@ -341,8 +383,8 @@ async def main():
else:
print("\nРезультаты сохранены в файл:", filename)
if os.name == 'nt':
input("Нажмите \033[32mEnter\033[0m для выхода...")
input(f"Нажмите {green('Enter')} для выхода...")
if __name__ == "__main__":
asyncio.run(main())
asyncio.run(main())

2
my-dns-list.txt Normal file
View File

@@ -0,0 +1,2 @@
exeple.com
1.exeple.ru

View File

@@ -61,6 +61,7 @@ rr3---sn-4g5lznlz.googlevideo.com
rr3---sn-ixh7yn7d.googlevideo.com
rr3---sn-p5qs7n6d.googlevideo.com
rr3---sn-q4flrn7y.googlevideo.com
rr4.sn-4g5edndy.googlevideo.com
rr4.sn-q4flrnle.googlevideo.com
rr4.sn-jvhnu5g-n8vy.googlevideo.com
rr4.sn-p5qlsn7d.googlevideo.com

View File

@@ -1,6 +1,6 @@
requests~=2.31.0
dnspython~=2.6.1
ipaddress~=1.0.23
configparser~=7.0.0
httpx~=0.27.0
httpx~=0.27.0
colorama~=0.4.6