← все скрипты

dns-propagation.py

python 3.9+ ~ 65 строк обновлён 3 февраля 2026

Проверка распространения DNS-записей через несколько публичных резолверов: Google (8.8.8.8), Cloudflare (1.1.1.1), Quad9 (9.9.9.9) и другие. Поддерживает типы записей A, AAAA, MX, CNAME, TXT. Полезно после смены DNS или миграции.

Зависимости

Использование

# Проверка 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()