I nearly told a colleague that packets weren’t reaching our FortiGate. I had what looked like good evidence: the diagnose debug flow filters were configured correctly, the test connection was being generated, and the CLI console showed absolutely nothing. No session creation, no route lookup, no policy match, no deny message.
The packets weren’t missing. The diagnostic output was.
The FortiGate web interface’s built-in CLI console is handy for quick commands and configuration changes, but I no longer trust it for real-time packet captures or debug output. If you’ve run a sniffer or debug flow from the web interface and seen nothing, check your diagnostic method before deciding the traffic never reached the firewall.
The situation
I was troubleshooting a connection that had stopped working through a site-to-site IPsec tunnel. One port was failing while other connections between the same two hosts worked fine. Rather than keep interpreting the configuration, I wanted to see exactly what the FortiGate was doing with the traffic.
I opened the FortiGate GUI, clicked the CLI console button and configured a debug flow:
diagnose debug reset
diagnose debug flow filter clear
diagnose debug flow filter addr 192.0.2.50
diagnose debug flow filter port 22
diagnose debug flow show function-name enable
diagnose debug flow trace start 50
diagnose debug enableI triggered the connection from the client, and nothing appeared.
That looked significant. If a packet reaches the FortiGate and is rejected by policy, the flow trace normally shows the packet being processed and the reason it was dropped. Complete silence looks like evidence that the traffic never arrived, and I was heading towards that conclusion.
The control test that changed everything
Before escalating, I ran the same test against a port I knew was working.
Same source. Same destination. Same FortiGate. Same tunnel. The only thing I changed was the port filter.
Again, nothing appeared.
That was the important result. A known-good connection should have produced output. If both the failing and the working connection produce nothing, the silence can’t be evidence that either packet was missing. The problem was the diagnostic method.
The fix: use a real SSH session
I closed the web console, opened PuTTY, connected to the FortiGate over SSH and ran the same commands.
This time the working connection traced properly. I could see the session being created, the route lookup, the policy decision and the traffic being handed to the tunnel, along with the return traffic.
The failing port still produced no flow output, but now that silence meant something. With a method I knew could see traffic, the missing trace became real evidence rather than a blank screen. The fault eventually turned out to be outside the firewall entirely.
The web console hadn’t proved the packets were missing. It had only proved that the web console wasn’t showing me the output.
Why I don’t use the web CLI for captures any more
I’m not the only one to hit this. Fortinet’s own knowledge base warns against using the built-in GUI CLI for high-volume packet capture, because it can’t handle large amounts of output, and recommends SSH with PuTTY or a similar client instead (Fortinet KB: Packet capture limitations in GUI and extended packet capture using CLI).
In my experience, it’s worse than a volume problem. With debug flow in particular, the web console showed no output at all, even for a single low-volume test. I saw this on FortiOS 7.6, and your mileage may vary on other builds. Either way, when the output itself is your evidence, the web console is the wrong place to collect it.
SSH has another advantage: PuTTY can log the whole session to a file (Session > Logging > Printable output). When you’re investigating an intermittent problem, you don’t want the evidence scrolling off the screen.
Sniffer and debug flow answer different questions
These two tools are often used together, but they tell you different things.
The sniffer tells you whether packets are there, and where.
diagnose sniffer packet any 'host 192.0.2.50 and port 22' 4 20 aHere any looks across all interfaces, the filter narrows the capture to the traffic you care about, verbosity 4 shows interface names, 20 stops after 20 packets, and a adds absolute timestamps. The interface names are what make this useful for tunnels and routing problems, since you can see where each packet enters and leaves.
Debug flow tells you what the FortiGate decided to do with them. That includes session handling, route lookup, policy matching, NAT, IPsec processing and drops.
My rule of thumb: the sniffer proves the packet is there, and debug flow explains the decision. Using both is far more useful than relying on either alone.
The other reason you might see nothing: NPU offload
Even over SSH, there’s a second trap. On FortiGates with NP6 or NP7 processors, established sessions can be offloaded to hardware, and the CPU-based diagnostic tools stop seeing those packets. Fortinet’s documentation states that flow monitoring doesn’t work for traffic offloaded to NP6 or NP7 processors (Fortinet: Debugging the packet flow).
The sniffer is affected too. A classic symptom is seeing the first few packets and then nothing, as if the capture has stopped (Fortinet KB: GUI packet capture is not working).
Before changing anything, check whether the session is actually offloaded:
diagnose sys session filter clear
diagnose sys session filter dst 192.0.2.50
diagnose sys session filter dport 22
diagnose sys session listIn the output, look at the npu_state and offload fields to see whether the session is being accelerated. If it is, and you need to see every packet, temporarily disable offload on that one policy:
config firewall policy
edit <policy-id>
set auto-asic-offload disable
next
endDon’t disable hardware acceleration globally just because a capture is inconvenient. Disabling offload moves traffic onto the CPU, so keep the change to the test policy and put it back as soon as you’re done:
config firewall policy
edit <policy-id>
unset auto-asic-offload
next
endExisting sessions can hide your test
Debug flow shows session setup. If the session you’re testing already exists, such as a long-lived TCP connection or an SSH session left open, you may not see the flow you’re expecting.
Clear only the matching sessions before retesting, using the same filter as above:
diagnose sys session filter clear
diagnose sys session filter dst 192.0.2.50
diagnose sys session filter dport 22
diagnose sys session clearBe careful here. diagnose sys session clear with no filter set clears every session on the firewall. Always check your filter before you run it, especially on a production box.
My FortiGate capture workflow
This is the process I use now whenever I need to prove what a FortiGate is doing.
- Connect over SSH, not the web console, with PuTTY session logging turned on.
- Start with a narrow sniffer. If you know the source, destination and port, filter on them. Use a packet count so the capture stops and flushes on its own.
- Generate the test traffic yourself where possible, so you know exactly when the connection attempt happened. Don’t assume an application tried to connect just because you clicked something.
- Move to debug flow once you know the packet is arriving but the connection still fails. When you’re finished, clean up with
diagnose debug disablefollowed bydiagnose debug reset. - Run a control test. This is the step that saved me. For every important test, create a known-good comparison that changes as little as possible, for example the same source and destination on port 443 instead of port 22. If the control produces a trace and the failing test doesn’t, the difference is meaningful. If neither produces output, stop troubleshooting the network and troubleshoot your method.
- Check offload if the sniffer shows a few packets and then stops.
- Confirm the HA member. If the FortiGate is in an HA cluster, make sure you’re connected to the unit actually processing the traffic. A perfect debug filter on the wrong cluster member looks exactly like a missing packet.
- Restore everything you changed, including offload settings and filters. Troubleshooting configuration shouldn’t become permanent configuration.
A note on IPsec tunnels
Tunnel problems have several stages, and a single blank capture can’t tell you which one failed. You may need to establish:
- Did the original packet arrive at the FortiGate?
- Was a session created or matched?
- Did the route and policy match?
- Was the packet sent to the IPsec interface?
- Was it encrypted and sent to the peer?
- Did return traffic come back?
- Was it decrypted and passed back through policy?
It helps to know which interface you’re sniffing. A capture on the tunnel interface shows the traffic before encryption and after decryption. A capture on the WAN interface shows ESP packets to and from the peer’s public IP. Capturing both, and comparing timestamps, tells you whether a packet made it into the tunnel.
Work from the endpoints inward and collect evidence at each stage, rather than jumping straight to “the VPN is broken.”
A blank screen isn’t evidence
This is the real lesson. When a diagnostic command produces no output, there are many possible explanations:
- The packet never reached the FortiGate.
- The filter didn’t match the traffic.
- The test never actually generated the traffic.
- An existing session meant no new flow was created.
- The traffic was offloaded to hardware.
- You were connected to the wrong HA member.
- The web CLI console didn’t display the output.
Only the first one means the packet never arrived. You need another piece of evidence before you can make that conclusion, and a control test is the fastest way to get it.
Without a control, you’re asking “why didn’t I see this packet?” With one, you’re asking a much better question: “can my method see a packet I already know is there?” If it can’t, you haven’t tested the network yet. You’ve tested your tools.
Checklist: FortiGate sniffer or debug flow showing nothing
- Are you using the web CLI console? Switch to SSH.
- Is your SSH client logging the session?
- Does a known-working connection produce output with the same filter?
- Are the source, destination, protocol and port in your filter correct?
- Did the test actually generate a new connection during the capture?
- Is there an existing session that needs clearing, with a filter set first?
- Are you connected to the HA member processing the traffic?
- Is the session offloaded to an NP6 or NP7 processor?
- Are you sniffing the right interface: tunnel or WAN?
- Have you disabled debugging and restored any offload changes?
Before trusting a negative result, prove your diagnostic method can see a positive one. I nearly escalated a fault to the wrong team because of a blank window, and a thirty-second control test was all it took to stop me.

From my early days on the helpdesk through roles as a service desk manager, systems administrator, and network engineer, I’ve spent more than 25 years in the IT world. As I transition into cyber security, my goal is to make tech a little less confusing by sharing what I’ve learned and helping others wherever I can.

