-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I have two test cases:
- Client sends SYN, the server responds with RST/ACK. This is what usually happens when somebody tries to connect to a closed port. http://cdn.big.dong.solutions/a2441ae2-62c4-4cb7-b2dc-fc26e3f40902/syn_reset.pcap
- Client and server do proper handshake, exchange some data, and then connection is terminated with RST from one side. No further packets come. Happens, among other cases. when connection is closed when there's still data in receive queue. http://cdn.big.dong.solutions/a2441ae2-62c4-4cb7-b2dc-fc26e3f40902/reset_session.pcap
I have written simple code that traces the reassembly process. https://gist.github.com/WGH-/8d316e46e9a198440c213513c798b64c
In the first scenario, trace looks like this:
2018/03/06 18:45:09 packet 1: calling AssembleWithTimestamp()
2018/03/06 18:45:09 stream #1: (created)
2018/03/06 18:45:09 stream #1: Reassembled
2018/03/06 18:45:09 packet 2: calling AssembleWithTimestamp()
2018/03/06 18:45:09 calling FlushAll
2018/03/06 18:45:09 stream #1: ReassemblyComplete
RST packet doesn't cause stream to be closed/aborted. It's only closed when FlushAll is explicitly called. Any port scan will cause tcpreassembly code to create a lot of streams that will never be cleaned up, unless flush is regularly, even though they can be properly cleaned up right away.
The second scenario:
2018/03/06 18:48:02 packet 1: calling AssembleWithTimestamp()
2018/03/06 18:48:02 stream #1: (created)
2018/03/06 18:48:02 stream #1: Reassembled
2018/03/06 18:48:02 packet 2: calling AssembleWithTimestamp()
2018/03/06 18:48:02 stream #2: (created)
2018/03/06 18:48:02 stream #2: Reassembled
2018/03/06 18:48:02 packet 3: calling AssembleWithTimestamp()
2018/03/06 18:48:02 packet 4: calling AssembleWithTimestamp()
2018/03/06 18:48:02 stream #1: Reassembled
2018/03/06 18:48:02 packet 5: calling AssembleWithTimestamp()
2018/03/06 18:48:02 packet 6: calling AssembleWithTimestamp()
2018/03/06 18:48:02 stream #2: Reassembled
2018/03/06 18:48:02 stream #2: ReassemblyComplete
2018/03/06 18:48:02 calling FlushAll
2018/03/06 18:48:02 stream #1: ReassemblyComplete
In this case, RST successfully terminates stream, but only in one direction. The other direction is cleaned up only when FlushAll is called.
For comparison, this is how the trace looks like when connection is closed with proper exchange of FIN packets: http://cdn.big.dong.solutions/a2441ae2-62c4-4cb7-b2dc-fc26e3f40902/normal_session.pcap
2018/03/06 19:09:58 packet 1: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #1: (created)
2018/03/06 19:09:58 stream #1: Reassembled
2018/03/06 19:09:58 packet 2: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #2: (created)
2018/03/06 19:09:58 stream #2: Reassembled
2018/03/06 19:09:58 packet 3: calling AssembleWithTimestamp()
2018/03/06 19:09:58 packet 4: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #1: Reassembled
2018/03/06 19:09:58 packet 5: calling AssembleWithTimestamp()
2018/03/06 19:09:58 packet 6: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #2: Reassembled
2018/03/06 19:09:58 packet 7: calling AssembleWithTimestamp()
2018/03/06 19:09:58 packet 8: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #1: Reassembled
2018/03/06 19:09:58 stream #1: ReassemblyComplete
2018/03/06 19:09:58 packet 9: calling AssembleWithTimestamp()
2018/03/06 19:09:58 stream #2: Reassembled
2018/03/06 19:09:58 stream #2: ReassemblyComplete
2018/03/06 19:09:58 packet 10: calling AssembleWithTimestamp()
2018/03/06 19:09:58 calling FlushAll
In this case, streams are cleaned up without a call to FlushAll.
Even though reassembly module seems to be more advanced than tcpassembly, it suffers from the same problem. https://gist.github.com/WGH-/ddd6390f37ceb7455e4f22b4ee5eeb9f
2018/03/06 19:13:41 packet 1: calling AssembleWithTimestamp()
2018/03/06 19:13:41 stream #1: (created)
2018/03/06 19:13:41 stream #1: Accept
2018/03/06 19:13:41 stream #1: ReassembledSG
2018/03/06 19:13:41 packet 2: calling AssembleWithTimestamp()
2018/03/06 19:13:41 stream #1: Accept
2018/03/06 19:13:41 calling FlushAll
2018/03/06 19:13:41 stream #1: ReassemblyComplete
2018/03/06 19:13:54 packet 1: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: (created)
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 stream #1: ReassembledSG
2018/03/06 19:13:54 packet 2: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 stream #1: ReassembledSG
2018/03/06 19:13:54 packet 3: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 packet 4: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 stream #1: ReassembledSG
2018/03/06 19:13:54 packet 5: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 packet 6: calling AssembleWithTimestamp()
2018/03/06 19:13:54 stream #1: Accept
2018/03/06 19:13:54 stream #1: ReassembledSG
2018/03/06 19:13:54 calling FlushAll
2018/03/06 19:13:54 stream #1: ReassemblyComplete
2018/03/06 19:14:08 packet 1: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: (created)
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 packet 2: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 packet 3: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 packet 4: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 packet 5: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 packet 6: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 packet 7: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 packet 8: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 packet 9: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 stream #1: ReassembledSG
2018/03/06 19:14:08 stream #1: ReassemblyComplete
2018/03/06 19:14:08 packet 10: calling AssembleWithTimestamp()
2018/03/06 19:14:08 stream #1: Accept
2018/03/06 19:14:08 calling FlushAll
I will likely try to fix this and submit an PR, but first, I'd like to discuss this a bit to make sure my conclusions are correct.