python实现Linux上的traceroute

news/2024/5/18 15:29:39 标签: python, linux, udp

1.Linux上的traceroute原理

UDP模式:UDP探测数据包(目标端口大于30000) + 中间网关发回 ICMP TTL 超时(ICMP Time Exceeded Message)数据包 + 目标主机发回ICMP Destination Unreachable 数据包
请添加图片描述请添加图片描述

python_3">2.用到的python模块、库介绍

PS:报文是网络中交换和传输的数据单元,即站点一次性要发送的数据块。

Scapy

Scapy是一个由Python编写的强大工具,目前很多优秀的网络扫描攻击工具都使用了这个模块。也可以在自己的程序中使用这个模块来实现对网络数据包的发送、监听和解析。这个模块相对于Nmap来说,更为底层。可以更直观的了解网络中的各类扫描攻击行为。

相对于Nmap来说,Scapy模块只会把收到的数据包展示给你,并不会告诉你这个包意味着什么。

例如,当你去医院检查身体时,医院会给你一份关于身体各项指标的检查结果,而医生也会告诉你得了什么病或者没有任何病。那么Nmap就像是一个医生,它会替你搞定-切,按照它的经验提供给你结果。而Scapy则像是一个体检的设备, 它只会告诉你各种检查的结果,如果你自己就是一个经验丰富的医生,显然检查的结果要比同行的建议更值得参考。

具体用法见这篇文章

这篇也很好

解析回包内容

关于ICMP

3.Scapy下载

请看这篇文章

和这篇文章

4.编程实现

代码链接

python">#coding=utf-8
from scapy.all import *
import struct,re,random

# 首先构造一个发送一个UDP报文-接收ICMP报文-返回路由/主机ip及时间的函数
#函数返回 1,源地址,数据包发-收时间
def send_udp(dest_ip,ttl,dport): #参数:目的地址 ttl值 目的端口

    #发送udp包开始时间
    time1 = time.time()  #当前系统时钟的时间戳(1970纪元后经过的浮点秒数)
    try:
        # 发送一个upd数据包,接收一个包
        reply_ICMP = sr1(IP(dst=dest_ip, ttl=ttl) / UDP(dport=dport) / b'hello!', timeout=1,
                                   verbose=False) #发送一个UPD数据包 dst目的地址 ttl值 dport目的端口 timeout=1超时1s丢弃 verbose=0不显示详细信息

        # ICMP超时消息-数据包到达中间路由器
        if reply_ICMP.getlayer(ICMP).type == 11 and reply_ICMP.getlayer(ICMP).code == 0:#ICMP差错报文-超时
            # 提取ICMP包的源地址-即路由器ip
            src_ip = reply_ICMP.getlayer(IP).src

            #接收解析完icmp超时报文的时间
            time2 = time.time() #当前系统时间戳
            # 计算时间ms数
            times = (time2-time1) * 1000 #从发送udp数据包,到接收ICMP超时报文所用时间

            return 1,src_ip,times  #返回一个元组


        # ICMP端口不可达-数据包到达目的主机
        elif reply_ICMP.getlayer(ICMP).type == 3 and reply_ICMP.getlayer(ICMP).code == 3:#ICMP差错报文-端口不可达

            src_ip = reply_ICMP.getlayer(IP).src #获取ICMP包的源地址-即目的主机ip

            time2 = time.time()
            times= (time2-time1) * 1000
            return 2, src_ip, times

    except Exception as e:#捕获异常
        return None


