一、问题背景
在基于Strongswan搭建IPsec站点到站点VPN的实际运维中,当遇到两侧流量选择器(Traffic Selector)定义的数据流无法互通时,常规的排障手段是通过Wireshark抓包分析。但IPsec协议栈的ESP封装机制会对有效载荷进行加密,导致抓包工具无法直接解析内层报文,这给问题定位带来了技术挑战。
对于Linux系统环境,管理员可以通过ip xfrm state
命令直接获取安全关联(SA)的状态信息,包括SPI值、加密算法和密钥等核心参数,配合Wireshark的ESP预共享密钥配置即可实现报文解密。但当VPN终端运行在Windows或其他非Linux系统时 ,这种依赖操作系统特定工具链的方法将不再适用。
通过技术社区的研究发现,目前存在两种主流的通用解决方案:
- save-keys插件方案 :通过编译安装Strongswan的附加插件,可在运行时自动生成符合Wireshark格式的密钥日志文件。但该方法需要重新编译源码,对生产环境的版本管理和运维流程存在侵入性,实际落地存在较高门槛。
- Charon守护进程调试方案(推荐方案) :通过启用Strongswan IKE守护进程(charon)的增强日志功能,可直接在标准日志中输出完整的IKE协商细节。
这边,我将详细介绍方案二的方法,该方案的优势在于无需修改代码或额外组件,通过日志中的KEYING MATERIAL
字段即可提取出ESP会话密钥(包括加密/认证密钥、SPI等),配合Wireshark的"协议首选项->ESP->导入密钥"功能,即可实现跨平台的数据包解密分析。
二、技术实现全流程详解
1. StrongSwan日志深度配置
编辑strongswan.conf文件
ini
charon {
# 关键模块加载(需包含kernel-netlink插件)
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
}
# 日志输出配置
filelog {
charonLog {
time_format = %b %e %T # 时间戳格式(兼容syslog)
ike_name = yes # 显示IKE会话标识
ike = 4 # IKEv1/v2协商细节
knl = 4 # 内核级SA状态跟踪
}
}
}
2. 密钥提取与格式转换
典型日志输出解析示例:
ini
08[CFG] proposals = ESP:AES_CBC_256/HMAC_SHA2_256_128/MODP_NONE/NO_EXT_SEQ
0[CHD] <conntun1|1> initiator SA seed => 69 bytes @ 0x000000502afff7b0
10[CHD] <conntun1|1> 0: 03 C8 C4 31 40 67 52 9E 8F C6 74 A4 E6 59 50 A6 [email protected].
10[CHD] <conntun1|1> 16: 45 30 F6 83 D1 E7 31 58 AA 9D 9D A6 A4 74 1D F8 E0....1X.....t..
10[CHD] <conntun1|1> 32: D1 59 DF ED E2 0D A6 88 20 FA 3B 85 AA 93 49 E7 .Y...... .;...I.
10[CHD] <conntun1|1> 48: C7 73 F1 B7 97 BF CA F3 16 CC F0 3A DD FA 72 D5 .s.........:..r.
10[CHD] <conntun1|1> 64: B1 09 01 4C 0C ...L.
10[CHD] <conntun1|1> responder SA seed => 69 bytes @ 0x000000502afff760
10[CHD] <conntun1|1> 0: 03 C2 32 6A 1C 67 52 9E 8F C6 74 A4 E6 59 50 A6 ..2j.gR...t..YP.
10[CHD] <conntun1|1> 16: 45 30 F6 83 D1 E7 31 58 AA 9D 9D A6 A4 74 1D F8 E0....1X.....t..
10[CHD] <conntun1|1> 32: D1 59 DF ED E2 0D A6 88 20 FA 3B 85 AA 93 49 E7 .Y...... .;...I.
10[CHD] <conntun1|1> 48: C7 73 F1 B7 97 BF CA F3 16 CC F0 3A DD FA 72 D5 .s.........:..r.
10[CHD] <conntun1|1> 64: B1 09 01 4C 0C ...L.
10[CHD] <conntun1|1> encryption initiator key => 32 bytes @ 0x00000192d1944a60
10[CHD] <conntun1|1> 0: 32 15 AB A7 9C F5 51 DC 5B 6D 20 95 31 DE 97 98 2.....Q.[m .1...
10[CHD] <conntun1|1> 16: 6B E0 AD 88 A6 D7 66 A9 48 74 45 03 BE B5 AA CD k.....f.HtE.....
10[CHD] <conntun1|1> encryption responder key => 32 bytes @ 0x00000192d1944880
10[CHD] <conntun1|1> 0: C6 7A 60 21 43 02 DF 3D A7 28 BA EF 58 BF 0C E0 .z`!C..=.(..X...
10[CHD] <conntun1|1> 16: B4 00 04 70 3B 2E 6F BC 9A E7 9A 1A 5F 48 76 DD ...p;.o....._Hv.
10[CHD] <conntun1|1> integrity initiator key => 32 bytes @ 0x00000192d1944730
10[CHD] <conntun1|1> 0: 31 51 BB 4B EB 91 C4 31 5D 27 22 D0 27 85 59 89 1Q.K...1]'".'.Y.
10[CHD] <conntun1|1> 16: E1 C9 AD 43 28 22 BF 62 FC 20 D6 A2 03 57 46 98 ...C(".b. ...WF.
10[CHD] <conntun1|1> integrity responder key => 32 bytes @ 0x00000192d19448e0
10[CHD] <conntun1|1> 0: 76 68 9E 6E 60 AC 89 5F 63 49 D2 91 45 2A 47 00 vh.n`.._cI..E*G.
10[CHD] <conntun1|1> 16: EA C9 D3 AD 42 7B E9 A7 AD E5 00 13 B0 9C 14 23 ....B{.........#
04[JOB] watcher got notification, rebuilding
04[JOB] watching 496 for reading
04[JOB] watching 792 for reading
10[CHD] <conntun1|1> adding inbound ESP SA
04[JOB] watcher going to poll() 3 fds
10[CHD] <conntun1|1> SPI 0xc2326a1c, src 119.141.124.1 dst 192.168.197.129
10[CHD] <conntun1|1> adding outbound ESP SA
10[CHD] <conntun1|1> SPI 0xc8c43140, src 192.168.197.129 dst 119.141.124.1
对应的wireshark配置如下:
yaml
Encryption Algorithm :AES_CBC_256
Integrity Algorithm :HMAC_SHA2_256_128
# Inbound SA (远端 → 本地)
SPI: 0xc2326a1c
Source: 119.141.124.1
Destination: 192.168.197.129
Encryption Key: 0xc67a60214302df3da728baef58bf0ce0b40004703b2e6fbc9ae79a1a5f4876dd
Integrity Key: 0x76689e6e60ac895f6349d291452a4700eac9d3ad427be9a7ade50013b09c1423
# Outbound SA (本地 → 远端)
SPI: 0xc8c43140
Source: 192.168.197.129
Destination: 119.141.124.1
Encryption Key: 0x3215aba79cf551dc5b6d209531de97986be0ad88a6d766a948744503beb5aacd
Integrity Key: 0x3151bb4beb91c4315d2722d027855989e1c9ad432822bf62fc20d6a203574698
对应填到wireshark配置里即可:
这样就可以看到解密的报文了,完美~