-
-
Save rectalogic/ee2a48e47584fc0825dad9ffe571ec92 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
""" | |
Runs "ip xfrm state" and outputs lines to be added to ~/.wireshark/esp_sa | |
This process must be run using sudo. | |
This allows Wireshark to decrypt ipsec traffic captured with 'sudo tcpdump -vni any -U -w /tmp/esp.pcap "ip proto 50"' | |
""" | |
import sys | |
import subprocess | |
AUTH = { | |
("hmac(sha1)", "96"): "HMAC-SHA-1-96 [RFC2404]", | |
("hmac(sha512)", "256"): "HMAC-SHA-512-256 [RFC4868]", | |
} | |
ENC = { | |
"cbc(aes)": "AES-CBC [RFC3602]", | |
} | |
def parse_xfrm(ip=None): | |
"""Parse "ip xfrm state" output of the form | |
src 10.0.0.161 dst 69.27.252.3 | |
proto esp spi 0x66a336c8 reqid 6 mode tunnel | |
replay-window 32 flag af-unspec | |
auth-trunc hmac(sha1) 0x0472ec471f7342db23904ccae9091303c710a318 96 | |
enc cbc(aes) 0xc033ab0b0b7d0b28841ffc8c2746da60a6cfd32c19fcfcddbd0e318c430a94cd | |
src 69.27.252.3 dst 10.0.0.161 | |
proto esp spi 0xc36ee45f reqid 6 mode tunnel | |
replay-window 32 flag af-unspec | |
auth-trunc hmac(sha1) 0xccd0880af3650626adda310aa385661c6e100ec0 96 | |
enc cbc(aes) 0xbadc9e716a0cdb11cd86f7c4986e5a70200fd353ed06b2ee30680fb7c6bd320d | |
""" | |
connections = [] | |
connection = None | |
for line in subprocess.check_output(["ip", "xfrm", "state"]).split("\n"): | |
if line.startswith("src "): | |
if connection is not None: | |
connections.append(connection) | |
if ip is None or ip in line: | |
_, src, _, dst = line.split(" ") | |
connection = {"src": src, "dst": dst} | |
else: | |
connection = None | |
elif connection is not None: | |
if line.startswith("\tproto esp"): | |
connection["spi"] = line.split(" ")[3] | |
elif line.startswith("\tauth-trunc "): | |
_, auth, key, bits = line.split(" ") | |
connection["auth"] = AUTH[(auth, bits)] | |
connection["auth_key"] = key | |
elif line.startswith("\tenc "): | |
_, enc, key = line.split(" ") | |
connection["enc"] = ENC[enc] | |
connection["enc_key"] = key | |
if connection is not None: | |
connections.append(connection) | |
return connections | |
def output_wireshark(connections): | |
"""Output ~/.wireshark/esp_sa lines of the form | |
"IPv4","10.0.0.161","69.27.252.3","0x66a336c8","AES-CBC [RFC3602]","0xc033ab0b0b7d0b28841ffc8c2746da60a6cfd32c19fcfcddbd0e318c430a94cd","HMAC-SHA-1-96 [RFC2404]","0x0472ec471f7342db23904ccae9091303c710a318" | |
"IPv4","69.27.252.3","10.0.0.161","0xc36ee45f","AES-CBC [RFC3602]","0xbadc9e716a0cdb11cd86f7c4986e5a70200fd353ed06b2ee30680fb7c6bd320d","HMAC-SHA-1-96 [RFC2404]","0xccd0880af3650626adda310aa385661c6e100ec0" | |
""" | |
for connection in connections: | |
print('"IPv4","{src}","{dst}","{spi}","{enc}","{enc_key}","{auth}","{auth_key}"'.format(**connection)) | |
if __name__ == "__main__": | |
ip = sys.argv[1] if len(sys.argv) > 1 else None | |
connections = parse_xfrm(ip) | |
output_wireshark(connections) |
I forked this, merged in rbdixon's changes, changed to Python 3 (as I'm on Ubuntu 20.04 without Python 2), fixed AES-GCM dissection (by mapping the ip xfrm state
bits value to a wireshark "ANY x bit authentication [no checking]" authentication type), and added some other authentication types (we had sha384 used in one case). You can find my fork here: https://gist.github.com/rlaager/c5b0ee093c96fc3401b83bcd2efae356
https://github.com/rlaager/ipsec2wireshark
Thanks for this script!
Hey Andrew,
I work for a company that uses the strongswan service, as part of an IPSec product.
We build strongswan from source, as we need the latest version of the code and include some tools.
I came across Richard Laager's ipsec2wireshark.py tool, which he branched from your original script.
I was considering including the tool in our strongswan RPM but was wondering if you would be ok
with this? and if so, what licensing applies?
Thanks,
Conor Doyle
@cdoyle-druid You can include it. I'll license it under MIT license https://choosealicense.com/licenses/mit/
Hey andrew, ok thanks. Conor
Thank you for sharing. I made a few tweaks locally that may be useful to others working with GCM(AES) tunnels:
Parse two additional stanzas in
ip xfrm state
output: