python流量包部分协议解析

知识点补充

流量包处理部分:

程序主要处理pcap的部分类型包括:

1.pcap包头

全局头部(Global Header):这部分信息包含在PCAP文件的开头,用于描述整个文件的格式和属性。全局头部包括以下字段:

  • Magic: 这是PCAP文件的魔术数字,用于标识PCAP文件的格式。

  • Major,Minor:这些字段指示了PCAP文件格式的版本号。

  • Timezone:

  • Sigfigs: Sigfigs(Significant Figures)字段通常用于记录时间戳的精度,它设置为0,表示时间戳的精度未指定。

  • Snaplen: Snaplen字段表示每个数据包的最大长度。

  • LinkType: LinkType字段指示了数据包的链接类型。

  • 数据包总:这是PCAP文件中的数据包总数。

2.ARP包(链路层)

ARP(Address Resolution Protocol)是一种网络协议,用于将IP地址映射到物理MAC地址,以便在局域网中正确地传送数据帧。ARP包是用来执行这个映射过程的网络数据包。下面是关于ARP包的一些重要信息:

  1. ARP包的基本结构:ARP包通常包括以下字段:

    • 硬件类型(Hardware Type):表示使用的网络硬件类型,例如以太网。

    • 协议类型(Protocol Type):表示上层协议的类型,通常是IPv4。

    • 硬件地址长度(Hardware Address Length):表示硬件地址(MAC地址)的长度。

    • 协议地址长度(Protocol Address Length):表示协议地址(IPv4地址)的长度。

    • 操作码(Opcode):指示ARP请求(1)或ARP响应(2)。

    • 发送方的硬件地址(Sender Hardware Address):发送ARP包的设备的MAC地址。

    • 发送方的协议地址(Sender Protocol Address):发送ARP包的设备的IPv4地址。

    • 目标硬件地址(Target Hardware Address):目标设备的MAC地址(通常在ARP请求中为空,因为请求的目标是要找到的)。

    • 目标协议地址(Target Protocol Address):目标设备的IPv4地址。

  2. ARP请求(ARP Request):当一台设备想要知道另一台设备的MAC地址时,它会发送一个ARP请求。ARP请求中包括发送方的MAC和IPv4地址,以及目标IP地址。本地网络中的所有设备都会接收ARP请求,但只有目标设备会响应。

  3. ARP响应(ARP Reply):当目标设备收到ARP请求后,它会生成一个ARP响应,其中包含了自己的MAC地址。ARP响应会发送回ARP请求的发起者,这样发起者就知道了目标设备的MAC地址,从而可以直接通信。

3.ICMP包(网络层)

ICMP(Internet Control Message Protocol)是一种用于在IP网络中传递控制消息的协议,通常用于网络故障排除、错误报告和网络状态查询。ICMP包是用于传输这些控制消息的网络数据包。以下是关于ICMP包的一些重要信息:

  1. ICMP包的基本结构:ICMP包通常包括以下字段:

    • 类型(Type):指示ICMP消息的类型,例如,Echo Request、Echo Reply、Destination Unreachable等。

    • 代码(Code):对ICMP消息类型的进一步说明或细分。

    • 校验和(Checksum):用于检测ICMP包中数据的错误或损坏。

    • 数据(Data):特定于消息类型的数据部分,可以包含有关错误或状态的额外信息。

  2. Echo Request和Echo Reply:最常见的ICMP消息是Echo Request和Echo Reply。Echo Request用于网络诊断工具如Ping,它发送请求到目标主机,如果目标主机在线并可达,将会发送Echo Reply作为响应。Ping工具通常用于检测网络主机的可达性和往返延迟。

  3. Destination Unreachable:ICMP Destination Unreachable消息表示某个目标不可到达。这可能是因为目标主机不可达、端口不可达或者网络不可达等原因。

  4. Time Exceeded:ICMP Time Exceeded消息通常用于跟踪数据包的生存时间。它可以在路由器或网关上生成,以指示数据包已经超过了它的最大生存时间(TTL)或者它在路由中遇到了循环。

  5. Redirect:ICMP Redirect消息通知主机将数据包发送到另一个网关,以改善数据包的路由。

  6. ICMP错误报文:ICMP还用于报告错误情况,例如ICMP Destination Unreachable和ICMP Time Exceeded。这些错误报文通常用于帮助网络管理员排除问题。

  7. ICMP查询消息:ICMP还用于发送查询消息,例如ICMP Echo Request。这些查询消息通常用于测试主机的可达性或测量往返延迟。

