01Before you touch anything

Three habits save more outages than any command: keep a current config backup, make changes under change control, and document what you altered and when. Ninety percent of "the firewall broke" tickets resolve to "a change was made" — so the fastest diagnostic is often a diff against a known-good config.

execute backup config flash before-change      # snapshot on-box before you start
show | grep -f                                  # full running config to compare off-box later

02The built-in toolbox (GUI + CLI)

You rarely need external tools. Reach for these first:

Log Viewer (GUI)Forward traffic, events, security, VPN, UTM — filter on Deny and on a source IP.
Policy Lookup (GUI)Enter source/dest/port/proto → it tells you the exact policy that would match.
FortiView (GUI)Top talkers, destinations, and threats — spot the anomaly visually.
Routing Monitor (GUI)The active routing table (Network → monitor).
Packet Capture (GUI/CLI)Grab traffic on an interface for offline analysis.

The two CLI families are get (show current state) and diagnose (dig deeper). Your orientation set:

get system status                 # model, firmware, serial, HA state
get system performance status     # CPU, memory, sessions, setup rate, uptime
get router info routing-table all # the routing table (CLI form of Routing Monitor)
diagnose sys session stat         # session table totals & setup rate
Version: FortiGate-100F v7.4.5,build...
CPU states: 3% user 2% system 0% nice 95% idle
Memory: 61% used
Sessions: 18423 (setup rate 214/s)

03The two commands that solve most cases

When you don't know why traffic is failing, these answer it. Debug flow makes the FortiGate narrate its decision for a packet — route lookup, policy match, NAT, UTM verdict. Sniffer proves whether the packet arrived and whether a reply came back.

Debug flow — "what did you decide, and why?"

diagnose debug reset
diagnose debug flow filter saddr 10.10.10.20      # the client
diagnose debug flow filter daddr 203.0.113.50     # the destination
diagnose debug flow filter dport 443
diagnose debug flow show function-name enable
diagnose debug flow show iprope enable            # show the policy-lookup decision
diagnose debug console timestamp enable
diagnose debug flow trace start 10                # follow the next 10 matching packets
diagnose debug enable
# … generate the traffic now …
diagnose debug disable
diagnose debug flow trace stop
diagnose debug reset                              # always reset when done
msg="vd-root received a packet(proto=6, 10.10.10.20:51244->203.0.113.50:443)"
msg="allocate a new session"
msg="find a route: gw-203.0.113.1 via wan1"
msg="Denied by forward policy check (policy 0)"   <- no matching policy = implicit deny

That last line is the whole diagnosis: policy 0 is the implicit deny — the packet reached the box and was routed, but no policy accepted it. Now you know it's a policy problem, not a routing or L2 one.

Sniffer — "did the packet even arrive, and did anyone answer?"

diagnose sniffer packet any 'host 10.10.10.20 and port 443' 4 0 a
# any = all interfaces · verbosity 4 = headers + iface names · count 0 = until Ctrl-C · a = absolute time
2026-07-31 09:14:02.114 port2 in  10.10.10.20.51244 -> 203.0.113.50.443: syn
2026-07-31 09:14:02.114 wan1  out 10.10.10.20.51244 -> 203.0.113.50.443: syn
# …no syn-ack coming back on wan1 → the problem is upstream/return-path, not inside the client LAN

diagnosis = sniffer (did it arrive / reply?) + debug flow (what did the FortiGate decide?)

04Connectivity problems

Work bottom-up, and let each command rule out a layer:

  • Interface & link. Is the port up with the right IP?
  • Route. Does a default (or specific) route point out the correct egress?
  • Policy & NAT. Does a policy accept the flow, and is NAT on for internet-bound traffic?
  • Name resolution. Can the box (and the client) resolve DNS at all?
get system interface physical                     # link state + speed/duplex per port
diagnose hardware deviceinfo nic wan1             # errors, drops, carrier on the physical NIC
get router info routing-table all                 # is there a route out, via the right interface?
execute ping-options source 10.10.10.1            # test from the LAN-facing IP…
execute ping 203.0.113.50                         # …to prove egress + return path
wan1: link up, speed 1000Mbps, duplex full
S*  0.0.0.0/0 [10/0] via 203.0.113.1, wan1
--- 203.0.113.50 ping statistics ---  5 packets transmitted, 5 received, 0% loss

Caviar: if the ping from the FortiGate works but the client's doesn't, the box is fine — the issue is a policy/NAT or a return route for the client subnet. Confirm with Policy Lookup, then a debug flow filtered on the client IP (§03).

