Bug #8440
opencapture-bypass: flow statistics of bypassed flows lost during shutdown
Description
Problem:¶
Suricata fails to record statistics for capture-bypassed flows (e.g., eBPF) if the engine shuts down before a flow timeout occurs.
This happens because the BypassUpdate callback, which gathers stats for capture-bypassed flows, is triggered only during timeout checks.
Consequently, any capture-bypassed flow statistics accumulated between the last timeout check and the Suricata shutdown are lost.
Proposed fix:¶
Force Suricata to perform a timeout check during the shutdown stage. This check iterates through all flows in the hash table and calls BypassUpdate on every capture-bypassed flow to ensure final statistics are gathered.
Reproducible test:¶
I used Suricata in af-packet mode with ebpf bypass. I sent a single encrypted TCP flow of 174 packets to Suricata's interface via tcpreplay and observed the bypassed statistics in three different test cases, adjusting the bypassed flow timeout for each. The flow is attached as a pcap. I tested with both a short timeout (5 seconds) and a long one (100 seconds). To verify that statistics gathering is handled properly, I shut down Suricata before the long timeout could occur.
The Suricata config file used for this test is attached.
To adjust the timeout for bypassed flows, I modified the following setting in suricata.yaml:
flow-timeout.tcp.bypassed: # 5 seconds short, 100 seconds long
To bypass all encrypted flows, I used the following setting in suricata.yaml:
app-layer.protocols.tls.encryption-handling: bypass
The testing process is as follows¶
Start Suricata with:
sudo src/suricata -S /dev/null -c suricata-bypass.yaml -l /tmp/ -vvvv --af-packet
Send traffic:
sudo tcpreplay -i ens1f0np0 https_non443.pcap
Extract results:
cat /tmp/stats.log | grep flow_bypassed
Results from different test runs:¶
branch: main, bypassed timeout: 5s flow_bypassed.local_capture_pkts | Total | 5 flow_bypassed.local_capture_bytes | Total | 4682 flow_bypassed.closed | Total | 1 flow_bypassed.pkts | Total | 159 flow_bypassed.bytes | Total | 162736 branch: main, bypassed timeout: 100s flow_bypassed.local_capture_pkts | Total | 5 flow_bypassed.local_capture_bytes | Total | 4682 branch: proposed fix, bypassed timeout: 100s flow_bypassed.local_capture_pkts | Total | 5 flow_bypassed.local_capture_bytes | Total | 4682 flow_bypassed.pkts | Total | 159 flow_bypassed.bytes | Total | 162736
Observation¶
The results show that when Suricata shuts down before any timeout check can occur (second test case), no statistics are gathered for the bypassed flow (the flow_bypassed.pkts and flow_bypassed.bytes fields are missing).
In the version with the proposed fix, the flow is not closed yet, but the statistics are gathered correctly.
Files