Help with custom rule

I created a rule as follow:

alert ip $HOME_NET any -> $EXTERNAL_NET any (msg:"Threatview.io blacklisted IP traffic OUTBOUND";iprep:dst,threatview-badip,=,100;sid:20000000;rev:1;classtype:bad-ip;)

I noticed that this rule also triggers in response to traffic from that blacklisted IP because flows are bidirectional. Is it possible to modify the rule only to trigger when the traffic is originated in my local HOME_NET?

Thanks

I don’t have a direct answer to your question, but this did remind me of a common problem with IP lists.

At one point I had to figure out a method to ignore alerts from external ips that were on a list, that didn’t result in a successful TCP connection. For example, if the IP address on the DSHIELD drop list scanned our network, but never found an open port, our SOC didn’t want to deal with that noise.

If suricata is the only option to do this, I’d suggest using datasets instead of IP rep. IP rep, as per the docs, only supports the ip protocol.

But with datasets, you could something like this…maybe? This is totally untested.

alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"Threatview.io blocklisted IP traffic - Outbound"; flow:established,to_server; ip.dst; dataset:isset,threatview-badip,type ip, load threatview-badip.list;)

Broken out:

  • flow:established filters out any sessions that didn’t make a 3WHS.
  • Adding the to_server option makes sure that our $HOME_NET src ip is the tcp client.
  • ip.dst is a sticky buffer that allows us to target that dst ip.

Now, this will only alert if that tcp session gets established, which, based on the outbound nature would be worth investigating. but what if that “bad ip” just isn’t listening anymore. An attempted but failed outbound connection might still mean there is malware/beacon activity/etc on the src ip machine.

Maybe two rules is the answer there? With different classtypes/priorities? maybe using flowbits that are set and unset (this would be a little complex) to make sure you don’t get duplicate alerts, maybe thresholds are good enough. You’d have to play around if you wanted more detailed alerts depending on the state of the session.

HA, the dataset use case is actually an example when looking at the ip.dst sticky buffer keyword: 8.39. IP Addresses Match — Suricata 7.0.4 documentation

Oh, even better, while I was looking at the docs, there is datarep (TIL), same logic would apply to using tcp and flow:established but you get the added benefit of using that “score” value.

https://docs.suricata.io/en/suricata-7.0.4/rules/datasets.html#datarep