def traceroute(dest_ip,max_hop):#参数 目的地址 跳数限制

    dest_port = 33434#目标端口号默认为33434 每次探测目标端口号+1
    now_hop = 0 #记录当前跳数
    ttl=0
    # 进行循环发包-每次发三个探测包
    while now_hop < max_hop: #循环hops次

        now_hop += 1
        ttl += 1
        dest_port += 1

        # 发送三个包,获取返回值
        result1 = send_udp(dest_ip,ttl,dest_port) #目标地址 ttl值 目标端口
        #result1
        # 如果出现了错误,打印*号。
        if result1 == None: #出现错误
            print('*')
        # 中间路由器的情况
        elif result1[0] == 1:
            print("%d %s %6.4fms" % (now_hop,result1[1],result1[2])) #跳数 路由器ip 数据包发-收时间(宽度为4,精确到小数点后2位)
        # 到达目的端口的情况
        elif result1[0] == 2:
            print("%d %s %6.4fms" % (now_hop,result1[1],result1[2])) #跳数 目的地址 数据包发-收时间
            break #退出程序

        time.sleep(1)  # 暂停1s

        result2 = send_udp(dest_ip, ttl, dest_port)  # 目标地址 ttl值 目标端口
        # result2
        # 如果出现了错误,打印*号。
        if result2 == None:  # 出现错误
            print('*')
        # 中间路由器的情况
        elif result2[0] == 1:
            print("%d %s %6.4fms" % (now_hop, result2[1], result2[2]))  # 跳数 路由器ip 数据包发-收时间(宽度为4,精确到小数点后2位)
        # 到达目的端口的情况
        elif result2[0] == 2:
            print("%d %s %6.4fms" % (now_hop, result2[1], result2[2]))  # 跳数 目的地址 数据包发-收时间
            break  # 退出程序
        time.sleep(1)#暂停1s

        result3 = send_udp(dest_ip, ttl, dest_port)  # 目标地址 ttl值 目标端口
        # result3
        # 如果出现了错误,打印*号。
        if result3 == None:  # 出现错误
            print('*')
        # 中间路由器的情况
        elif result3[0] == 1:
            print("%d %s %6.4fms" % (now_hop, result3[1], result3[2]))  # 跳数 路由器ip 数据包发-收时间(宽度为8,精确到小数点后4位)
        # 到达目的端口的情况
        elif result3[0] == 2:
            print("%d %s %6.4fms" % (now_hop, result3[1], result3[2]))  # 跳数 目的地址 数据包发-收时间
            break  # 退出程序
        time.sleep(1)#暂停1s


if __name__ == "__main__":
    destination=input("请输入目的主机ip:")
    max_hops=int(input("请输入跳数限制:"))
    traceroute(destination,max_hops)

另一种方法


http://www.niftyadmin.cn/n/610126.html

相关文章

五、Shell脚本:循环语句——for循环,while循环,until循环

循环语句&#xff1a; 1、for循环语句 2、while循环语句 3、untli循环语句 1.1 for语句的结构 读取不同的变量值&#xff0c;用来逐个执行同一组命令 1.2、for循环语句的三种语句结构用法 for语句结构&#xff1a;第一种&#xff1a; for 变量名 in 取值列表 do命令序列 don…

python从Route Views Archieve上下载解析.bz2数据包

python从Route Views Archieve上下载解析.bz2数据包 1.下载压缩包 2.解压缩包 3.解析解压缩后文件 #encoding:utf-8 import os import requests import urllib import urllib2 import bz2url http://archive.routeviews.org/bgpdata/2001.10/RIBS/rib.20011026.1648.…

六、Shell脚本:函数与数组

一、Shell函数 &#xff08;1&#xff09;将命令序列按格式写在一起 &#xff08;2&#xff09;可方便重复使用命令序列 &#xff08;3&#xff09;Shell函数定义 [ function ] 函数名(){ 命令序列 [return x] } &#xff08;4&#xff09;调用函数的方法 函数名 [参数一][参数…

七:Shell脚本:正则表达式与文本处理器三剑客grep,egrep, sed,awk

正则表达式定义 正则表达式&#xff0c;又称正规表达式、常规表达式 使用字符串来描述、匹配一系列符合某个规则的字符串 ●正则表达式组成 ◆普通字符 大小写字母、数字、标点符号及一些其他符号 ◆元字符 在正则表达式中具有特殊意义的专用字符 基础正则表达式元字符 &#…

八、Shell脚本:正则表达式三剑客awk

awk概述&#xff1a; AWK是一种处理文本文件的语言&#xff0c;是一个强大的文本分析工具。 它是专门为文本处理设计的编程语言&#xff0c;也是行处理软件&#xff0c;通常用于扫描、过滤、统计汇总工作 数据可以来自标准输入也可以是管道或文件 工作原理: 当读到第一行时&am…

全面接触SQL语法三

HAVING 条件子句 指定一特定的分组记录&#xff0c;并满足HAVING 所指定的条件或状态&#xff0c;但条件是针对分组的条件设置。 SELECT fieldlist FROM table WHERE selectcriteria GROUP BY groupfieldlist HAVING groupcriteria fieldlist 显示被查询的字段名称。(可与…

九、Shell脚本:四个小工具(sort,cut,uniq,tr)

1、sort工具 2、cut工具 3、uniq工具 4、tr工具 1.1、sort工具概述&#xff1a; 依据不同的数据类型进行排序 ●字符排序 ●数字排序 1.2语法格式 sort [选项] 参数 sort常用选项数字油 -f:忽略大小写 -b:忽略每行前面的空格 -M:按照月份进行排序 -n:按照数字进行排序 -r:反向…