Skip to content

tcpassembly and reassembly: improper RST handling #425

@WGH-

Description

@WGH-

I have two test cases:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions