实验源代码:【免费】基于Traceroute主动测量技术的路由追踪源代码资源-优快云文库
- 实验背景
任务一:了解Ping、Tracert原理,在Windows通过Ping、Tracert命令实现与特定IP之间的交互。使用Wireshark获取相关报文序列,构建基于ICMP Traceroute路由追踪技术的交互规则(以时序图形式展示)并对比分析多次探测下路由追踪的差异。
任务二:使用Python中Scapy模块编写代码,实现ICMP Ping 和ICMP Traceroute路由追踪功能,并对路径进行可视化。代码结果可通过命令进行辅助验证。
任务三:阅读提供的Linux系统下获取的三种主动测量PCAP数据,回答一个问题。“发送端收到的ICMP报文可能不是按照TTL大小顺序返回,发送端是如何确定收到的一个ICMP报文是从哪个中间路由器返回的?”提示:阅读发送报文和返回报文的格式及内容。
- 实验内容
2.1 使用文档及运行样例
2.1.1 项目结构
本项目结构(仅将修改部分列出)如下:
/Windows系统
/代码
/ICMP_Ping.py
/ICMP_Traceroute.py
2.1.2 使用方法
需要提前安装scapy和matplotlib库。
任务一的两个命令如图:
运行任务二的ping程序的一个命令行范例如下:
python ICMP_Ping.py --mode=ping -a 36.152.44.95 -i 10
其中—mode=ping指示了程序命令;-a后面的参数是ping的目的IP地址,范例中的36.152.44.95是www.baidu.com的IP地址;-i后面的参数是设定的TTL参数的值,本例中设为10。
运行任务二的traceroute程序的一个命令行范例如下:
python ICMP_Traceroute.py --mode=trace -a 36.152.44.95
其中—mode=trace指示了程序命令;-a后面的参数是ping的目的IP地址,范例中的36.152.44.95是www.baidu.com的IP地址。
2.2 UML图与主要数据结构
任务二实现ping程序的UML图:
c:ICMP_Ping.py |
m: ICMP_Ping(addr,TTL) |
f: id_ping f: seq_ping f: packet f: request |
任务二实现traceroute程序的UML图:
c: ICMP_Traceroute.py |
m: Tracert_ICMP(des,ttl) m: Tracert(dst,max_ttl) |
f: start_time f: id_ping f: seq_ping f: pkt f: reply f: hops f: rtts f: ttl f: item f: Result f: time_result f: plt |
2.3 主要算法说明
对于ping功能实现,主要是使用了scapy模块的sr1发送以及构造
报文:
id_ping = randint(1, 65535) # 随机产生ping ID位
seq_ping = randint(1, 65535) # 随机产生ping序列号位
packet = IP(dst=addr, ttl=TTL) / ICMP(id=id_ping, seq=seq_ping) / b'This is payload!' # 构造一个数据包
request = sr1(packet,timeout=5) # 使用ping发送给host中的IP
if request:
request.show()
其中为了解决ping功能如果没有ping通的输出问题,与学姐和同学讨论之后在sr1中加入参数timeout=5。
对于traceroute功能实现,因为代码所提供的结构之中已经构建了循环,所以在调用函数只需判断type对应返回不同输出即可:
try:
start_time=time.time()
# 构造IP数据包,设置TTL值
id_ping = randint(1, 65535) # 随机产生ping ID位
seq_ping = randint(1, 65535) # 随机产生ping序列号位
pkt = IP(dst=dst, ttl=ttl) / ICMP(id=id_ping, seq=seq_ping) # 构造一个数据包
# 发送数据包并等待响应
reply = sr1(pkt, verbose=False,timeout=5)
if reply is None:
return None
elif reply.type == 0:
return [2, reply.src,time.time() - start_time]
else:
return [1,reply.src,time.time() - start_time]
except Exception as e:
if re.match('.*NoneType.*',str(e)):
return None #测试失败返回None
为了使得命令行输出结果更加简洁,在sr1中添加参数:verbose=False。
为了实现可视化路径,利用matplotlib库,没有另外再编写函数,而是在原有框架的判断输出部分增添向量输入代码,最终得以实现“路径可视化”:
def Tracert(dst,max_ttl):
hops = []
rtts = []
ttl = 1
for item in range(1, max_ttl):
Result = Tracert_ICMP(dst, item) # Use Tracert_ICMP function
if Result == None:#如果测试失败就打印‘*’
print("{} | {} | {}".format(item, "*", "Time Out"))
hops.append("*")
rtts.append(0)
elif Result[0] == 1:#如果未抵达目的,打印这一跳和消耗的时间
time_result = '%4.2f' % Result[2]
print("{} | {} ms | {}".format(item, time_result, str(Result[1])))
hops.append(str(Result[1]))
rtts.append(time_result)
elif Result[0] == 2:#如果抵达目的,打印这一跳和消耗的时间,并跳出循环
time_result = '%4.2f' % Result[2]
print("{} | {} ms | {}".format(item, time_result, str(Result[1])))
hops.append(str(Result[1]))
rtts.append(time_result)
break
ttl += 1
time.sleep(1)
plt.plot(hops, rtts, "o-")
plt.xlabel("Hops")
plt.ylabel("RTT (ms)")
plt.title("Traceroute to " + dst)
plt.show()
2.4 结果展示
2.4.1 任务一时序图
2.4.2 任务二路径可视化
我们得到的命令行输出为:
我们得到的路径可视化结果为:
其中横坐标展示了从主机到目的IP的中间路由,纵坐标展示了主机到达中间路由的时间。
2.4.3 任务三问题回答
当发送端发送一个数据包时,它会将该数据包中的IP头中的标识符字段设置为一个唯一的值,并将该值存储在一个数据结构中。当发送端收到一个ICMP报文时,它首先检查该报文是否是一个超时报文。如果是,那么发送端会检查该报文中的IP头中的标识符字段是否与之前发送的数据包中的标识符字段相同。如果相同,那么发送端就可以确定该ICMP报文是从哪个中间路由器返回的。
而当收到的ICMP报文不是超时报文,那么发送端就可以确定该报文是从目标主机返回的。这是因为当目标主机收到数据包时,它会响应一个ICMP应答报文,该报文中包含与数据包中的标识符字段相同的值。通过比较这两个值,发送端就可以知道该报文是从目标主机返回的。
- 实验总结
本次实验通过三个任务使得我对主动测量有了初步的认识,任务一的时序图要求增强我的画图能力也加深了我对计算机网络知识的理解。在实现任务二时遇到过很多麻烦,诸如ping实现找不到主机时,程序会不断广播无法暂停;traceroute实现时输出不够简洁等等,通过和同学的讨论以及询问学长学姐再加上网上查找的资料,终于将问题一一解决,最终获得预期输出时的满足感不言而喻。任务三帮助我回顾了以往写的一些知识,巩固了我对一些网络协议的理解。这对将对我进行后续实验有着好的影响。