使用Scapy通过Socket实现IPsec AH隧道模式的报文重构问题
问题:Scapy重构IPsec AH隧道模式报文失败
环境配置
- AH隧道模式
- 外层IP源地址:192.168.100.4
- AH头部Next Header字段设为IPv4
- 内层报文:10.0.1.2到10.0.1.1的ICMP请求报文
发送端代码及生成的报文结构
from scapy.all import SecurityAssociation, AH, IP, ICMP, raw # 安全关联(Security Association)配置 sa = SecurityAssociation(AH, spi=0x222, auth_algo='SHA2-384-192', auth_key=b'secret key', tunnel_header=IP(src='192.168.100.4', dst='192.168.100.6')) # 构造并加密报文 packet = packet_from_Interface # 内层IP+ICMP报文 e1 = sa.encrypt(packet) print("AH packet:") e1.show()
生成的报文结构:
###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 140 id = 1 flags = frag = 0 ttl = 64 proto = ah chksum = 0x30e3 src = 192.168.100.4 dst = 192.168.100.6 \options \ ###[ AH ]### nh = 4 payloadlen= 7 reserved = None spi = 0x222 seq = 2 icv = 266cd31bc38315f1091b8c9affb181b9ec8b33a43b9cb50d padding = None ###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 84 id = 7564 flags = DF frag = 0 ttl = 64 proto = icmp chksum = 0x71b src = 10.0.1.2 dst = 10.0.1.1 \options \ ###[ ICMP ]### type = echo-request code = 0 chksum = 0xc8bb id = 0x7 seq = 0x1 unused = '' ###[ Raw ]### load = '\x0e\\x8fLf\x00\x00\x00\x00\x12t\x03\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
接收端代码及实际结果
接收端代码:
recv_packet = IP(byte_packet_received) recv_packet.show()
实际输出的报文结构:
###[ IP ]### version = 4 ihl = 5 tos = 0x0 len = 128 id = 1 flags = frag = 0 ttl = 64 proto = ah chksum = 0x30ef src = 192.168.100.4 dst = 192.168.100.6 \options \ ###[ AH ]### nh = 4 payloadlen= 4 reserved = 0 spi = 0x222 seq = 1 icv = ebf23a021ee0bbf47fab24ac padding = ###[ Raw ]### load = 'E\x00\x00T\\xabS@\x00@\x01yS\n\x00\x01\x02\n\x00\x01\x01\x08\x00\\xabB\x00\x08\x00\x01ߒLf\x00\x00\x00\x00X\\xe8\t\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'
问题分析与解决建议
核心问题
- Scapy默认不会自动根据AH头部的
Next Header字段解析后续协议层,导致内层IP报文被识别为Raw负载。 - 接收端解密时SA配置可能与发送端不一致,或报文序列(seq)不匹配,导致验证失败。
解决步骤
1. 手动解析内层IP报文
接收端需提取AH层的负载,根据nh字段(值为4对应IPv4)重新解析为IP报文:
from scapy.all import IP, AH recv_packet = IP(byte_packet_received) # 提取AH层 ah_layer = recv_packet[AH] # 解析内层IP inner_ip_pkt = IP(ah_layer.payload) inner_ip_pkt.show() # 此时可正常识别内层IP和ICMP细节
2. 确保SA配置完全一致
解密必须使用与发送端完全相同的安全关联参数,包括SPI、认证算法、密钥:
from scapy.all import SecurityAssociation # 与发送端完全一致的SA配置 sa = SecurityAssociation(AH, spi=0x222, auth_algo='SHA2-384-192', auth_key=b'secret key', tunnel_header=IP(src='192.168.100.4', dst='192.168.100.6')) try: decrypted_pkt = sa.decrypt(recv_packet) print("解密成功:") decrypted_pkt.show() except Exception as e: print(f"解密失败原因:{e}")
3. 排查报文序列(seq)问题
发送端报文seq为2,接收端显示为1,需确认:
- 发送时SA的seq是否正确递增(Scapy的SA会自动递增seq,但需确保每次加密使用同一个SA实例)
- 接收的报文是否为发送端发出的目标报文(可能存在报文丢失或顺序错乱)
内容的提问来源于stack exchange,提问作者Ramon
相关产品推荐
相关产品推荐

