commit b27803241c2ef1aea33d4a5cb365e9ec1f2b0aff Author: GRayHook Date: Sun Apr 5 12:56:33 2026 +0700 init diff --git a/dns_domains_from_dump.py b/dns_domains_from_dump.py new file mode 100755 index 0000000..257e972 --- /dev/null +++ b/dns_domains_from_dump.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +""" +Извлекает уникальные QNAME из текстового вывода tcpdump (UDP/TCP DNS). +Ответы и соответствие IP не учитываются — только запрошенные имена. +""" + +from __future__ import annotations + +import argparse +import re +import sys +from typing import Set, TextIO + +# Запрос: + ? . (<остаток длины>) +# Примеры: "47028+ A? talk-pilsner.kakao.com. (40)" +# TCP: "... length 48 31523+ A? api.example.com. (46)" +_QUERY = re.compile( + r""" + (? int: + parser = argparse.ArgumentParser( + description="Список уникальных доменов из текстового вывода tcpdump (DNS-запросы)." + ) + parser.add_argument( + "file", + nargs="?", + default="-", + help="Файл с дампом; по умолчанию или «-» — читать stdin", + ) + args = parser.parse_args() + + inp: TextIO + if args.file == "-": + inp = sys.stdin + else: + inp = open(args.file, encoding="utf-8", errors="replace") + + seen: Set[str] = set() + try: + for line in inp: + for m in _QUERY.finditer(line): + name = m.group(3).rstrip(".") + if name and name not in seen: + seen.add(name) + print(name) + finally: + if inp is not sys.stdin: + inp.close() + + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())