# 這個腳本是實作Linux中traceroute程式的,是探測從我們這個機器到我們要探測的IP地址中間都需要經過那些路由,
# 原理:我們的機器發送UDP高埠的資料包,發送給目的地址,首先設定ttl為1,然后逐次增加,在沒有到達我們的目的IP
# 地址的路由,會發送ICMP的超時報文,然后我們從中提取IP地址,因為我們發送的是高埠的報文,到達目的地址的時候,
# 目的地址會發送ICMP的埠不可達報文,這樣我們就探測出從我們源埠到目的埠的路由,
from scapy.all import *
import struct,re,random
# 跟我們實作ping程式的想法是一樣的,首先構造一個發送一個UDP報文的函式,
# 入參為目的地址,ttl數,
def traceroute_one(dst,ttl_no,dport):
# 定義發包時間,
send_time = time.time()
try:
# 發送一個包,接收一個包,
traceroute_one_reply = sr1(IP(dst=dst, ttl=ttl_no) / UDP(dport=dport) / b'hello world', timeout=1,
verbose=False)
# 判斷ICMP包是不是超時回答,
if traceroute_one_reply.getlayer(ICMP).type == 11 and traceroute_one_reply.getlayer(ICMP).code == 0:
# 提取源地址
src_ip = traceroute_one_reply.getlayer(IP).src
# 定義接收時間,
recv_time = time.time()
# 計算時間ms數
mid_time = (recv_time - send_time) * 1000
# 回傳,
return 1,src_ip,mid_time
# 這里接接收的是最后一跳,ICMP應該是埠不可達,
elif traceroute_one_reply.getlayer(ICMP).type == 3 and traceroute_one_reply.getlayer(ICMP).code == 3:
# 下邊處理是一樣的,
src_ip = traceroute_one_reply.getlayer(IP).src
recv_time = time.time()
mid_time = (recv_time - send_time) * 1000
return 2, src_ip, mid_time
except Exception as e:
return None
def traceroute(dst,hops):
# 目的埠從33434開始算起,入參為目的地址,我們想要查找的路由的條數,
dport = 33434
hop = 0
# 進行回圈包,
while hop < hops:
hop += 1
# 這里需要改變埠,
dport += hop
# 發送一個包,獲取回傳值,
traceroute_result = traceroute_one(dst,hop,dport)
# 如果出現了錯誤,列印*號,
if traceroute_result == None:
print('*')
# 這里代表中間路由,我們進行列印資訊,
elif traceroute_result[0] == 1:
print("%d %s %4.2fms" % (hop,traceroute_result[1],traceroute_result[2]))
# 最后一個包,為埠不可達,列印資訊后,需要退出回圈,因為已經到達目的地址了,雖然可能沒有達到我們定義的條數,
elif traceroute_result[0] == 2:
print("%d %s %4.2fms" % (hop, traceroute_result[1], traceroute_result[2]))
break
time.sleep(1)
if __name__ == "__main__":
traceroute('180.101.49.12',10)
# 接下來我們就可以使用wirshark進行抓包來看一下,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/241733.html
標籤:Python
