Много всего...
This commit is contained in:
Ground-Zerro
2024-08-10 02:03:31 +11:00
parent 966e11db76
commit c148415781
9 changed files with 310 additions and 537 deletions

View File

@@ -24,8 +24,11 @@
**Функции:** **Функции:**
- Скрипт загружает списки доменных имен Antifilter - community edition, а также популярных сервисов и разрешает их в IP-адреса используя публичные DNS-сервера. - Скрипт загружает списки доменных имен Antifilter - community edition, а также популярных сервисов и разрешает их в IP-адреса используя публичные DNS-сервера.
- Итоговый список содержит только уникальные IP-адреса исключая дубликаты, также фильтруются IP-адреса самих DNS-серверов, заглушки в виде редиректа на localhost и (по желанию) IP-адреса Cloudflare. - Итоговый список содержит только уникальные IP-адреса исключая дубликаты, также фильтруются IP-адреса самих DNS-серверов, заглушки в виде редиректа на localhost и (по желанию) IP-адреса Cloudflare.
- Возможен выбор DNS сервера из установленного в системе, а также Google Public DNS, Quad9, Cloudflare DNS, OpenDNS, Cisco Umbrella, DNS.Watch, Dyn, CleanBrowsing, Alternate DNS, AdGuard DNS, Control D или все сразу.
- Разрешение DNS имени происходит используя каждый из указанных пользователем DNS серверов и не останавливается при первом же успешном получении его IP-адреса.
- С помощью конфигурационного файла можно настроить все параметры работы в т.ч. задать список сервисов, формат сохранения, количество потоков, имя выводного файла и другие. - С помощью конфигурационного файла можно настроить все параметры работы в т.ч. задать список сервисов, формат сохранения, количество потоков, имя выводного файла и другие.
*Обратите внимание, что для эффекта от точечной маршрутизации близкого к 100% резолвить DNS имена необходимо из сети, в которой предполагается их использование при помощи DNS серверов, настроенных в роутере/хосте...*
**Автоматизация:** **Автоматизация:**
@@ -34,10 +37,7 @@
**Зависимости:** Для работы Domain Mapper необходимо наличие следующих библиотек Python: **Зависимости:** Для работы Domain Mapper необходимо наличие следующих библиотек Python:
- requests - requests, dnspython, ipaddress, configparser, httpx
- dnspython
- ipaddress
- configparser
*Не забудьте установить их перед запуском:* *Не забудьте установить их перед запуском:*
``` ```
@@ -51,22 +51,3 @@ pip3 install -r requirements.txt
###### Протестировано в Ubuntu 20.04 и Windows 10/11 ###### Протестировано в Ubuntu 20.04 и Windows 10/11
## Domain Mapper SDS (main-SDS.py)
###### Небольшой форк основного кода
**Отличия:**
- Иной подход к работе меню.
- Возможность выбора DNS серверов, которые будут использованы для проверки, в т.ч.: Системный DNS, Google, Quad9, OpenDNS, Cloudflare, CleanBrowsing, Alternate DNS, AdGuard DNS (пишите если нужно что-то еще добавить).
*В отличии от основной программы проверка DNS имени будет производиться не до первого успешного разрешения его IP-адреса, а последовательно используя каждый из указанных пользователем DNS серверов. По другому говоря - скрипт будет пытаться получить IP адрес DNS имени отдельно у каждого DNS сервера, что повышает шансы разрешить его IP в случае, например "заглушек" провайдера.*
- Список сервисов и DNS серверов исключен из кода, теперь они загружаются с Github.
*Таким образом пользователь получит актуальные данные запустив даже старую версию скрипта.*
- Автоматизация при помощи config.ini пока частичная.
- Более долгая работа т.к. DNS имя запрашивается у каждого из указанных DNS серверов.
*Можно частично компенсировать увеличением числа используемых потоков, однако будьте осторожны - не превысьте количество установленных DNS сервером запросов в секунду, чтобы не получать от него таймаут вместо разрешенного IP-адреса.*

View File

