diff options
author | Peter Wu <peter@lekensteyn.nl> | 2020-06-23 16:13:00 +0200 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2020-06-23 16:13:00 +0200 |
commit | 4a7586873954c711b9766c4ead23134d8d923281 (patch) | |
tree | d45cca7e9185d7b980fd7d8ea69d6eb616d9b828 | |
parent | 96cb5ac11dfb7f9e2da394e53aff651ecd09ae82 (diff) | |
download | wireshark-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-x | reordertcp.py | 58 |
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 |