tcp, tcp-pkt, tcp-stream in Suricata rule

In Suricata’s official document, there are oversimplified descriptions for these three protocol options, and it’s really confusing.

  • tcp (for tcp-traffic)
  • tcp-pkt (for matching content in individual tcp packets)
  • tcp-stream (for matching content only in a reassembled tcp stream)

In order to figure out the difference between these three options, I did some experiments and tried to summarize some patterns.

  • tcp (for tcp traffic)
    • It looks like Suricata performs both individual packet detection (tcp-pkt) and stream detection (tcp-stream).
    • Under normal circumstances, Suricata will output only the stream detection result if both detections produce results and overlap. If only one type of detection produces a result, it will output that result accordingly.
    • Like tcp-stream, it may
    • However, in certain “unexpected scenarios,” Suricata may output both individual packet detection and stream detection results, even if they overlap in the same stream. I’ve conducted some experiments but haven’t identified a clear pattern for this behavior.
    • This is based on my experiments. The official documentation does not explicitly explain, and the real answer might only be found by analyzing Suricata’s source code. (´・_・`)
  • tcp-pkt (for matching content in individual tcp packets)
    • If you want the packet number matched by a Suricata rule (content: "xxx") to be the same as the packet filtered by the Wireshark (tcp contains "xxx"), then you should select tcp-pkt instead of the other two.
  • tcp-stream (for matching content only in a reassembled tcp stream)
    • Theoretically, Suricata performs matching in the stream after TCP reassembly. However, it doesn’t necessarily reconstruct the entire TCP stream. The extent of reassembly depends on Suricata’s reassembly configuration and the length of the current TCP stream (It may still be active).
    • So, if you analyze an offline pcap traffic file using tcp or tcp-stream options, Suricata may output an inaccurate packet number (pcap_cnt) that differs from the exact TCP packet filtered in Wireshark. It may be the FIN packet of the stream or just a subsequence packet in the stream. However, they indeed belong to the same TCP stream.

Experiment

I got a pcap file: tcp-ethereal-trace-1, and the traffic has an HTTP stream.

I wrote these four rules to match the string ‘POST /et‘ at the No. 4 packet shown in Wireshark.

alert tcp-pkt any any -> 128.119.245.12 80 (msg:"funway - String Check"; flow:established,to_server; content:"POST /et"; classtype:string-detect; sid:1000001; rev:1;)

alert tcp-stream any any -> 128.119.245.12 80 (msg:"funway - String Check"; flow:established,to_server; content:"POST /et"; classtype:string-detect; sid:1000002; rev:1;)

alert tcp any any -> 128.119.245.12 80 (msg:"funway - String Check"; flow:established,to_server; content:"POST /et"; classtype:string-detect; sid:1000003; rev:1;)

alert tcp any any -> 128.119.245.12 80 (msg:"funway - String Check"; flow:established,to_server; content:"POST /et"; depth:10; classtype:string-detect; sid:1000004; rev:1;)

The results are shown below:

  • Rule 1 tcp-pkt matches one packet, which is the same as the No. 4 packet in Wireshark.
  • Rule 2 tcp-stream matches one packet, which is a subsequence packet in the TCP stream.
  • Rule 3 tcp outputs only one result, same with tcp-stream.
  • Rule 4 tcp with depth option outputs two results, like a combination of tcp-pkt and tcp-stream. W…eird.

Then, I tried to use these three options to match a string that is split into two packets.

The results are shown below, tcp-pkt matches nothing.

Match “within 90 days”, which is split into two TCP packets.

Leave a Comment

Your email address will not be published. Required fields are marked *