Suricata flow keyword causing cpu/mem overload

Hello all,

We are using Suricata 6.0.8 and have about 62080 rules loaded into it. Everything runs fine at this point with drops below 1% and cpu/mem normal.

About 8000 rules are alerting on outbound traffic towards IP addresses. Those rules are only supposed to alert when the traffic is initiated from within the network (and not as a response (rst,ack) to inward traffic such as scanning). For this reason i recently added the keyword “flow: to_server” to these rules.

The rules then look like this :
alert ip $HOME_NET any → 174.48.35.112 any (msg: “Outgoing To IP: 174.48.35.112”; flow:to_server; classtype:trojan-activity; sid:47681332; rev:1; priority:0;)

However, after adding the keyword “flow: to_server” to these rules, our server goes to 100% on CPU and Memory usage and the droprate goes to 70%

My questions :

  • Is it normal that adding the flow keyword adds such an amount of load on the server?
  • Is the flow keyword the correct way to achieve what I want?

All help is welcome! Thanks in advance

Server stats : 125GB memory, 88 core cpu, Intel(R) Xeon(R) Gold 6238 CPU @ 2.10GHz

Cpu usage with “flow:to_server” on the rules :

Stats.log with keyword “flow:to_server” on the rules :

Counter | TM Name | Value

capture.kernel_packets | Total | 25284813778
capture.kernel_drops | Total | 21716314767
decoder.pkts | Total | 3536501012
decoder.bytes | Total | 1746492034230
decoder.invalid | Total | 2137
decoder.ipv4 | Total | 3547942748
decoder.ipv6 | Total | 32762
decoder.ethernet | Total | 3536501012
decoder.tcp | Total | 3211581170
decoder.udp | Total | 293104769
decoder.icmpv4 | Total | 6639923
decoder.icmpv6 | Total | 10049
decoder.gre | Total | 14590128
decoder.vlan | Total | 3536468187
decoder.vxlan | Total | 59
decoder.teredo | Total | 206
decoder.avg_pkt_size | Total | 493
decoder.max_pkt_size | Total | 1518
flow.tcp | Total | 741593702
flow.udp | Total | 105708432
flow.icmpv4 | Total | 4779967
flow.icmpv6 | Total | 3591
defrag.ipv4.fragments | Total | 3895431
defrag.ipv4.reassembled | Total | 576641
decoder.event.ipv4.trunc_pkt | Total | 2137
decoder.event.ipv4.opt_pad_required | Total | 429
decoder.event.icmpv4.unknown_code | Total | 7
decoder.event.ipv6.zero_len_padn | Total | 9756
decoder.event.ipv4.frag_overlap | Total | 1
tcp.sessions | Total | 83328603
tcp.pseudo | Total | 5542628
tcp.invalid_checksum | Total | 80
tcp.syn | Total | 83479215
tcp.synack | Total | 69438894
tcp.rst | Total | 37475888
tcp.pkt_on_wrong_thread | Total | 8
tcp.stream_depth_reached | Total | 574
tcp.reassembly_gap | Total | 5162822
tcp.overlap | Total | 27241210
tcp.insert_list_fail | Total | 7
detect.alert | Total | 74
app_layer.flow.http | Total | 1983862
app_layer.tx.http | Total | 2850703
app_layer.flow.smtp | Total | 11
app_layer.tx.smtp | Total | 16
app_layer.flow.tls | Total | 209695
app_layer.flow.ssh | Total | 316
app_layer.flow.smb | Total | 73968
app_layer.tx.smb | Total | 1136719
app_layer.flow.dcerpc_tcp | Total | 140602
app_layer.flow.dns_tcp | Total | 7281
app_layer.tx.dns_tcp | Total | 16087
app_layer.flow.enip | Total | 115
app_layer.tx.enip | Total | 122
app_layer.flow.ntp | Total | 54169
app_layer.tx.ntp | Total | 49280
app_layer.flow.tftp | Total | 113818
app_layer.tx.tftp | Total | 113818
app_layer.flow.ikev2 | Total | 8700
app_layer.flow.krb5_tcp | Total | 47091
app_layer.tx.krb5_tcp | Total | 44912
app_layer.flow.dhcp | Total | 969587
app_layer.tx.dhcp | Total | 1085549
app_layer.flow.snmp | Total | 2246245
app_layer.tx.snmp | Total | 4790077
app_layer.flow.failed_tcp | Total | 196191
app_layer.flow.dcerpc_udp | Total | 394
app_layer.flow.dns_udp | Total | 21873786
app_layer.tx.dns_udp | Total | 22777600
app_layer.flow.krb5_udp | Total | 8092
app_layer.flow.failed_udp | Total | 80433526
flow_mgr.closed_pruned | Total | 2885168
flow_mgr.new_pruned | Total | 843502777
flow_mgr.est_pruned | Total | 9054863
flow.spare | Total | 271972
flow.tcp_reuse | Total | 12116
flow_mgr.flows_checked | Total | 23084
flow_mgr.flows_notimeout | Total | 9646
flow_mgr.flows_timeout | Total | 13438
flow_mgr.flows_timeout_inuse | Total | 141
flow_mgr.flows_removed | Total | 13297
flow_mgr.rows_checked | Total | 262144
flow_mgr.rows_skipped | Total | 238136
flow_mgr.rows_empty | Total | 7309
flow_mgr.rows_maxlen | Total | 6
tcp.memuse | Total | 42749600
tcp.reassembly_memuse | Total | 1320128460
http.memuse | Total | 217487061
flow.memuse | Total | 144682456

By adding the flow:to_server statement the rule is no longer considered “ip only”. IP only rules are processed differently, and check just once per flow. By adding the statement the rule is now checked for each packet, instead of just once per flow.

Thanks, that’s good to know
Is there another way to achieve what I intended? (alerting on outbound traffic initiated from within and not a response to inbound traffic)

You could try the new dataset for IPs but do you have an example where you need the flow:to_server?
Since the HOME_NET should just contain your local network and if you have a outbound IP as target, that should be enough.