4.DHCP包(应用层)

DHCP(Dynamic Host Configuration Protocol)是一种网络协议,用于自动分配IP地址和其他网络配置信息给计算机和设备,以便它们可以顺利地连接到网络。DHCP包是用于在DHCP交互中传输信息的网络数据包。以下是关于DHCP包的一些重要信息:

  1. DHCP包的基本结构:DHCP包通常包括以下字段:

    • 操作码(Opcode):指示DHCP消息的类型,如请求(1)、应答(2)等。

    • 硬件类型(Hardware Type):表示使用的硬件类型,通常是以太网。

    • 硬件地址长度(Hardware Address Length):表示硬件地址(MAC地址)的长度。

    • 跳数(Hops):用于限制消息的传播,通常设置为0。

    • 事务ID(Transaction ID):用于将请求和响应匹配在一起。

    • 秒数(Seconds):自DHCP客户端启动以来的秒数,用于同步时间。

    • 标志(Flags):包含广播标志和广播地址标志。

    • 客户端IP地址(Client IP Address):DHCP客户端当前的IP地址。

    • 分配的IP地址(Your IP Address):DHCP服务器为客户端分配的IP地址。

    • 下一个服务器IP地址(Next Server IP Address):用于引导过程的服务器IP地址。

    • Relay Agent IP地址(Relay Agent IP Address):用于DHCP中继代理的IP地址。

    • 客户端硬件地址(Client Hardware Address):DHCP客户端的MAC地址。

    • 服务器主机名(Server Hostname):DHCP服务器的主机名。

    • 引导文件名(Boot Filename):用于引导过程的文件名。

    • 选项(Options):包含其他配置信息,如子网掩码、默认网关、DNS服务器等。

  2. DHCP请求和应答:DHCP包有两种主要类型,即DHCP请求和DHCP应答。DHCP请求由客户端发送,以请求网络配置信息,而DHCP应答由DHCP服务器发送,以响应客户端请求并提供配置信息。

  3. 租约(Lease):DHCP服务器通常为客户端提供一个IP地址租约,即一个特定时间段内该IP地址的有效性。客户端在租约到期前需要更新或续约租约,否则IP地址可能会被释放回池中供其他设备使用。

  4. DHCP中继代理(DHCP Relay Agent):在跨子网的环境中,DHCP中继代理可以帮助在不同子网之间传递DHCP消息,以便DHCP服务器能够为来自不同子网的客户端提供IP地址。

5.DNS包(应用层)

DNS(Domain Name System)包是用于域名解析的网络数据包,用于将人类可读的域名(例如www.example.com)转换为计算机可理解的IP地址(例如192.168.1.1)。以下是关于DNS包的一些重要信息:

  1. DNS包的基本结构:DNS包通常包括以下字段:

    • 事务ID(Transaction ID):用于将DNS请求与响应匹配在一起。

    • 标志(Flags):包括查询/响应标志、操作码、授权回答标志等。

    • 问题计数(Question Count):表示DNS查询的数量。

    • 回答计数(Answer Count):表示DNS响应中包含的回答数量。

    • 权威回答计数(Authority Count):表示权威服务器的数量。

    • 附加信息计数(Additional Count):表示附加信息的数量。

    • 查询部分(Question Section):包括查询的域名和查询类型(例如A记录、AAAA记录、MX记录等)。

    • 回答部分(Answer Section):包括查询的域名的IP地址或其他资源记录。

    • 权威部分(Authority Section):包含权威服务器的信息。

    • 附加部分(Additional Section):包含与查询相关的附加信息,如DNS服务器的IP地址。

  2. DNS查询类型:DNS包中的查询部分指定了DNS查询的类型,常见的查询类型包括:

    • A记录:将域名解析为IPv4地址。

    • AAAA记录:将域名解析为IPv6地址。

    • MX记录:获取邮件交换服务器的信息。

    • CNAME记录:获取规范名称,用于别名。

    • NS记录:获取域名的权威名称服务器信息。

  3. DNS响应:DNS包中的回答部分包含了DNS服务器提供的查询结果,通常包括一个或多个资源记录,其中包括IP地址或其他相关信息。

  4. DNS缓存:DNS客户端和DNS服务器通常会在本地缓存DNS响应,以减少网络流量并提高域名解析速度。这有助于将频繁访问的域名解析请求快速响应。

  5. DNS协议操作码:DNS包中的操作码字段指示DNS请求的类型,如查询、更新、通知等。

