Suricata Custom Rule Flow

  • Dear community,

    I am having problems with the following scenario:

    I set up two Pis wich are connected to my pfSense APU. On one Pi I started netcat with nc -l port, on the other Pi I sent messages to the server via netcat.
    Now I am trying to filter established traffic (after the tcp handshake), let's say with the rule:

    pass tcp any any -> $MY_NETWORK $MY_PORT (msg:"test"; priority:1; content:"Hello"; flow:established; sid:12345; rev:1;)

    and drop everything else with

    drop ip any any <> any any (msg:"default deny rule suricata"; priority:5; sid:54321; rev:1;)

    My problem: All traffic gets dropped. I think this happens, because the first SYN packet from the client gets dropped.
    But if I add a rule for this very first SYN packet like so:

    pass tcp any any -> $MY_NETWORK $MY_PORT (msg:"allow syn"; flags:S; dsize:0; sid:123; rev:1;)

    all traffic to the netcat server is passed through, even without the "Hello" content.

    So my question is: How can I allow the handshake but filter the actual payload?

    Any help would be greatly appreciated.

  • Update:

    When removing the default deny rule and instead adding a new drop rule which negates the pass rule, I can filter the payload.  (Bad payload gets dropped)

    pass tcp any any -> $MY_NETWORK $MY_PORT (msg:"test"; priority:1; content:"Hello"; flow:established; sid:12345; rev:1;)
    drop tcp any any -> $MY_NETWORK $MY_PORT (msg:"test"; priority:1; content:!"Hello"; flow:established; sid:12344; rev:1;)

    But this way I lose control over the tcp handshake, as I would like to explicitly allow every single packet in the handshake via a rule, and therefore be able to turn my default deny rule on. My goal is to whitelist the traffic and not blacklist it.

    Any suggestions?

  • Two questions.

    (1) First, what mode (Inline IPS or Legacy Mode) blocking is being utilized?

    (2) Other than the details you stated (two Pi boxes communicating), what is the "big picture" of what you want to accomplish?  In other words, what is the reason for wanting to do what you describe?  There may be another way to achieve the result is why I am asking.

    Your rules are giving you trouble because Suricata does not have enough information to filter on.  For example, you would need to restrict your pass rule to a specific host and port instead of an entire network and port to use the rules as you have them written.


  • Hi,

    thanks for your reply. I am running Suricata in Inline mode. The goal is to filter payload in a dummy protocol between the two Pis, where the tcp handshake is still passed through.

    I now added rules like the following one to allow the handshake to pass, without allowing the whole stream to pass:

    pass tcp-pkt $MY_NETWORK any -> any any (msg:"pass synack"; flags:SA; dsize:0; sid:13245; rev:1;)

    With those rules I was able to reenable my default deny rule.

    While it seems to be working, are there more elegant ways of acomplishing this?

  • I still don't really understand what you want as an end game here.  Your last rule is simply going to pass everything on any port that is sourced from $MY_NETWORK to anywhere so long as the SYN and ACK flags are set on the TCP packet.  PASS rules have priority in the processing chain, and once a PASS rule matches for a packet no other examination takes place against any additional rules.  The packet is passed.

    Why don't you just filter by specific IP addresses (and maybe ports if possible) within the firewall itself and leave the IDS out of it?  Suricata and Snort rules typically are used to find malicious content, so they are designed to trigger when certain byte sequences are detected within the payload.  It seems like you are wanting to use to pass only selected content.  That is going to be a bit harder.


Log in to reply