openwrt / openwrt/packages

snort3: snort.uc passes --daq via the snort table, so every daq.modules variable is discarded (queue_maxlen has no effect, fail_open is never applied)

Open Beginner friendly
#30,392 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

release/25.12
Dominant language
Makefile
Stars
4.6k
Forks
4k
Avg merge
3d 12h
Merged PRs (30d)
134

Description

Maintainer: @flyn-org, @graysky2 (template author: @efahl)
Environment: OpenWrt 25.12.5 x86/64, snort3 3.10.0.0-r1, libdaq3 3.0.23, kernel 6.12 (template identical on master, 3.12.2.0-r1)

Environment

Reproduced on OpenWrt 25.12.5 x86/64 with snort3 3.10.0.0-r1, libdaq3 3.0.23, kernel 6.12. The template on master (net/snort3 3.12.2.0-r1, files/snort.uc) is unchanged since 203e941 (2024-02-05) and byte-identical on openwrt-25.12. libdaq3 on master is 3.0.27; modules/nfq/daq_nfq.c is unchanged since v3.0.23.

Summary

With method=nfq, snort-mgr setup renders both

snort = {
  ['-Q'] = true,
  ['--daq'] = 'nfq',                          -- snort.uc line 44
  ['--max-packet-threads'] = 4,
}
daq = {
  ...
  modules = {                                 -- snort.uc lines 80-86 (daq table 75-87)
    { name = 'nfq', mode = 'inline',
      variables = { 'device=eth2', 'queue_maxlen=8192', 'fanout_type=hash', 'fail_open', } }
  }
}

Snort processes the snort table as its command line, and does so before any other table (src/main/finalize.lua:110-117). --daq nfq therefore becomes a bare module config on sc->daq_config (src/main/snort_module.cc:925 in 3.10.0.0, :889 on master). When the daq table is closed, SFDAQModule::end() (src/packet_io/sfdaq_module.cc:162, :168 on master) calls SFDAQConfig::overlay() (src/packet_io/sfdaq_config.cc:113-121), which replaces the entire daq.modules list with that bare entry. All variables (and the configured mode) are silently dropped without any warning, so the nfq DAQ runs with its defaults: queue_maxlen=1024 and no fail_open, whatever /etc/config/snort says. main.uc:121 documents the intent (queue_maxlen ... // --daq-var queue_maxlen=int), but the value never reaches libdaq.

Because the stock default is queue_maxlen '1024', the bug is invisible until someone raises the value: the setting then does nothing, and fail_open (unconditional in the template) is never active, so a full queue drops packets instead of bypassing inspection as the template intends.

Observed

  • dmesg: nfnetlink_queue: nf_queue: full at 1024 entries, dropping packets(s) with option queue_maxlen '8192'; queue_dropped in /proc/net/netfilter/nfnetlink_queue climbing (165k in 3 days), i.e. no fail-open either.
  • A/B on the rendered file with 'debug' added to daq.modules[1].variables, Snort started on an unused queue: with line 44 present the DAQ prints nothing (the variable was discarded); with the line removed it prints Set socket receive buffer size to 12435456 (= 8192 x 1518). Under load the kernel then logs full at 8192 entries.
  • copy_mode/copy_range are unaffected (libdaq sets them independently of the variables).

Reproduce

  1. uci set snort.snort.method=nfq; uci set snort.nfq.queue_maxlen=8192; uci commit snort; /etc/init.d/snort restart, then generate enough load to overflow a queue: dmesg says full at 1024.
  2. Quick check without load: append table.insert(daq.modules[1].variables, 'debug') to the rendered file and start Snort - no DAQ debug output. Remove ['--daq'] = 'nfq', and start again: debug output appears and the receive buffer size reflects queue_maxlen.

Proposed fix

Delete the ['--daq'] = '{{ snort.method }}', line from the snort table in files/snort.uc. daq.modules[1].name already selects the module for all three methods (SFDAQ::init iterates the configured module list and falls back to pcap only when it is empty; snort -T passes for pcap, afpacket and nfq, and nfq starts and binds its queues). Nothing else in snort-mgr, main.uc or nftables.uc depends on snort['--daq']. Keeping --daq and dropping daq.modules instead is not an option, because the variables would have no home.

Notes

  • After the fix fail_open becomes active as intended: a full queue then passes packets uninspected and increments no counter (__nfqnl_enqueue_packet with NFQA_CFG_F_FAIL_OPEN), so the drop counters stop being a load indicator. Worth a comment in snort.config, or a UCI option to make it optional.
  • Minor: fanout_type is an afpacket variable. libdaq stores variables without validation and the nfq module only matches debug, fail_open and queue_maxlen, so it is ignored rather than rejected. Harmless, but misleading in the nfq variable list.

I can open a PR for the template change.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with files/snort.uc, especially the snort and daq tables around the cited lines, then trace configuration handling through src/main/finalize.lua and SFDAQConfig::overlay(). Run snort -T for pcap, afpacket, and nfq and verify the rendered nfq configuration preserves queue_maxlen and fail_open in daq.modules.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, lua
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.