05Policy misconfigurations

Policies are evaluated top to bottom, first match wins. The usual failures: a broader policy above shadows yours, the interface pair is wrong, or a UTM profile (not the policy) is doing the blocking. Start with Policy Lookup, then trace:

diagnose debug flow filter saddr 10.10.10.20 daddr 203.0.113.50 dport 443
diagnose debug flow show iprope enable
diagnose debug flow trace start 5
diagnose debug enable
# …generate traffic, then disable/reset as in §03…
msg="Match policy id 7"                            <- which policy actually caught it
msg="utm: proxy-based inspection ... blocked (webfilter)"   <- policy allowed, UTM denied

Caviar: "allowed by policy but still blocked" almost always means a security profile — web filter, IPS, application control, or SSL inspection. The debug flow names the culprit; then fix the profile, not the policy. Cross-check the policy ID column in the forward-traffic log to confirm which rule matched in production.

06VPN tunnels (IPsec & SSL-VPN)

IPsec site-to-site. Diagnose it in phases — Phase 1 (IKE) first, then Phase 2 (IPsec), then policy/route.

get vpn ipsec tunnel summary                      # up/down + rx/tx per tunnel at a glance
diagnose vpn ike gateway list                     # Phase 1 (IKE) state per peer
diagnose vpn tunnel list                          # Phase 2 SAs, selectors, encryption
# live IKE negotiation:
diagnose debug application ike -1
diagnose debug enable                             # watch it try to come up, then: diagnose debug reset
gateway 'HQ-to-Branch'  ike v2  status: established  <- P1 up
# common P1/P2 failures: proposal mismatch, PSK mismatch, wrong peer/gateway IP,
# or Phase 2 selector (subnet) mismatch between the two ends

If both phases are up but traffic still fails, it's the boring stuff: a firewall policy permitting tunnel traffic in both directions, and a route pointing the remote subnet at the IPsec interface.

SSL-VPN. Check reachability, auth, and the internal path in that order:

get vpn ssl monitor                               # who is connected, and their assigned IPs
diagnose debug application sslvpn -1
diagnose debug enable                             # watch a login attempt; then reset
SSL-VPN Login Users: user 'jdoe'  tunnel-ip 10.212.134.200  ok
# if login fails: credentials/auth server, or the user isn't in the mapped group
# if login ok but no internal access: missing policy (ssl.root → internal) or no return route to the IP pool

07Performance & conserve mode

High CPU, high memory, or "conserve mode" throttling usually traces to one process, one session storm, or memory pressure.

get system performance status                     # CPU/memory/session snapshot & setup rate
diagnose sys top 2 20                              # top processes by CPU (refresh 2s, 20 lines) — 'q' to quit
diagnose sys session stat                          # session count & setup rate (SYN floods show here)
diagnose hardware sysinfo conserve                 # are we in conserve mode, and the memory thresholds
memory conserve mode: on   total 2048MB  used 1740MB (85%)  green:82% red:88%
# entered conserve at the red threshold → find the memory hog (diagnose sys top) or reduce
# proxy-based inspection / session load; sustained high setup rate hints at a flood or a loop.

Caviar: a single client generating tens of thousands of sessions is a classic culprit — filter the session table by source (diagnose sys session filter src <ip> then diagnose sys session list) to catch a loop or malware before blaming the box.

08DNS & routing quick checks

execute ping FortiGuard.net                        # does the box resolve + reach the internet by name?
diagnose test application dnsproxy 6                # the FortiGate's own DNS cache/servers
get router info routing-table details 203.0.113.50 # exactly which route a destination will use
diagnose ip router ... / diagnose firewall proute list   # policy routes (they win over the routing table)

Caviar: a destination that "should work" but doesn't often has a policy route (PBR) silently steering it out the wrong interface — policy routes are evaluated before the routing table, so always check proute when a route looks correct but traffic goes the wrong way. (See also the FQDN object / DNS round-robin trap.)

09A repeatable method

When you're stuck, run the same loop every time — it turns "the firewall is broken" into a decision tree:

  • Reproduce & scope. One client, one destination, one port. Vague reports waste hours.
  • Did it arrive? Sniffer on the ingress interface. No packet → it's upstream/L2/routing to the box.
  • What was decided? Debug flow. It names the route, the policy, the NAT, the UTM verdict.
  • Fix the named thing. Policy, profile, route, or NAT — whatever the trace pointed at.
  • Confirm & document. Re-test the exact flow, then note the change (§01).

method = reproduce + sniff (arrived?) + debug flow (verdict?) + fix the named layer + verify

10References