基础知识十、Python解析网络报文之IP首部报文解析


       在上一节 搭建基础框架
后本节我们真正实现对IP报文的解析,首先通过下面这张图先了解一下数据报文组装的结构顺序,IP首部处于IP数据包的头部,每一行32位,共计5行,总长度为20字节。IP协议处于OSI七层模型的网络层,网络层的作用就是负责解决数据报在虚拟网络中传输路径的问题。
请添加图片描述

一、前期准备

1.1 IP首部组成

       IP首部位于IP数据报的前20个字节,每一行有32比特位,共计5行。
在这里插入图片描述
       第一行包括 4位IP-version 4位IP头长度 8位服务类型 16位报文总长度
       第二行包括 16位标识符 3位标记位 13位片偏移 (解析时不关注此行)
       第三行包括 8位TTL 8位协议 16位头部校验和
       第四行包括 32位源IP地址
       第五行包括 32位目的IP地址

1.2 struct处理二进制报文数据

       通过设置下面的格式可以将二进制数据按照不同字节大小进行解析

FORMATC TYPEPYTHON TYPESTANDARD SIZE
Bunsigned charinteger1字节
Hunsigned shortinteger2字节
Lunsigned longinteger4字节
schar[]string~

       大端字节序表示高位在前,低位在后,是网络通信中常用的顺序;小段字节序则相反,低位在前,高位在后,因为计算机电路在处理低位字节效率较高,常用于主机存储中。
       下面是struct包解析demo,其中>表示按照大端顺序进行解析。

import struct

bin_str = b'ABCDEFGH'
print(bin_str)
print(bin_str.decode())
res = struct.unpack('>8B', bin_str)
print(res)
res2 = struct.unpack('>4H', bin_str)
print(res2)
res3 = struct.unpack('>2L', bin_str)
print(res3)
res4 = struct.unpack('>8s', bin_str)
print(res4)

测试结果:
在这里插入图片描述

二、IP首部解析器的实现

       创建net包 新建parser.py文件
       在IPParser中分别对头部报文的每一行进行解析。

class IPParser:

    IP_HEADER_LENGTH = 20  # 报文前二十字节为ip头部

    @classmethod
    def parse_ip_header(cls, ip_header):
        """
        IP报文格式
        1. 4位IP-version 4位IP头长度 8位服务类型 16位报文总长度
        2. 16位标识符 3位标记位 13位片偏移 暂时不关注此行
        3. 8位TTL 8位协议 16位头部校验和
        4. 32位源IP地址
        5. 32位目的IP地址
        :param ip_header:
        :return:
        """
        line1 = struct.unpack('>BBH', ip_header[:4])  # 先按照8位、8位、16位解析
        ip_version = line1[0] >> 4  # 通过右移4位获取高四位
        # 报文头部长度的单位是32位 即四个字节
        iph_length = (line1[0] & 15) * 4  # 与1111与运算获取低四位
        packet_length = line1[2]
        line3 = struct.unpack('>BBH', ip_header[8: 12])
        TTL = line3[0]
        protocol = line3[1]
        iph_checksum = line3[2]
        line4 = struct.unpack('>4s', ip_header[12: 16])
        src_ip = socket.inet_ntoa(line4[0])
        line5 = struct.unpack('>4s', ip_header[16: 20])
        dst_ip = socket.inet_ntoa(line5[0])

        # 返回结果
        # ip_version ip版本
        # iph_length ip头部长度
        # packet_length 报文长度
        # TTL 报文寿命
        # protocol 协议号 1 ICMP协议 6 TCP协议 17 UDP协议
        # iph_checksum ip头部的校验和
        # src_ip 源ip
        # dst_ip 目的ip
        return {
            'ip_version': ip_version,
            'iph_length': iph_length,
            'packet_length': packet_length,
            'TTL': TTL,
            'protocol': protocol,
            'iph_checksum': iph_checksum,
            'src_ip': src_ip,
            'dst_ip': dst_ip
        }

    @classmethod
    def parse(cls, packet):
        ip_header = packet[:cls.IP_HEADER_LENGTH]

        return cls.parse_ip_header(ip_header)

三、测试逻辑

       在ServerProcessTask中调用IPParser

def process(self):
    """
    异步处理方法
    :return:
    """
    headers = {
        'network_header': None,
        'transport_header': None
    }

    ip_header = IPParser.parse(self.packet)
    headers['network_header'] = ip_header
    return headers

测试结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值