ps:MDNS

mDNS代表"Multicast DNS",是一种用于在小型局域网络(LAN)中进行局域网主机名解析的协议。它允许设备在没有集中式DNS服务器的情况下发现和解析其他设备的主机名和IP地址。mDNS通常用于家庭网络、小型办公网络和物联网设备等场景。

以下是关于mDNS的一些重要信息:

  1. 主机名解析:mDNS允许设备通过本地网络广播查询来查找其他设备的主机名和IP地址。这使得设备能够使用友好的主机名而不是IP地址来识别和访问其他设备。

  2. 零配置:mDNS是一种零配置协议,不需要任何预先配置的DNS服务器或DHCP服务器。设备可以通过广播消息进行主机名解析,而不需要中央管理。

  3. UDP协议:mDNS使用UDP协议在本地网络上广播和响应查询。标准的mDNS端口号是5353/UDP。

  4. .local域名后缀:mDNS使用特殊的域名后缀".local",例如"mycomputer.local",以标识局域网内的主机名。

  5. Bonjour协议:Apple的Bonjour是基于mDNS的实现,使苹果设备能够轻松发现和与其他Bonjour兼容设备进行通信。

  6. 应用领域:mDNS广泛应用于各种场景,包括打印机自动发现、网络音频设备(如AirPlay设备)发现、智能家居设备互联等。

Multicast DNS(mDNS)的目的IP地址通常是224.0.0.251。mDNS使用多播地址224.0.0.251来进行本地网络内的DNS查询和响应广播。当设备发送mDNS查询时,它将查询数据包的目的IP地址设置为224.0.0.251,以通知本地网络中的其他设备,这是一个mDNS查询。

其他支持mDNS的设备可以监听这个多播地址,如果它们有与查询匹配的主机名解析信息,它们可以通过多播回复来响应。因此,224.0.0.251是mDNS协议中用于查询和响应的目的IP地址,有助于设备在局域网中进行主机名解析和发现其他设备。这个IP地址是mDNS的标准多播地址。

6.HTTP包(应用层)

HTTP(Hypertext Transfer Protocol)包是用于在Web上传输和交换超文本文档(通常是HTML文件)和其他资源的网络数据包。HTTP是一种应用层协议,它允许客户端(通常是Web浏览器)与Web服务器之间进行通信,并请求或发送Web内容。以下是关于HTTP包的一些重要信息:

  1. HTTP包的基本结构:HTTP包通常由以下部分组成:

    • 请求行(Request Line):包括HTTP请求方法(GET、POST、PUT等)、请求的URL和HTTP版本。

    • 请求头部(Request Headers):包括关于请求的元信息,如用户代理、内容类型、接受语言等。

    • 空白行:用于分隔请求头部和请求主体。

    • 请求主体(Request Body):可选部分,通常包含与请求相关的数据,例如表单数据或上传的文件。

    或者对于HTTP响应包:

    • 状态行(Status Line):包括HTTP版本、状态代码(例如200 OK、404 Not Found)、状态消息。

    • 响应头部(Response Headers):包括关于响应的元信息,如服务器类型、内容类型、内容长度等。

    • 空白行:用于分隔响应头部和响应主体。

    • 响应主体(Response Body):包含实际的Web内容,如HTML页面、图像、文本等。

  2. HTTP请求方法:HTTP定义了各种请求方法,用于指示客户端的操作类型。常见的HTTP请求方法包括:

    • GET:请求获取指定资源的内容。

    • POST:向指定资源提交数据进行处理,常用于表单提交。

    • PUT:请求服务器存储一个资源,并用请求的数据替换指定的资源。

    • DELETE:请求服务器删除指定资源。

    • HEAD:类似于GET,但只请求获取资源的响应头部信息,不包含实际内容。

    • 等等。

  3. HTTP响应状态码:HTTP响应状态码表示服务器对请求的处理结果。常见的HTTP状态码包括:

    • 200 OK:请求成功。

    • 404 Not Found:请求的资源未找到。

    • 500 Internal Server Error:服务器内部错误。

    • 302 Found:临时重定向。

    • 401 Unauthorized:未经授权。

    • 等等。

  4. 持久连接:HTTP允许使用持久连接,也称为HTTP Keep-Alive,以在单个连接上传输多个HTTP请求和响应,减少连接建立和关闭的开销,提高性能。

  5. HTTPS:HTTPS是HTTP的安全版本,使用SSL/TLS加密来保护数据传输的安全性和隐私。

