dns-propagation.py
Проверка распространения DNS-записей через несколько публичных резолверов: Google (8.8.8.8), Cloudflare (1.1.1.1), Quad9 (9.9.9.9) и другие. Поддерживает типы записей A, AAAA, MX, CNAME, TXT. Полезно после смены DNS или миграции.
Зависимости
- Python 3.9+
dig(пакетdnsutils/bind-utils)
Использование
# Проверка A-записи python3 dns-propagation.py example.com # Проверка MX-записей python3 dns-propagation.py example.com --type MX # Проверка через конкретные серверы python3 dns-propagation.py example.com --servers 8.8.8.8,1.1.1.1
Код
#!/usr/bin/env python3
"""dns-propagation.py — проверка распространения DNS-записей."""
import subprocess
import argparse
import sys
DEFAULT_SERVERS = {
"Google": "8.8.8.8",
"Google-2": "8.8.4.4",
"Cloudflare": "1.1.1.1",
"Cloudflare-2": "1.0.0.1",
"Quad9": "9.9.9.9",
"OpenDNS": "208.67.222.222",
"Yandex": "77.88.8.8",
}
def query_dns(domain: str, server: str, record_type: str) -> list[str]:
"""Запрашивает DNS-запись через указанный резолвер."""
try:
result = subprocess.run(
["dig", f"@{server}", domain, record_type, "+short", "+time=3", "+tries=1"],
capture_output=True, text=True, timeout=10
)
lines = [l.strip() for l in result.stdout.strip().splitlines() if l.strip()]
return lines if lines else ["— нет ответа —"]
except subprocess.TimeoutExpired:
return ["— таймаут —"]
except FileNotFoundError:
print("Ошибка: утилита dig не найдена. Установите dnsutils.", file=sys.stderr)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="Проверка распространения DNS")
parser.add_argument("domain", help="Домен для проверки")
parser.add_argument("--type", default="A", dest="rtype",
help="Тип записи: A, AAAA, MX, CNAME, TXT (по умолчанию A)")
parser.add_argument("--servers", help="Свои DNS-серверы через запятую")
args = parser.parse_args()
if args.servers:
servers = {ip: ip for ip in args.servers.split(",")}
else:
servers = DEFAULT_SERVERS
print(f"\n Домен: {args.domain}")
print(f" Тип: {args.rtype}")
print(f" {'─' * 50}")
results = {}
for name, ip in servers.items():
answers = query_dns(args.domain, ip, args.rtype)
results[name] = answers
answer_str = ", ".join(answers)
print(f" {name:<16} ({ip:<16}) → {answer_str}")
# Проверяем консистентность
unique = set()
for answers in results.values():
unique.add(tuple(sorted(answers)))
print(f" {'─' * 50}")
if len(unique) == 1 and "— нет ответа —" not in list(unique)[0]:
print(" ✓ Записи консистентны на всех серверах")
elif len(unique) == 1:
print(" ✗ Запись не найдена ни на одном сервере")
else:
print(f" ⚠ Обнаружены расхождения ({len(unique)} варианта ответа)")
print(" DNS-записи ещё не распространились полностью")
if __name__ == "__main__":
main()