You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
#!/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
# Запрос: <txid>+ <TYPE>? <qname>. (<остаток длины>)
# Примеры: "47028+ A? talk-pilsner.kakao.com. (40)"
# TCP: "... length 48 31523+ A? api.example.com. (46)"
_QUERY = re . compile (
r """
(?<! \ d) # не середина числа
( \ d+) \ + # txid и флаг запроса
\ s+
(?: \ [[^ \ ]]+ \ ] \ s+)* # опц. блоки tcpdump: [1au], [bad udp cksum ...], ...
( \ S+?) # тип (A, AAAA, PTR, …)
\ ?
\ s+
([^ \ s()]+) # QNAME (с завершающей точкой в дампе)
\ s+
\ ( \ d+ \ ) # длина хвоста пакета
""" ,
re . VERBOSE ,
)
def main ( ) - > 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 ( ) )