@@ -1,29 +1,67 @@
[DomainMapper] [DomainMapper]
# Имена сервисов, разделенные запятыми, для разрешения доменных имен в IP-адреса без запроса у пользователя # Имена сервисов, разделенные запятыми, для разрешения доменных имен в IP-адреса без запроса у пользователя, если не указано (по умолчанию) - пользователю будет выведено меню выбора
# доступные опции: 'Antifilter community edition', 'Youtube', 'Facebook', 'Openai', 'Tik-Tok', 'Instagram', 'Twitter', 'Netflix', 'Bing', 'Adobe', 'Apple', 'Google', 'Tor-Truckers', 'Search-engines' # опции:
# 'all' - проверить все сервисы, если не указано (по умолчанию) - пользователю будет выведено меню выбора # all - проверить все сервисы
# Antifilter community edition - список заблокированных DNS имен формируемый сообществом
# Youtube
# Facebook
# Openai
# Tik-Tok
# Instagram
# Twitter
# Netflix
# Bing
# Adobe
# Apple
# Google
# Tor-Truckers - торрент трекеры
# Search-engines - поисковые системы
service = service =
# Включить фильтрацию IP-адресов cloudflare и не записывать их в файл результатов # DNS сервера (номер), разделенные пробелом, которые будут использоваться для разрешения доменных имен, если не указано (по умолчанию) - пользователю будет выведено меню выбора
# доступные опции: 'yes', 'no', если значение пусте (по умолчанию) - пользователю будет выведен запрос с подсказкой # опции:
# 0 - использовать все доступные DNS серверы
# 1 - Системный DNS
# 2 - Google Public DNS
# 3 - Quad9
# 4 - Cloudflare DNS
# 5 - OpenDNS
# 6 - Cisco Umbrella
# 7 - DNS.Watch
# 8 - Dyn
# 0 - CleanBrowsing
# 10 - Alternate DNS
# 11 - AdGuard DNS
# 12 - Control D
dnsserver =
# Включить фильтрацию IP-адресов cloudflare и не записывать их в файл результатов, если не указано (по умолчанию) - пользователю будет выведен запрос с подсказкой
# опции:
# yes - исключить IP адреса cloudflare из итогового списка
# no - оставить IP адреса cloudflare в итоговом списке
cloudflare = cloudflare =
# Имя выходного файла # Имя конечного файла, если не указано (по умолчанию) - будет использоваться имя фала "domain-ip-resolve.txt" в каталоге со скриптом
# доступные опции: 'имя_файла', 'полный_путь/имя_файла', если не указано - будет использоваться имя фала "domain-ip-resolve.txt" в папке со скриптом # опции:
# имя_файла - файл с указанным именем будет сохранени в каталоге со скриптом
# полный_путь/имя_файла - файл будет сохранен с указанным именем в указанной каталоге
filename = filename =
# Количество потоков сканирования # Количество потоков сканирования, если не указано (по умолчанию) - будет использоваться 20 потоков
# если не указано (по умолчанию) - будет использоваться 20 потоков
threads = threads =
# Тип выходного файла # Формат сохранения файла результатов, если не указано (по умолчанию) - пользователю будет выведен запрос с подсказкой
# доступные опции: 'ip' - только "IP" адрес, 'unix' - "ip rote %IP% mask/%mask% %gateway%", cidr' - "IP/маска", 'win' - "rote add %IP% mask %mask% %gateway%" # опции:
# если не указано (по умолчанию) - пользователю будет выведен запрос с подсказкой # ip - только IP адрес
# unix - ip rote %IP%/32 %gateway%
# cidr - IP/32
# win - rote add %IP% mask 255.255.255.255 %gateway%
filetype = filetype =
# адрес шлюза - используется при сохранении IP-адресов в 'win' или 'unix' формате, если не указан (по умолчанию) - пользователю будет выведен запрос с подсказкой # адрес шлюза - используется при сохранении IP-адресов в 'win' или 'unix' формате, если не указан (по умолчанию) - пользователю будет выведен запрос с подсказкой
gateway = gateway =
# Команда для консоли после завершения скриптом всех операций, может быть полезно для автоматизации и комбинирования с другим скриптом, кодом или программой # Команда для консоли после завершения скриптом всех операций, может быть полезно для автоматизации и комбинирования с другим скриптом, кодом или программой
# доступные опции: 'исполняемая_команда_для_консоли' # опции:
# исполняемая_команда_для_консоли
run = run =

11
dnsdb Normal file
View File

@@ -0,0 +1,11 @@
Google Public DNS: 8.8.8.8 8.8.4.4
Quad9: 9.9.9.9 149.112.112.112
Cloudflare DNS: 1.1.1.1 1.0.0.1
OpenDNS: 208.67.222.222 208.67.220.220
Cisco Umbrella: 208.67.222.222 208.67.220.220
DNS.Watch: 84.200.69.80 84.200.70.40
Dyn: 216.146.35.35 216.146.36.36
CleanBrowsing: 185.228.168.9 185.228.169.9
Alternate DNS: 76.76.19.19 76.223.122.150
AdGuard DNS: 94.140.14.14 94.140.15.15
Control D: 76.76.2.0 76.76.10.0

View File

@@ -1,7 +0,0 @@
Google: 8.8.8.8 8.8.4.4
Quad9: 9.9.9.9 149.112.112.112
OpenDNS: 208.67.222.222 208.67.220.220
Cloudflare: 1.1.1.1 1.0.0.1
CleanBrowsing: 185.228.168.9 185.228.169.9
Alternate DNS: 76.76.19.19 76.223.122.150
AdGuard DNS: 94.140.14.14 94.140.15.15

View File

@@ -1,315 +0,0 @@
import configparser
import ipaddress
import os
import re
from concurrent.futures import ThreadPoolExecutor, as_completed
import dns.resolver
import requests
# Function to load URLs from external file
def load_urls(url):
try:
response = requests.get(url)
response.raise_for_status()
lines = response.text.split('\n')
urls = {}
for line in lines:
if line.strip():
service, url = line.split(': ', 1)
urls[service.strip()] = url.strip()
return urls
except Exception as e:
print(f"Ошибка при загрузке списка платформ: {e}")
return {}
# Function to load DNS servers from external file
def load_dns_servers(url):
try:
response = requests.get(url)
response.raise_for_status()
lines = response.text.split('\n')
dns_servers = {}
for line in lines:
if line.strip():
service, servers = line.split(': ', 1)
dns_servers[service.strip()] = servers.strip().split()
return dns_servers
except Exception as e:
print(f"Ошибка при загрузке списка DNS серверов: {e}")
return {}
# Load URLs and DNS servers from external files
platform_db_url = "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platformdb.txt"
dns_db_url = "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/dnsdb.txt"
urls = load_urls(platform_db_url)
dns_servers = load_dns_servers(dns_db_url)
# Function to resolve DNS
def resolve_dns_and_write(service, url, unique_ips_all_services, include_cloudflare, threads, cloudflare_ips_count,
null_ips_count, resolver_nameserver_pairs):
try:
print(f"\033[33mЗагрузка данных - {service}\033[0m")
response = requests.get(url)
response.raise_for_status()
dns_names = response.text.split('\n')
if include_cloudflare:
cloudflare_ips = get_cloudflare_ips()
else:
cloudflare_ips = set()
unique_ips_current_service = set()
print(f"\033[33mАнализ DNS имен платформы: {service}\033[0m")
with ThreadPoolExecutor(max_workers=threads) as executor:
futures = []
for nameserver_pair in resolver_nameserver_pairs:
future = executor.submit(resolve_domains_with_nameservers, dns_names, unique_ips_current_service,
unique_ips_all_services, cloudflare_ips, cloudflare_ips_count, null_ips_count,
nameserver_pair)
futures.append(future)
for future in as_completed(futures):
future.result()
print(f"\033[33mСписок IP-адресов для платформы {service} создан.\033[0m")
return '\n'.join(unique_ips_current_service) + '\n'
except Exception as e:
print(f"Не удалось сопоставить IP адреса {service} его доменным именам.", e)
return ""
# Function to get Cloudflare IP addresses
def get_cloudflare_ips():
try:
response = requests.get("https://www.cloudflare.com/ips-v4/")
response.raise_for_status()
cloudflare_ips = set()
cidr_blocks = re.findall(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2})', response.text)
for cidr in cidr_blocks:
ip_network = ipaddress.ip_network(cidr)
for ip in ip_network:
cloudflare_ips.add(str(ip))
return cloudflare_ips
except Exception as e:
print("Ошибка при получении IP адресов Cloudflare:", e)
return set()
# Function resolve domain using a pair of DNS servers
def resolve_domains_with_nameservers(domains, unique_ips_current_service, unique_ips_all_services, cloudflare_ips,
cloudflare_ips_count, null_ips_count, nameserver_pair):
dns_server_name, nameservers = nameserver_pair
for domain in domains:
domain = domain.strip()
if domain:
for nameserver in nameservers:
resolver = dns.resolver.Resolver()
resolver.nameservers = [nameserver]
resolver.rotate = False
resolver.timeout = 1
resolver.lifetime = 1
try:
ips = resolver.resolve(domain)
for ip in ips:
ip_address = ip.address
if ip_address in ('127.0.0.1', '0.0.0.0') or ip_address in resolver.nameservers:
null_ips_count[0] += 1
elif ip_address in cloudflare_ips:
cloudflare_ips_count[0] += 1
elif ip_address not in unique_ips_all_services:
unique_ips_current_service.add(ip_address)
unique_ips_all_services.add(ip_address)
print(f"\033[36m{domain} IP адрес: {ip_address} получен от {dns_server_name}\033[0m")
except Exception as e:
print(f"\033[31mНе удалось разрешить {domain} через {dns_server_name}\033[0m")
# Function to read configuration file
def read_config(filename):
try:
config = configparser.ConfigParser()
with open(filename, 'r', encoding='utf-8-sig') as file:
config.read_file(file)
if 'DomainMapper' in config:
config = config['DomainMapper']
service = config.get('service') or ''
threads = int(config.get('threads') or 20)
filename = config.get('filename') or 'domain-ip-resolve.txt'
cloudflare = config.get('cloudflare') or ''
filetype = config.get('filetype') or ''
gateway = config.get('gateway') or ''
run_command = config.get('run') or ''
print("Загружена конфигурация из config.ini.")
return service, threads, filename, cloudflare, filetype, gateway, run_command
except Exception as e:
print(f"Ошибка загрузки конфигурации: {e}")
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: ")
if input_gateway:
return input_gateway.strip()
else:
return gateway
# Function to check if 'service' is specified in the configuration file
def check_service_config(service):
if service:
if service.strip().lower() == "all":
return list(urls.keys())
else:
return [s.strip() for s in service.split(',')]
else:
selected_services = []
while True:
if os.name == 'nt':
os.system('cls')
else:
os.system('clear')
print("\nВыберите сервисы:")
for idx, (service, url) in enumerate(urls.items(), 1):
print(f"{idx}. {service.capitalize()}")
selection = input("\nУкажите номера сервисов через пробел и нажмите \033[32mEnter\033[0m: ")
if selection.strip():
selections = selection.split()
selected_services = [list(urls.keys())[int(sel) - 1] for sel in selections if sel.isdigit()
and 1 <= int(sel) <= len(urls)]
break
return selected_services
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"
# Function to select DNS servers
def check_dns_servers():
system_dns_servers = dns.resolver.Resolver().nameservers
selected_dns_servers = []
dns_server_options = [('Системный DNS', system_dns_servers)] + list(dns_servers.items())
while True:
if os.name == 'nt':
os.system('cls')
else:
os.system('clear')
print("\nКакие DNS сервера использовать?")
for idx, (name, servers) in enumerate(dns_server_options, 1):
print(f"{idx}. {name}: {', '.join(servers)}")
selection = input("\nУкажите номера DNS серверов через пробел и нажмите \033[32mEnter\033[0m: ")
if selection.strip():
selections = selection.split()
for sel in selections:
if sel.isdigit():
sel = int(sel)
if 1 <= sel <= len(dns_server_options):
selected_dns_servers.append((dns_server_options[sel-1][0], dns_server_options[sel-1][1]))
break
return selected_dns_servers
def process_file_format(filename, filetype, gateway):
if not filetype:
filetype = input("\nВыберите в каком формате сохранить файл: \n\033[32mwin\033[0m"
" - 'route add %IP% mask %mask% %gateway%', \033[32munix\033[0m"
" - 'ip route %IP%/%mask% %gateway%', \033[32mcidr\033[0m"
" - 'IP/mask', \033[32mEnter\033[0m - только IP: ")
if filetype.lower() in ['win', 'unix']:
gateway = gateway_input(gateway)
try:
with open(filename, 'r', encoding='utf-8-sig') as file:
ips = file.readlines()
except Exception as e:
print(f"Ошибка чтения файла: {e}")
return
if ips:
with open(filename, 'w', encoding='utf-8-sig') as file:
for ip in ips:
if filetype.lower() == 'win':
file.write(f"route add {ip.strip()} mask 255.255.255.255 {gateway}\n")
elif filetype.lower() == 'unix':
file.write(f"ip route {ip.strip()}/32 {gateway}\n")
elif filetype.lower() == 'cidr':
try:
with open(filename, 'r', encoding='utf-8-sig') as file:
ips = file.readlines()
except Exception as e:
print(f"Ошибка чтения файла: {e}")
return
if ips:
with open(filename, 'w', encoding='utf-8-sig') as file:
for ip in ips:
file.write(f"{ip.strip()}/32\n")
else:
pass
def main():
service, threads, filename, cloudflare, filetype, gateway, run_command = read_config('config.ini')
total_resolved_domains = 0
selected_services = check_service_config(service)
resolver_nameserver_pairs = check_dns_servers() # Get selected DNS server pairs
include_cloudflare = check_include_cloudflare(cloudflare)
unique_ips_all_services = set()
cloudflare_ips_count = [0] # To count the number of Cloudflare IPs excluded
null_ips_count = [0] # To count the number of null IPs excluded
with open(filename, 'w', encoding='utf-8-sig') as file:
for service in selected_services:
result = resolve_dns_and_write(service, urls[service], unique_ips_all_services, include_cloudflare,
threads, cloudflare_ips_count, null_ips_count, resolver_nameserver_pairs)
file.write(result)
total_resolved_domains += len(result.split('\n')) - 1
print("\nПроверка завершена.")
print(f"Использовались DNS сервера: {', '.join([f'{pair[0]} ({", ".join(pair[1])})' for pair
in resolver_nameserver_pairs])}")
if include_cloudflare:
print(f"Исключено IP-адресов Cloudflare: {cloudflare_ips_count[0]}")
print(f"Исключено IP-адресов 'заглушек' провайдера: {null_ips_count[0]}")
print(f"Разрешено IP-адресов из DNS имен сервисов: {total_resolved_domains}")
process_file_format(filename, filetype, gateway)
if run_command:
print("\nВыполнение команды после завершения скрипта...")
os.system(run_command)
else:
print("Результаты сохранены в файл:", filename)
if os.name == 'nt':
input("Нажмите \033[32mEnter\033[0m для выхода...")
if __name__ == "__main__":
main()

417
main.py
View File

@@ -1,114 +1,16 @@
import configparser import asyncio
import configparser
import ipaddress import ipaddress
import os import os
import re import re
from concurrent.futures import ThreadPoolExecutor from asyncio import Semaphore
from collections import defaultdict
import dns.resolver import dns.asyncresolver
import requests import httpx
# URLs
urls = {
'Antifilter community edition': "https://community.antifilter.download/list/domains.lst",
'Youtube': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-youtube.txt",
'Facebook': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-facebook.txt",
'Openai': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-openai.txt",
'Tik-Tok': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-tiktok.txt",
'Instagram': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-instagram.txt",
'Twitter': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-twitter.txt",
'Netflix': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-netflix.txt",
'Bing': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-bing.txt",
'Adobe': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-adobe.txt",
'Apple': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-apple.txt",
'Google': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-google.txt",
'Tor-Truckers': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-ttruckers.txt",
'Search-engines': "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platforms/dns-search-engines"
".txt",
}
# Function to resolve DNS # Read configuration file
def resolve_dns_and_write(service, url, unique_ips_all_services, include_cloudflare, threads):
try:
print(f"Загрузка данных - {service}")
response = requests.get(url)
response.raise_for_status()
dns_names = response.text.split('\n')
resolver = dns.resolver.Resolver(configure=False)
resolver.nameservers = ['8.8.8.8', '8.8.4.4', '208.67.222.222', '208.67.220.220', '4.2.2.1', '4.2.2.2',
'149.112.112.112'] # Public DNS servers
resolver.rotate = True
resolver.timeout = 1
resolver.lifetime = 1
if include_cloudflare:
cloudflare_ips = get_cloudflare_ips()
else:
cloudflare_ips = set()
unique_ips_current_service = set() # Set to store unique IP addresses for the current service
print(f"Анализ DNS имен платформы: {service}")
with ThreadPoolExecutor(max_workers=threads) as executor:
futures = []
for domain in dns_names:
if domain.strip():
future = executor.submit(resolve_domain, resolver, domain, unique_ips_current_service,
unique_ips_all_services, cloudflare_ips)
futures.append(future)
# Дождаться завершения всех задач
for future in futures:
future.result()
print(f"Список IP-адресов для платформы {service} создан.")
return '\n'.join(unique_ips_current_service) + '\n'
except Exception as e:
print(f"Не удалось сопоставить IP адреса {service} его доменным именам.", e)
return ""
# Function to get Cloudflare IP addresses
def get_cloudflare_ips():
try:
response = requests.get("https://www.cloudflare.com/ips-v4/")
response.raise_for_status()
cloudflare_ips = set()
# Extract CIDR blocks from the response text using regular expressions
cidr_blocks = re.findall(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2})', response.text)
for cidr in cidr_blocks:
ip_network = ipaddress.ip_network(cidr)
for ip in ip_network:
cloudflare_ips.add(str(ip))
return cloudflare_ips
except Exception as e:
print("Ошибка при получении IP адресов Cloudflare:", e)
return set()
# Function resolve domain
def resolve_domain(resolver, domain, unique_ips_current_service, unique_ips_all_services, cloudflare_ips):
try:
ips = resolver.resolve(domain)
for ip in ips:
ip_address = ip.address
if (ip_address not in ('127.0.0.1', '0.0.0.1') and
ip_address not in resolver.nameservers and
ip_address not in cloudflare_ips and
ip_address not in unique_ips_all_services): # Check for uniqueness
unique_ips_current_service.add(ip_address)
unique_ips_all_services.add(ip_address)
print(f"\033[36m{domain} IP адрес: {ip_address}\033[0m")
except Exception as e:
print(f"\033[31mНе удалось обработать: {domain}\033[0m - {e}")
# Function to read configuration file
def read_config(filename): def read_config(filename):
try: try:
config = configparser.ConfigParser() config = configparser.ConfigParser()
@@ -117,27 +19,28 @@ def read_config(filename):
if 'DomainMapper' in config: if 'DomainMapper' in config:
config = config['DomainMapper'] config = config['DomainMapper']
service = config.get('service') or '' service = config.get('service') or ''
threads = int(config.get('threads') or 20) request_limit = int(config.get('threads') or 20)
filename = config.get('filename') or 'domain-ip-resolve.txt' filename = config.get('filename') or 'domain-ip-resolve.txt'
cloudflare = config.get('cloudflare') or '' cloudflare = config.get('cloudflare') or ''
filetype = config.get('filetype') or '' filetype = config.get('filetype') or ''
gateway = config.get('gateway') or '' gateway = config.get('gateway') or ''
run_command = config.get('run') or '' run_command = config.get('run') or ''
dns_server_indices = list(map(int, config.get('dnsserver', '').split())) if config.get('dnsserver') else []
print("Загружена конфигурация из config.ini.") print("\033[33mЗагружена конфигурация из config.ini:\033[0m")
return service, threads, filename, cloudflare, filetype, gateway, run_command 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"Файл результатов: {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 'не указано'}")
return service, request_limit, filename, cloudflare, filetype, gateway, run_command, dns_server_indices
except Exception as e: except Exception as e:
print(f"Ошибка загрузки конфигурации: {e}") print(f"\033[33mОшибка загрузки config.ini:\033[0m {e}\nИспользуются настройки 'по умолчанию'.")
service = '' return '', 20, 'domain-ip-resolve.txt', '', '', '', '', []
threads = int(20)
filename = 'domain-ip-resolve.txt'
cloudflare = ''
filetype = ''
gateway = ''
run_command = ''
return service, threads, filename, cloudflare, filetype, gateway, run_command
def gateway_input(gateway): def gateway_input(gateway):
@@ -149,64 +52,207 @@ def gateway_input(gateway):
return gateway return gateway
# Function to check if 'service' is specified in the configuration file # Function to limit requests
def check_service_config(service): def get_semaphore(request_limit):
return defaultdict(lambda: Semaphore(request_limit))
# Initialize semaphore for limiting requests
def init_semaphores(request_limit):
return get_semaphore(request_limit)
async def load_urls(url):
try:
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
text = response.text
lines = text.split('\n')
urls = {}
for line in lines:
if line.strip():
service, url = line.split(': ', 1)
urls[service.strip()] = url.strip()
return urls
except Exception as e:
print(f"Ошибка при загрузке списка платформ: {e}")
return {}
async def load_dns_servers(url):
try:
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
text = response.text
lines = text.split('\n')
dns_servers = {}
for line in lines:
if line.strip():
service, servers = line.split(': ', 1)
dns_servers[service.strip()] = servers.strip().split()
return dns_servers
except Exception as e:
print(f"Ошибка при загрузке списка DNS серверов: {e}")
return {}
async def get_cloudflare_ips():
try:
async with httpx.AsyncClient() as client:
response = await client.get("https://www.cloudflare.com/ips-v4/")
response.raise_for_status()
text = response.text
cloudflare_ips = set()
cidr_blocks = re.findall(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2})', text)
for cidr in cidr_blocks:
ip_network = ipaddress.ip_network(cidr)
for ip in ip_network:
cloudflare_ips.add(str(ip))
return cloudflare_ips
except Exception as e:
print("Ошибка при получении IP адресов Cloudflare:", e)
return set()
async def resolve_domain(domain, resolver, semaphore, dns_server_name, null_ips_count, cloudflare_ips,
cloudflare_ips_count):
async with semaphore:
try:
response = await resolver.resolve(domain)
ips = [ip.address for ip in response]
for ip_address in ips:
if ip_address in ('127.0.0.1', '0.0.0.0') or ip_address in resolver.nameservers:
null_ips_count[0] += 1
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")
return ips
except Exception as e:
print(f"\033[31mНе удалось разрешить {domain} через {dns_server_name}\033[0m")
return []
async def resolve_dns(service, url, 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")
tasks = []
for server_name, servers in dns_servers:
resolver = dns.asyncresolver.Resolver()
resolver.nameservers = servers
for domain in dns_names:
domain = domain.strip()
if domain:
tasks.append(resolve_domain(domain, resolver, semaphore[server_name], server_name, null_ips_count,
cloudflare_ips, cloudflare_ips_count))
results = await asyncio.gather(*tasks)
unique_ips_current_service = set()
for result in results:
for ip_address in result:
if ip_address not in unique_ips_all_services:
unique_ips_current_service.add(ip_address)
unique_ips_all_services.add(ip_address)
return '\n'.join(unique_ips_current_service) + '\n'
except Exception as e:
print(f"Не удалось сопоставить IP адреса {service} его доменным именам.", e)
return ""
def check_service_config(service, urls):
if service: if service:
if service.strip().lower() == "all": if service.strip().lower() == "all":
return list(urls.keys()) # Select all available services return list(urls.keys())
else: else:
return [s.strip() for s in service.split(',')] return [s.strip() for s in service.split(',')]
else: else:
selected_services = [] selected_services = []
while True: while True:
if os.name == 'nt': # Для пользователей Windows print("\n\033[33mВыберите сервисы:\033[0m")
os.system('cls') # Очистить экран print("0. Выбрать все")
else:
os.system('clear')
print("\nВыберите сервисы:\n")
print("0 - Отметить все")
for idx, (service, url) in enumerate(urls.items(), 1): for idx, (service, url) in enumerate(urls.items(), 1):
checkbox = "[*]" if service in selected_services else "[ ]" print(f"{idx}. {service.capitalize()}")
print(f"{idx}. {service.capitalize()} {checkbox}")
selection = input("\n\033[32mВведите номер сервиса\033[0m и нажмите Enter (Пустая строка " selection = input("\nУкажите номера сервисов через пробел и нажмите \033[32mEnter\033[0m: ")
"и \033[32mEnter\033[0m для старта): ") if selection.strip():
if selection == "0": selections = selection.split()
selected_services = list(urls.keys()) if '0' in selections: # User selected all services
elif selection.isdigit(): selected_services = list(urls.keys())
idx = int(selection) - 1 break
if 0 <= idx < len(urls): else:
service = list(urls.keys())[idx] selected_services = [list(urls.keys())[int(sel) - 1] for sel in selections if sel.isdigit()
if service in selected_services: and 1 <= int(sel) <= len(urls)]
selected_services.remove(service) break
else:
selected_services.append(service)
elif selection == "":
break
return selected_services return selected_services
# Function to check if to include Cloudflare IPs based on configuration or user input
def check_include_cloudflare(cloudflare): def check_include_cloudflare(cloudflare):
if cloudflare.lower() == 'yes': if cloudflare.lower() == 'yes':
return True return True
elif cloudflare.lower() == 'no': elif cloudflare.lower() == 'no':
return False return False
else: else:
return input("Исключить IP адреса Cloudflare из итогового списка? (\033[32myes\033[0m " return input("\nИсключить IP адреса Cloudflare из итогового списка? (\033[32myes\033[0m "
"- исключить, \033[32mEnter\033[0m - оставить): ").strip().lower() == "yes" "- исключить, \033[32mEnter\033[0m - оставить): ").strip().lower() == "yes"
# Function to process file format def check_dns_servers(dns_servers, dns_server_indices):
system_dns_servers = dns.asyncresolver.Resolver().nameservers
selected_dns_servers = []
dns_server_options = [('Системный DNS', system_dns_servers)] + list(dns_servers.items())
if dns_server_indices:
for idx in dns_server_indices:
if 0 <= idx <= len(dns_server_options):
selected_dns_servers.append((dns_server_options[idx][0], dns_server_options[idx][1]))
return selected_dns_servers
while True:
print("\n\033[33mКакие DNS сервера использовать?\033[0m")
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: ")
if selection.strip():
selections = selection.split()
if '0' in selections: # User selected all DNS servers
selected_dns_servers = dns_server_options
break
else:
for sel in selections:
if sel.isdigit():
sel = int(sel)
if 1 <= sel <= len(dns_server_options):
selected_dns_servers.append(
(dns_server_options[sel - 1][0], dns_server_options[sel - 1][1]))
break
return selected_dns_servers
def process_file_format(filename, filetype, gateway): def process_file_format(filename, filetype, gateway):
if not filetype: if not filetype:
filetype = input("\nВыберите в каком формате сохранить файл: \n\033[32mwin\033[0m" filetype = input("\n\033[33mВ каком формате сохранить файл?\033[0m"
" - 'route add %IP% mask %mask% %gateway%', \033[32munix\033[0m" "\n\033[32mwin\033[0m - route add IP mask MASK GATEWAY"
" - 'ip route %IP%/%mask% %gateway%', \033[32mcidr\033[0m" "\n\033[32munix\033[0m - ip route IP/MASK GATEWAY"
" - 'IP/mask', \033[32mEnter\033[0m - только IP: ") "\n\033[32mcidr\033[0m - IP/MASK"
"\n\033[32mПустое значение\033[0m - только IP"
"\nВаш выбор: ")
if filetype.lower() in ['win', 'unix']: if filetype.lower() in ['win', 'unix']:
# Обработка файлов разных форматов
gateway = gateway_input(gateway) gateway = gateway_input(gateway)
try: try:
@@ -224,7 +270,6 @@ def process_file_format(filename, filetype, gateway):
elif filetype.lower() == 'unix': elif filetype.lower() == 'unix':
file.write(f"ip route {ip.strip()}/32 {gateway}\n") file.write(f"ip route {ip.strip()}/32 {gateway}\n")
elif filetype.lower() == 'cidr': elif filetype.lower() == 'cidr':
# Обработка CIDR формата
try: try:
with open(filename, 'r', encoding='utf-8-sig') as file: with open(filename, 'r', encoding='utf-8-sig') as file:
ips = file.readlines() ips = file.readlines()
@@ -235,47 +280,69 @@ def process_file_format(filename, filetype, gateway):
if ips: if ips:
with open(filename, 'w', encoding='utf-8-sig') as file: with open(filename, 'w', encoding='utf-8-sig') as file:
for ip in ips: for ip in ips:
file.write(f"{ip.strip()}/32\n") # Assuming /32 subnet mask for all IPs file.write(f"{ip.strip()}/32\n")
else: else:
# Сохранить только IP адреса
pass pass
def main(): async def main():
# Read parameters from the configuration file # Load configuration
service, threads, filename, cloudflare, filetype, gateway, run_command = read_config('config.ini') service, request_limit, filename, cloudflare, filetype, gateway, run_command, dns_server_indices = read_config('config.ini')
total_resolved_domains = 0 # Load URLs
selected_services = check_service_config(service) platform_db_url = "https://raw.githubusercontent.com/Ground-Zerro/DomainMapper/main/platformdb"
urls = await load_urls(platform_db_url)
# Check if to include Cloudflare IPs based on configuration or user input # Get selected services from user
selected_services = check_service_config(service, urls)
# Load DNS servers
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
selected_dns_servers = check_dns_servers(dns_servers, dns_server_indices)
# Get Cloudflare IP addresses
cloudflare_ips = await get_cloudflare_ips()
# Check if Cloudflare IPs should be included or excluded
include_cloudflare = check_include_cloudflare(cloudflare) include_cloudflare = check_include_cloudflare(cloudflare)
# Set to store unique IP addresses across all services
unique_ips_all_services = set() unique_ips_all_services = set()
semaphore = init_semaphores(request_limit)
null_ips_count = [0]
cloudflare_ips_count = [0]
tasks = []
# DNS resolution for selected services for service in selected_services:
with open(filename, 'w', encoding='utf-8-sig') as file: # Open file for writing tasks.append(resolve_dns(service, urls[service], selected_dns_servers, cloudflare_ips, unique_ips_all_services,
for service in selected_services: semaphore, null_ips_count, cloudflare_ips_count))
result = resolve_dns_and_write(service, urls[service], unique_ips_all_services, include_cloudflare, threads)
file.write(result) # Write unique IPs directly to the file
total_resolved_domains += len(result.split('\n')) - 1
print("\nПроверка завершена.") results = await asyncio.gather(*tasks)
print(f"Сопоставлено IP адресов доменам: {total_resolved_domains}")
with open(filename, 'w', encoding='utf-8-sig') as file:
for result in results:
file.write(result)
print("\n\033[33mПроверка завершена.\033[0m")
print(
f"Использовались DNS сервера: {', '.join([f'{pair[0]} ({', '.join(pair[1])})' for pair in selected_dns_servers])}")
if include_cloudflare:
print(f"Исключено IP-адресов Cloudflare: {cloudflare_ips_count[0]}")
print(f"Исключено IP-адресов 'заглушек': {null_ips_count[0]}")
print(f"Разрешено IP-адресов из DNS имен: {len(unique_ips_all_services)}")
# Asking for file format if filetype is not specified in the configuration file
process_file_format(filename, filetype, gateway) process_file_format(filename, filetype, gateway)
# Executing the command after the program is completed, if it is specified in the configuration file if run_command:
if run_command is not None and run_command.strip():
print("\nВыполнение команды после завершения скрипта...") print("\nВыполнение команды после завершения скрипта...")
os.system(run_command) os.system(run_command)
else: else:
print("Результаты сохранены в файл:", filename) print("\nРезультаты сохранены в файл:", filename)
if os.name == 'nt': # Для пользователей Windows при запуске из проводника if os.name == 'nt':
input("Нажмите \033[32mEnter\033[0m для выхода...") input("Нажмите \033[32mEnter\033[0m для выхода...")
if __name__ == "__main__": if __name__ == "__main__":
main() asyncio.run(main())

View File

@@ -2,3 +2,5 @@ requests~=2.31.0
dnspython~=2.6.1 dnspython~=2.6.1
ipaddress~=1.0.23 ipaddress~=1.0.23
configparser~=7.0.0 configparser~=7.0.0
httpx~=0.27.0

View File

@@ -1,4 +0,0 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> resolvedns <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DNS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DNS.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...