7.SYSLOG(应用层)

Syslog是一种用于记录系统事件和消息的协议和标准。它通常用于Unix和类Unix操作系统中,但也在其他操作系统上得到了广泛支持。Syslog的目标是允许计算机和网络设备将系统消息、警告、错误和其他事件发送到一个或多个中央日志服务器或收集器,以进行集中式的记录、分析和监控。

以下是关于Syslog包的一些重要信息:

  1. Syslog协议:Syslog协议定义了日志消息的格式和传输方式,通常使用UDP或TCP作为传输协议。Syslog消息包括时间戳、主机名、应用程序标识、消息内容等字段。

  2. 设备和应用程序支持:各种网络设备、服务器、路由器、交换机以及应用程序都可以生成Syslog消息。这些消息通常包括系统事件、性能统计、安全事件等信息。

  3. Syslog级别:Syslog定义了不同的消息级别,用于表示消息的重要性和严重性。常见的Syslog级别包括DEBUG、INFO、NOTICE、WARNING、ERROR、CRITICAL、ALERT和EMERGENCY。

  4. Syslog设备和收集器:Syslog消息可以由各种设备生成,然后通过网络发送到Syslog服务器或收集器。Syslog服务器负责接收、存储和管理这些消息。流行的Syslog服务器包括rsyslog、syslog-ng、Graylog等。

  5. Syslog配置:Syslog允许管理员配置设备和应用程序以发送消息到指定的Syslog服务器。配置通常包括指定Syslog服务器的IP地址和端口号,以及选择消息的级别和目的地。

  6. 日志分析和监控:通过集中式的Syslog服务器,管理员可以对系统事件进行监控、分析和故障排除。Syslog消息还可以用于安全信息和事件管理(SIEM)系统,以帮助检测和应对安全威胁。

日志记录部分:

程序配置日志记录器(Logger),以便在应用程序中实现日志记录功能。具体来说,它执行了以下操作:

  1. 创建一个新的日志记录器对象(Logger),并设置其日志级别为DEBUG。日志记录器通常以应用程序中的不同模块或功能为基础,以帮助组织和标识日志消息。

  2. 配置日志记录到文件:程序指定了日志文件的路径,根据传入的logger_name参数来创建不同名称的日志文件。它将日志级别设置为DEBUG,以允许记录所有级别的日志消息。然后,它创建一个文件处理器(FileHandler),将日志消息写入指定的日志文件。还为文件处理器设置了日志消息的格式(formatter),包括时间戳、记录器名字、日志级别和消息内容。

  3. 配置日志记录到控制台:程序创建一个控制台处理器(StreamHandler),允许将日志消息输出到控制台。与文件处理器类似,它也将日志级别设置为DEBUG,并为其设置了与文件处理器相同的日志消息格式。

  4. 最后,程序将文件处理器和控制台处理器添加到创建的日志记录器中,以便同时将日志消息记录到文件和控制台。这允许开发人员在开发和调试应用程序时能够在控制台实时查看日志,同时也将日志信息存储在文件中,以供以后分析和审查。

源代码

"""
coding:utf-8
@Software:PyCharm
@Time:2023/6/13 17:30
@Author:gjc
"""

import struct
from scapy.all import *
from scapy.all import PcapReader


