summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2020-06-23 16:13:00 +0200
committerPeter Wu <peter@lekensteyn.nl>2020-06-23 16:13:00 +0200
commit4a7586873954c711b9766c4ead23134d8d923281 (patch)
treed45cca7e9185d7b980fd7d8ea69d6eb616d9b828
parent96cb5ac11dfb7f9e2da394e53aff651ecd09ae82 (diff)
downloadwireshark-notes-4a7586873954c711b9766c4ead23134d8d923281.tar.gz
reordertcp.py: quick utility to sort a TCP stream in a capture
There is a known issue where out-of-order TCP segments breaks HTTP/2 dissection and TLS reassembly, even with the TCP Reassemble out-of-order segments preference enabled. This utility works around that issue by sorting TCP segments within a capture. Requires scapy, install with: pip3 install scapy
-rwxr-xr-xreordertcp.py58
1 files changed, 58 insertions, 0 deletions
diff --git a/reordertcp.py b/reordertcp.py
new file mode 100755
index 0000000..0719fad
--- /dev/null
+++ b/reordertcp.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Reorder a pcap file with a single TCP stream. Convert with
+# 'tshark -r input.pcapng -w output.pcap -F pcap' if scapy crashes with
+# "struct.error: 'I' format requires 0 <= number <= 4294967295" in
+# _write_packet.
+
+import argparse
+import logging
+import time
+
+from scapy.all import *
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--linktype', type=int, default=1,
+ help='DLT (0 for Null/Loopback, 1 for Ethernet)')
+parser.add_argument('infile')
+parser.add_argument('outfile')
+
+
+def main():
+ args = parser.parse_args()
+ logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO)
+
+ t1 = time.monotonic()
+ packets = rdpcap(args.infile)
+ t2 = time.monotonic()
+ logging.info('Capture loaded in %.3f seconds', t2 - t1)
+
+ # Assume a single stream
+ clt = packets[0][TCP]
+ svr = packets[1][TCP]
+ assert clt.flags.S and not clt.flags.A
+ assert svr.flags.S and svr.flags.A
+ assert clt.sport == svr.dport
+ assert clt.dport == svr.sport
+ assert clt.dport != clt.sport
+
+ def seq_key(p):
+ t = p[TCP]
+ if t.sport == svr.sport:
+ return t.seq - svr.seq
+ elif t.dport == svr.sport:
+ return t.ack - svr.seq
+ else:
+ raise RuntimeError(f'Unexpected {t}')
+ packets.sort(key=seq_key)
+
+ t1 = time.monotonic()
+ wrpcap(args.outfile, packets, linktype=args.linktype)
+ t2 = time.monotonic()
+ logging.info('Capture written in %.3f seconds', t2 - t1)
+
+
+if __name__ == '__main__':
+ try:
+ main()
+ except KeyboardInterrupt:
+ pass