NFQUEUE routed deployment
Queue only the intended routed lab conversation and keep firewall policy separate from inspection.
Examples target Suricata 8.0.1 on a prepared Linux lab host. Constructed outputs are illustrative, not live sensor results. Commands are lesson examples; no sensor or enforcement is started by this page.
Prepare a routed test boundary
A Linux lab gateway has lan0 at 10.10.10.1/24 and wan0 at 192.0.2.1/24. Client 10.10.10.20 uses that gateway; Server 192.0.2.80 returns through 192.0.2.1. The client sends cleartext HTTP to port 8080. Management stays on a separate path. Routing, forwarding and the existing firewall must already permit the benign baseline; this example adds inspection, not a complete perimeter firewall.
| Direction | Queued selector |
|---|---|
| Request | lan0 → wan0, client → server, destination TCP 8080 |
| Response | wan0 → lan0, server → client, source TCP 8080 |
Verify the queue consumer
suricata --build-info
Suricata version 8.0.1
NFQueue support: yesThe selected build must include NFQUEUE support. The running instance will consume queue 0; a differently numbered consumer will not inspect these queued packets.
suricata -T -c /etc/suricata/suricata.yaml --init-errors-fatal
suricata -c /etc/suricata/suricata.yaml -q 0Validate rules first and avoid an unrelated service instance. Do not enable queueing on a production gateway while experimenting. The command is an example for the prepared lab, not a service started by this lesson.
Add a dedicated scoped table
table inet suricata_lab {
chain inspect {
type filter hook forward priority 10; policy accept;
iifname "lan0" oifname "wan0" ip saddr 10.10.10.20 ip daddr 192.0.2.80 tcp dport 8080 counter queue num 0
iifname "wan0" oifname "lan0" ip saddr 192.0.2.80 ip daddr 10.10.10.20 tcp sport 8080 counter queue num 0
}
}Save this complete dedicated table as suricata-lab.nft. It queues only the stated IPv4 TCP conversation in both directions. Validate with nft -c -f ./suricata-lab.nft before loading with nft -f ./suricata-lab.nft. Priority 10 places this chain after a conventional priority-0 filter; inspect the actual ruleset because other hooks or offload paths can alter coverage. An earlier drop cannot be undone by this chain, and an accepted Suricata verdict does not bypass later firewall policy.
Check that the hook is used
nft list table inet suricata_lab
table inet suricata_lab {
chain inspect {
type filter hook forward priority 10; policy accept;
... counter packets 6 bytes 700 queue num 0
... counter packets 5 bytes 620 queue num 0
}
}The ellipses are selected-rule abbreviations, not configuration to paste. Counter increments show the intended path reached queueing, but endpoint observations and EVE verdicts establish the final outcome. IPv6 and other services are deliberately outside this lab selector.
Remove only the lab policy
nft delete table inet suricata_labThis removes the dedicated inspection table without flushing unrelated firewall rules. Confirm the benign baseline after removal, then stop the lab consumer. Without a bypass option, packets sent to an unconsumed NFQUEUE are normally dropped; adding queue bypass changes that behavior and removes inspection while no consumer is present. It does not solve every overload or process-hang case.
Further reading
Key Takeaways
- NFQUEUE inserts userspace inspection at selected Netfilter hooks.
- The gateway needs working bidirectional routing before inspection.
- Queue numbers and selectors must match the consumer.
- A queue verdict does not replace the rest of the firewall policy.
- Use a dedicated table for narrow scope and precise rollback.