Raw Socket数据包头部解析:Python嗅探器源IP/端口及字段疑问
嗨,我来帮你解决这两个问题——之前我自己写Socket嗅探器的时候也踩过这些坑,太懂这种摸不着头脑的感觉了!
一、如何找到发送方IP和端口号
首先得明确你捕获的是IPv4数据包(从你给的头部元组来看是IPv4),咱们一步步来:
发送方IP地址:其实就在你拿到的IP头部里!IPv4头的结构里,源IP位于第13-16字节(也就是从
data索引12开始的4个字节),而你已经能获取的接收方IP(目的IP)在它后面的4个字节(索引16-19)。比如你可以直接把这四个字节转成点分十进制:source_ip = '.'.join(map(str, data[12:16]))发送方端口号:端口属于传输层(TCP/UDP)内容,得先跳过IP头部才能拿到。IP头的长度由
data[0]的后4位决定:比如data[0]是69(二进制01000101),后4位是0101,代表IP头长度是5×4=20字节。所以传输层头部从data[20]开始:- 如果是UDP协议(协议号17),源端口是传输层头的前两个字节,用
struct模块解析:import struct ip_header_len = (data[0] & 0x0F) * 4 source_port = struct.unpack('!H', data[ip_header_len:ip_header_len+2])[0] - 如果是TCP协议(协议号6),解析方式完全一样,因为TCP头的前两个字节也是源端口。
- 如果是UDP协议(协议号17),源端口是传输层头的前两个字节,用
二、解析你给出的IP头部元组字段
先说明:你的元组看起来是把IP头的字段拆成了十进制值,但其中有些元素(比如1541)明显超过了单字节的范围(0-255),应该是拆分时的小错误,但结合已知的协议字段(header[6]=17),咱们对应标准IPv4头的字段来解释:
元组:(69, 0, 61, 1541, 0, 128, 17, 0, 192, 168, 56, 1, 255, 255, 255, 255)
- 索引0: 69:二进制是
01000101,前4位0100表示IPv4版本,后4位0101表示IP头部长度(5个32位字,也就是20字节,这是IPv4的最小头部长度) - 索引1: 0:服务类型(ToS),值0代表使用默认服务质量,无特殊优先级或延迟要求
- 索引2-3: 61, 1541:这应该是**总长度(Total Length)**字段(原本是2字节,0-65535),但拆分出错了——正确的做法是从原始
data中取2字节用struct.unpack('!H', data[2:4])获取,它代表整个数据包(IP头+数据)的字节数 - 索引4-5: 0, 128:对应**标识(Identification)**字段(2字节),值为
0×0080=128,用于分片重组时标识同一个数据包的分片 - 索引6: 17:你已经知道的协议(Protocol),17对应UDP协议,6对应TCP,1对应ICMP
- 索引7: 0:头部校验和(Header Checksum),值0通常是因为网卡硬件已经完成校验,或者捕获的数据包还没计算校验和
- 索引8-11: 192,168,56,1:源IP地址,组合起来就是
192.168.56.1——这就是你要找的发送方IP! - 索引12-15:255,255,255,255:目的IP地址,也就是你已经获取的接收方IP,这是一个广播地址
内容的提问来源于stack exchange,提问作者user9321739
相关产品推荐
相关产品推荐

