Я пытаюсь выполнить простой тест трассировки трассировки SYN TCP в рамках более крупного проекта. Я использую Python 3.7 на Windows, но хотел бы, чтобы код работал на Windows, Ma c и Linux. Я хотел бы использовать сокеты для достижения этой цели, а не просто вызывать команду traceroute в ОС, частично потому, что я хочу узнать, как их использовать, а также потому, что не на всех платформах установлен traceroute по умолчанию, а выходные форматы значительно различаются. Я заинтересован в получении сообщения ICMP TTL Exceeded для каждого прыжка и достаточно точном расчете времени ответа.
Я могу создать сокет для подключения к целевому веб-серверу, но если установить TTL на меньшее число из прыжков, я должен получить сообщение ICMP типа 11 (превышено TTL) от маршрутизатора вдоль пути, когда TTL достигает 0.
for i in range(1,10):
print(f"Tracing TTL={i}")
try:
s = socket.socket(socket.AF_INET,type=socket.SOCK_STREAM)
s.setsockopt(socket.SOL_IP, socket.IP_TTL, i)
s.connect((target, 443))
s.recv(1500)
s.close()
except TimeoutError as e:
print(f"Timeout TTL={i}")
Код выше, кажется, игнорирует ошибку ICMP, и просто раз через несколько секунд. PCAP показывает, что я получаю сообщения ICMP, но я не делаю то, что мне нужно для их получения.
Я видел ссылку на установку параметра IP IN.IP_RECVERR
, но я также прочитал, что это Linux только и не рекомендуется, так как это спецификация платформы c. Какой самый pythoni c способ перехватить ICMP-ответ от маршрутизатора для каждого отправленного пакета? Является ли это тем, что модуль сокета может обрабатывать как часть TCP-соединения, или мне нужно асинхронно прослушивать входящие ICMP и писать свой собственный обработчик для перехвата и сопоставления их с исходным сообщением?
Я гуглял целую вечность пытался найти какое-то руководство о том, как ICMP и TCP должны взаимодействовать на уровне сокетов, но пока не нашел ничего полезного. Я хотел бы, чтобы мой код мог обрабатывать любые обычные сообщения о превышении TTL, недостижимом, отказанном типе. Если кто-то может указать мне в направлении чего-то, что объясняет, как это сделать, я был бы очень благодарен.
Я попытался сделать это со Scapy, который отлично работает для traceroute, но не выполняет хорошую работу по времени каждого прыжка, он сообщает о гораздо большей задержке между отправкой и получением, чем на самом деле видно на захватывает, вероятно, из-за того, как он собирает и обрабатывает данные.