Will a single NIC work for snort3 in IPS mode if pure wireless?

Hyperscan isn't available for the arch. Only x86 :confused:

That's right, it's an Intel project, so the only thing left to do is to pin it and reduce the number of queues to 3, one queue for each pinned cpu.

Latest version of what? The input path is protected if you have the nfq table configured on the proper chain, uci set snort.nfq.chain_type=prerouting (assuming you also want to protect the lan devices via the forward path).

Well, snort operates on interfaces and can't apply its address-based filtering until it has already grabbed the packets, so there's always overhead even for packets that get ignored.

I don't have any ideas on what to try for this, other than Rene's suggestions about snaplen and queue_maxlen. There's a balance you have to find for tuning those, they can balloon memory usage which might cause other issues.

1 Like
#!/bin/sh
# config
wan_device="" #setting a device between the quotation marks disable auto detection, "" autotection
	      #you can set more then one interface with a comma between the device names for example "eth0,eth1"
#config

verbose=false

if [ -z "$wan_device" ]; then

wan_device=$(uci get network.wan.device)

fi

nft list ruleset | grep -q 'IPS' && nft delete chain inet fw4 IPS_output && nft delete chain inet fw4 IPS_input

nft -f - <<TABLE

table inet fw4 {

          chain IPS_output {

             type filter hook postrouting priority 225; policy accept;

oifname { $wan_device,Wg0 } tcp flags ack ct state established counter accept

oifname { $wan_device } udp dport 51820 ct state established counter accept

oifname { $wan_device,Wg0 } counter queue flags bypass to 5-7

}

chain IPS_input {

              type filter hook prerouting priority 300; policy accept;

iifname { $wan_device } udp sport 51820 ct state established counter accept

iifname { $wan_device,Wg0 } counter queue flags bypass to 5-7

	}
}

TABLE

$verbose

exit 0

Here is the latest version of the snort-table script as you can see there have been significant changes the data input is now monitored at the prerouting hook and the data output at the postrouting hook.

//edit/ In this way, the system services are also completely protected if the queue is only set on the postrouting hook, the data stream to the system services is not monitored if it is only set on the prerouting hook, the data stream from the system services is not monitored.

1 Like

Thanks for pointing that out. Changing it to 65531 did not change the CPU saturation nor increase the download speed.

Yes, I have this setup in /etc/config/snort:

config snort 'snort'
...
  option home_net        '192.168.1.0/24 192.168.3.0/24' # a string
  option external_net    '!$HOME_NET'            # a string
...

I changed the threads to 3 now. What is the method/syntax to pin these 3?

Ah! That makes total sense.

If you snort with nice -n -20 taskset -a -c 1,2,3 snort ... snort is bound to cores 1-3 with the highest priority, but you have to check beforehand with /proc/cpuinfo whether the cpu numbering is correct, in some cases the numbering is not continuous or the next number is not a real core but only the hypherthreading part. You would then have to insert this in /etc/init.d/snort before $PROG -q -i "$interface" -c... have done this in an extra script with which I start snort because I have integrated other things there.

1 Like

@efahl - for some reason I am getting this error despite having the config file with correct syntax:

# snort-mgr check
ERROR: In option enabled='1', must be one of [0, 1]
Errors during generation of snort config

and

# cat /etc/config/snort
#
config snort 'snort'
	option enabled         '1'              # one of [0, 1]
	option manual          '0'              # one of [0, 1]
	option oinkcode        ''               # a string
	option home_net        '192.168.1.0/24 192.168.3.0/24' # a string
	option external_net    '!$HOME_NET'            # a string
	option config_dir      '/etc/snort'     # a path string
	option temp_dir        '/var/snort.d'   # a path string
	option log_dir         '/mnt'       # a path string
	option logging         '1'              # one of [0, 1]
	option openappid       '0'              # one of [0, 1]
	option mode            'ids'            # one of [ids, ips]
	option method          'nfq'           # one of [pcap, afpacket, nfq]
	option action          'drop'        # one of [default, alert, block, drop, reject]
	option interface       'eth1'           # a string
	option snaplen         '65531'           # 1518 <= x <= 65535
	option include         '/etc/snort/include.snort'               # a path string

config nfq 'nfq'
	option queue_count     '3'              # 1 <= x <= 16
	option queue_start     '3'              # 1 <= x <= 32768
	option queue_maxlen    '8192'           # 1024 <= x <= 65536
	option fanout_type     'lb'           # one of [hash, lb, cpu, rollover, rnd, qm]
	option thread_count    '3'              # 0 <= x <= 32
	option chain_type      'postrouting'          # one of [prerouting, input, forward, output, postrouting]
	option chain_priority  '300'         # one of [raw, filter, 300]
	option include         '/etc/snort/include.nfq'               # a path string

Any ideas?

That's very weird. What do you see when you run just uci get?

$ uci get snort.snort.enabled
1

@efahl -
It is:

# uci get snort.snort.enabled
1

There were some recent changes to ucode, specifically the in operator which I use to check the config... So let's check your version, here's the one I'm running:

$ opkg info ucode
Package: ucode
Version: 2024.02.21~ba3855ae-r1
...

@efahl - it's a snapshot I just built:

# opkg info ucode
Package: ucode
Version: 2024.04.07~5507654a-r1
Depends: libc, libucode20230711
Status: install ok installed
Architecture: aarch64_cortex-a53
Installed-Time: 1712939303

Could you try this, see if it returns true like mine does?

$ ucode -p " '1' in [0, 1] "
true
# ucode -p " '1' in [0, 1] "
false

AHA. Regression in ucode, I'll put in an issue.
EDIT: https://github.com/openwrt/openwrt/issues/15144
EDIT 2: Turns out to be an expected change in the semantics of ucode,
PR submitted https://github.com/openwrt/packages/pull/23916/files

For now, you could hack /usr/share/snort/main.c, down at line 44 in the contains function, just add return true;:

 42 const ConfigItem = {
 43         contains: function(value) {

                    return true;        // ADD THIS LINE, skip the rest of the function.

 44                 // Check if the value is contained in the listed values,
 45                 // depending on the item type.
 46                 switch (this.type) {
1 Like

Worked. Thanks. I was about to revert
08639a5e47d8ec2d78693493924081d841601028 and build.

@xxxx @efahl - is this safe to ignore or do I need to tweak something to prevent it?

# dmesg
...
[ 5424.304872] net_ratelimit: 103 callbacks suppressed
[ 5424.304886] nfnetlink_queue: nf_queue: full at 1024 entries, dropping packets(s)
[ 5424.317161] nfnetlink_queue: nf_queue: full at 1024 entries, dropping packets(s)
[ 5424.324612] nfnetlink_queue: nf_queue: full at 1024 entries, dropping packets(s)
...
/etc/config/snort
config snort 'snort'
	option enabled         '1'              # one of [0, 1]
	option manual          '0'              # one of [0, 1]
	option oinkcode        ''               # a string
	option home_net        '192.168.1.0/24 192.168.3.0/24' # a string
	option external_net    '!$HOME_NET'            # a string
	option config_dir      '/etc/snort'     # a path string
	option temp_dir        '/var/snort.d'   # a path string
	option log_dir         '/mnt'       # a path string
	option logging         '1'              # one of [0, 1]
	option openappid       '0'              # one of [0, 1]
	option mode            'ids'            # one of [ids, ips]
	#option mode            'ips'            # one of [ids, ips]
	option method          'nfq'           # one of [pcap, afpacket, nfq]
	option action          'drop'        # one of [default, alert, block, drop, reject]
	option interface       'eth1'           # a string
	option snaplen         '65531'           # 1518 <= x <= 65535
	option include         '/etc/snort/include.snort'               # a path string

config nfq 'nfq'
	option queue_count     '3'              # 1 <= x <= 16
	option queue_start     '3'              # 1 <= x <= 32768
	option queue_maxlen    '8192'           # 1024 <= x <= 65536
	option fanout_type     'lb'           # one of [hash, lb, cpu, rollover, rnd, qm]
	option thread_count    '3'              # 0 <= x <= 32
	option chain_type      'postrouting'          # one of [prerouting, input, forward, output, postrouting]
	option chain_priority  '300'         # one of [raw, filter, 300]
	option include         '/etc/snort/include.nfq'               # a path string
/etc/snort/include.snort
-- Disable output to syslog
alert_syslog = nil
alert_json = nil

-- Enable output to alert_fast.txt
alert_fast = {
  file = true,
  packet = false,
}

network = {
  checksum_eval = 'none',
}

search_engine = {
  search_method = 'hyperscan',
  offload_search_method ='hyperscan',
  detect_raw_tcp = true,
}

detection = {
  hyperscan_literals = true,
  pcre_to_regex = true,
}
/etc/snort/include.nfq
    ct state invalid drop;
    oifname "{{ snort.interface }}" tcp flags ack ct state established counter accept

In the start line in /etc/init.d/snort add at end:

--daq-var queue_maxlen=8192

Why this is not taken over although you already have higher values in the /etc/config/snort config file I have no idea, @efahl has to take care of it. I said that it is better to start Snort with parameters.

@xxxx - I appended the line but still got the dmesg messages:

# grep max /etc/init.d/snort 
   procd_set_param command $PROG -q -i "$interface" --daq-var queue_maxlen=8192 -c "${config_dir%/}/snort.lua" --tweaks local

I'm pretty sure it's safe (but slow) to ignore them, as they'll be retransmitted if they're important enough.

I'm digging through https://github.com/snort3/libdaq/blob/master/modules/nfq/daq_nfq.c#L427 trying to figure out if things are going wrong on the snort side or in nfnetlink itself. There's an undocumented daq_var debug (a couple lines above the queue_maxlen handling), but I can't get it to produce any output, not sure where stdin from netlink is going (I don't see it in console, dmesg or log)... I'd be very interested in what the output at line 510 is.

1 Like