Snort_inline: Adapting the TCP stream reassembler

Posted on Jul 10, 2006

Currently I am rewriting a modification of the TCP reassembler in Snort_inline. Snort’s TCP reassembler is called Stream4 and it works fairly well in IDS mode, however it has some serious issues in inline mode. The biggest and most important issue is that Snort_inline cannot block an attack if it is detected in the reassembled stream. In Snort_inline 2.4 we made our first attempt to fix this with the stream4inline modification.

Stream4 was never designed to be used inline. It was designed to help the detection capabilities of Snort in IDS mode. This had a large consequence for the design. In Stream4, incoming packets are stored in a per-stream list of packets, before the packet is handled normally. After a number of packets have been piled up this way, the stream is flushed. This flush builds a pseudo packet containing the payloads of all the ack’d packets in the list. This pseudo packet is than ran through the detection engine, to see if it contains an attack. This works fine for IDS mode, since this way the attacks can be detected in the reassembled stream.

When running in inline this concept has a big flaw. In inline mode we can use the action drop. This action makes sure that the underlying subsystem (netfilter or ipfilter) discards the packet, making sure it will not reach the destination. The problem with Stream4 is that at the time the pseudo packet is inspected, its content is already accepted and ack’d by the end-host. This situation is of course very unsatisfying.

To deal with this problem in Snort_inline 2.4 we created the stream4inline option. This option is a modification to Stream4 that simply reassembles the stream for every packet received. Then instead of the normal packet, the reassembled stream is scanned every time. There are two performance problems with this approach. The first is that we call the functions to build the pseudo packet for every packet we receive. Since this function walks the packet list every time, this is expensive.

The second problem is harder to solve. Because we scan a sliding window, we end up scanning the same data multiple times. I have not really thought of an (easy) solution for this. The rewrite of the stream4inline option is mostly focused on two improvements. First the performance of the reassembly itself will be improved by keeping a cached version of the reassembled stream. Second, the implementation will be much better and robust. I will discuss it on a more technical level later.