mirror of
https://github.com/Ground-Zerro/DomainMapper.git
synced 2025-12-10 01:47:18 +07:00
316 lines
13 KiB
Python
316 lines
13 KiB
Python
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()
|