def read_pacp_head(path):
    """
        查看pcap文件头部信息,包括:
        magic_number: 用于标识文件类型和字节序,它的值为0xA1B2C3D4(大端字节序)或0xD4C3B2A1(小端字节序)。
        version_major和version_minor: 分别表示主版本号和副版本号,用于指示文件格式的版本。
        thiszone: 表示时区,通常设置为0。
        sigfigs: 时间戳精度,通常设置为0。
        snaplen: 抓包最大长度,表示捕获的数据包最多保留snaplen个字节,多余的数据会被截断。
        network: 表示网络类型,用于指示链路层的协议,例如Ethernet(0x00000001)。
        :return: NULL

    """
    try:
        # 打开pcap文件
        with open(path, 'rb') as f:
            data = f.read(24)
            """
            =:表示使用本地字节序(native byte order)来解析数据,也就是系统的默认字节序。
            I:表示一个32位无符号整数(unsigned int,4字节)。
            H:表示一个16位无符号整数(unsigned short,2字节)。
            """
            magic, major, minor, tz, sigfigs, snaplen, network = struct.unpack("=IHHIIII", data)
    except Exception as e:
        print(f"Error: {e}")
        return None
    # 打印pcap文件头信息
    print("Magic: 0x{:08x}".format(magic))
    print("Major: {}".format(major))
    print("Minor: {}".format(minor))
    print("Timezone: {}".format(tz))
    print("Sigfigs: {}".format(sigfigs))
    print("Snaplen: {}".format(snaplen))
    print("LinkType: {}".format(network))


def process_packet(packet, packet_number):
    """
        处理单个数据包的函数。
        在这里可以编写对数据包的处理逻辑。
        :param packet: 输入的流量包
        :param packet_number: 流量包编号
        :return: NULL
    """
    try:
        # 打印packet信息
        # print(packet.show())

        # 处理arp协议相关包
        if "ARP" in packet:
            print("Packet Number:{} ----------ARP".format(packet_number))
            # 将MAC地址转换为整数
            mac_int = int(packet['ARP'].hwdst.replace(":", ""), 16)
            # 广播地址的最低有效位为全1(0xFF)为询问包
            if mac_int == 0:
                print("Who has {} ? Tell {}".format(packet['ARP'].pdst, packet['ARP'].psrc))
            else:
                print("{} is at {}".format(packet['ARP'].psrc, packet['ARP'].hwsrc))
            print("------------------------------------------------------------------------")

        # 处理icmp协议相关包
        if "ICMP" in packet:
            print("Packet Number:{} ---------ICMP".format(packet_number))
            # print(packet.show())
            print('{}--->{}  '.format(packet['IP'].src, packet['IP'].dst), end="")
            # icmp报文的类型及功能由type和code两个字段控制
            if packet['ICMP'].type == 0:
                if packet['ICMP'].code == 0:
                    print('Echo (ping) reply')
            elif packet['ICMP'].type == 3:
                if packet['ICMP'].code == 0:
                    print('目的网络不可达')
                elif packet['ICMP'].code == 1:
                    print('目的主机不可达')
                elif packet['ICMP'].code == 2:
                    print('目的协议不可达')
                elif packet['ICMP'].code == 3:
                    print('目的端口不可达')
                elif packet['ICMP'].code == 6:
                    print('目的网络未知')
                elif packet['ICMP'].code == 7:
                    print('目的主机未知')
            elif packet['ICMP'].type == 4:
                if packet['ICMP'].code == 0:
                    print('源抑制')
            elif packet['ICMP'].type == 8:
                if packet['ICMP'].code == 0:
                    print('Echo (ping) request')
            elif packet['ICMP'].type == 9:
                if packet['ICMP'].code == 0:
                    print('路由器通知')
            elif packet['ICMP'].type == 10:
                if packet['ICMP'].code == 0:
                    print('路由器发现')
            elif packet['ICMP'].type == 11:
                if packet['ICMP'].code == 0:
                    print('TTL超时')
            elif packet['ICMP'].type == 12:
                if packet['ICMP'].code == 0:
                    print('IP头损坏')
            print("------------------------------------------------------------------------")

        # 处理dhcp协议相关包
        if "DHCP" in packet:
            print("Packet Number:{} ---------DHCP".format(packet_number))
            # dhcp报文有不同的type
            if packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 1:
                print('DHCP DISCOVER - Transaction ID:{} '.format(packet['BOOTP'].xid))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 2:
                for option in packet['DHCP'].options:
                    if isinstance(option, tuple) and option[0] == 'server_id':
                        server_id = option[1]
                    if isinstance(option, tuple) and option[0] == 'lease_time':
                        lease_time = option[1]
                print('DHCP OFFER - Transaction ID:{} '.format(packet['BOOTP'].xid), end="")
                print('DHCP SERVER({}) OFFER {} TO DHCP CLIENT'.format(server_id, packet['BOOTP'].yiaddr))
                print('lease_time: {}s'.format(lease_time))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 3:
                for option in packet['DHCP'].options:
                    if isinstance(option, tuple) and option[0] == 'requested_addr':
                        requested_addr = option[1]
                print('DHCP REQUEST - Transaction ID:{} '.format(packet['BOOTP'].xid))
                print('DHCP CLIENT REQUEST {}'.format(requested_addr))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 4:
                print('DHCP DECLINE - Transaction ID:{} '.format(packet['BOOTP'].xid))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 5:
                print('DHCP ACK - Transaction ID:{} '.format(packet['BOOTP'].xid))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 6:
                print('DHCP NAK - Transaction ID:{} '.format(packet['BOOTP'].xid))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 7:
                print('DHCP RELEASE - Transaction ID:{} '.format(packet['BOOTP'].xid), end="")
                print('RELEASE IP:{}'.format(packet['BOOTP'].ciaddr))

            elif packet['DHCP'].options[0][0] == 'message-type' and packet['DHCP'].options[0][1] == 8:
                print('DHCP INFORM - Transaction ID:{} '.format(packet['BOOTP'].xid))
            print("------------------------------------------------------------------------")

        # 处理dns协议相关包
        if "DNS" in packet:

            if 'IP' in packet and packet['IP'].dst == '224.0.0.251':
                print("Packet Number:{} ----------MDNS".format(packet_number))
                print('忽略MDNS')

            elif packet['DNS'].qr == 0:
                print("Packet Number:{} ----------DNS".format(packet_number))
                print('DNS查询报文 - Transaction ID:{} '.format(packet['DNS'].id), end="")
                if isinstance(packet['DNS'].qd.qname, bytes):
                    print('类型:{} 主机名:{} '.format(packet['DNS'].qd.qtype, packet['DNS'].qd.qname.decode("utf-8").strip()))
                elif isinstance(packet['DNS'].qd.qname, str):
                    print('类型:{} 主机名:{} '.format(packet['DNS'].qd.qtype, packet['DNS'].qd.qname))

            elif packet['DNS'].qr == 1:
                print("Packet Number:{} ----------DNS".format(packet_number))
                print('DNS回复报文 - Transaction ID:{} '.format(packet['DNS'].id), end="")
                if isinstance(packet['DNS'].an.rrname, bytes) and isinstance(packet['DNS'].an.rdata, bytes):
                    print('类型:{} 主机名:{} 回复信息:{} '.format(packet['DNS'].an.type, packet['DNS'].an.rrname.decode("utf-8").strip(), packet['DNS'].an.rdata.decode("utf-8").strip()))
                elif isinstance(packet['DNS'].an.rrname, str) and isinstance(packet['DNS'].an.rdata, bytes):
                    print('类型:{} 主机名:{} 回复信息:{} '.format(packet['DNS'].an.type, packet['DNS'].an.rrname, packet['DNS'].an.rdata.decode("utf-8").strip()))
                elif isinstance(packet['DNS'].an.rrname, bytes) and isinstance(packet['DNS'].an.rdata, str):
                    print('类型:{} 主机名:{} 回复信息:{} '.format(packet['DNS'].an.type, packet['DNS'].an.rrname.decode("utf-8").strip(), packet['DNS'].an.rdata))
                elif isinstance(packet['DNS'].an.rrname, str) and isinstance(packet['DNS'].an.rdata, str):
                    print('类型:{} 主机名:{} 回复信息:{} '.format(packet['DNS'].an.type, packet['DNS'].an.rrname, packet['DNS'].an.rdata))

                # 处理ns:包含权威DNS服务器的信息,这些服务器可以提供与查询相关的其他信息,例如,域名的权威域名服务器。
                if packet['DNS'].ns is not None:
                    print('NS:')
                    for i in range(packet['DNS'].nscount):
                        print("   Name:{} Value:{} Type:{} TTL:{} ".format(packet['DNS'].ns[i].rrname.decode("utf-8").strip(), packet['DNS'].ns[i].rdata.decode("utf-8").strip(), packet['DNS'].ns[i].type, packet['DNS'].ns[i].ttl))

            print("------------------------------------------------------------------------")

        # 处理http协议相关流量包(不包括https UPnP)
        if "TCP" in packet:
            try:
                payload = packet['Raw'].load.decode("utf-8").strip()
                # TODO: 部分流量包的载荷字段包含有http等相关内容,导致被纳入该部分处理,可以改用Python中的http.server模块
                if "HTTP/1.1" in payload or "HTTP/1.0" in payload:
                    print("Packet Number:{} ----------HTTP".format(packet_number))
                    print('{}:{}--->{}:{}  '.format(packet['IP'].src, packet['TCP'].sport, packet['IP'].dst, packet['TCP'].dport, end=""))
                    if 'HTTP/1.1 200' in payload or 'HTTP/1.0 200' in payload:
                        lines = packet['Raw'].load.decode('utf-8').split('\n')
                        if len(lines) > 0:
                            print(lines[0].strip(), end=" ")
                        for line in lines:
                            if line.startswith('Content-Type:'):
                                print("({})".format(line.split(': ')[1].strip()))

                    else:
                        lines = packet['Raw'].load.decode('utf-8').split('\n')
                        if len(lines) > 0:
                            print(lines[0])

                    print("------------------------------------------------------------------------")

            except:
                pass

        # 处理syslog包
        if "UDP" in packet:
            # syslog通常使用udp 端口514
            if packet['UDP'].dport == 514:
                print("Packet Number:{} ----------SYSLOG".format(packet_number))
                syslog_message = packet['Raw'].load.decode('utf-8')
                # 使用正则表达式提取Syslog消息中的不同部分
                match = re.match(r"<(\d+)>(\S+) (\S+) (.+)", syslog_message)
                if match:
                    priority = match.group(1)
                    timestamp = match.group(2)
                    hostname = match.group(3)
                    message = match.group(4)
                    facility = int(priority) // 8
                    severity = int(priority) % 8
                    facility_names = [
                        "kernel messages",
                        "user-level messages",
                        "mail system",
                        "system daemons",
                        "security/authorization messages",
                        "messages generated internally by syslogd",
                        "line printer subsystem",
                        "network news subsystem",
                        "UUCP subsystem",
                        "clock daemon",
                        "security/authorization messages",
                        "FTP daemon",
                        "NTP subsystem",
                        "log audit",
                        "log alert",
                        "clock daemon",
                        "local use 0",
                        "local use 1",
                        "local use 2",
                        "local use 3",
                        "local use 4",
                        "local use 5",
                        "local use 6",
                        "local use 7"
                    ]
                    severity_names = [
                        "Emergency",
                        "Alert",
                        "Critical",
                        "Error",
                        "Warning",
                        "Notice",
                        "Informational",
                        "Debugging"
                    ]
                    print(facility_names[facility], end=" ")
                    print("[{}]:".format(severity_names[severity]))
                    print("    Timestamp:", timestamp)
                    print("    Hostname :", hostname)
                    print("    Message  :", message)
                    print("------------------------------------------------------------------------")

                else:
                    print("未能匹配Syslog消息")
                    print("------------------------------------------------------------------------")

    except Exception as e:
        print(f"Error: {e}")


def read_pcap_file(pcap_file):
    """
        读取 PCAP 文件,打印pcap文件中的数据包总数
        :param pcap_file: pcap文件路径
        :return: NULL
    """
    try:
        packet_count = 0
        packet_number = 1  # 初始化数据包编号
        with PcapReader(pcap_file) as packets:
            for packet in packets:
                # 处理单个流量包
                process_packet(packet, packet_number)
                packet_count += 1  # 流量包总数计数
                packet_number += 1  # 增加数据包编号
        print("pcap文件包头信息:")
        read_pacp_head(pcap_file)
        print("数据包总数:{}".format(packet_count))

    except Exception as e:
        print(f"Error: {e}")

处理部分主要代码

 后续:

使用tk新增了一个可视化窗口,便于选择分析的pcap包,将print输出修改为输出带log日志,新增功能效果如下(现在分析的协议较少)

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值