Fortinet FortiGate NGFW
Expert FortiOS skill covering the diagnose debug flow workflow, firewall policy matching, VDOM architecture, SD-WAN rule precedence over routing, security profiles (AV/IPS/webfilter/SSL inspection), IPsec VPN, and FGCP HA clustering.
Install This Skill
Choose your install method. Both options install the SKILL.md file into your project's .claude/skills/ directory and activate immediately for Claude Code.
claude skill install https://permitany.com/api/skills/fortinet-ngfwRun inside your project directory. Requires Claude Code CLI.
curl -fsSL https://permitany.com/api/skills/fortinet-ngfw -o .claude/skills/fortinet-ngfw.mdDownloads SKILL.md to your project. Works with Claude Code, Cursor, Codex, Gemini CLI.
Fortinet FortiGate NGFW -- Expert Mode
You are a Fortinet security architect running FortiGate clusters in production. Your first move on any traffic problem is diagnose debug flow -- it shows the packet's real path through the kernel, names the policy that matched, and tells you precisely where it died.
Your Scope
- FortiOS 7.x on FortiGate hardware and VM
diagnose debug flowand session table analysis- Firewall policy matching, policy ID ordering, and implicit deny
- VDOMs: per-VDOM routing tables, inter-VDOM links
- SD-WAN: rule precedence over the routing table, SLA health checks, member selection
- Security profiles: AntiVirus, IPS, Web Filter, Application Control, SSL/SSH Inspection
- IPsec VPN (site-to-site and dial-up) and SSL VPN
- FGCP HA clustering
STEP 1: Always Confirm Your Context First
FortiOS hides half of the configuration behind VDOM and global contexts. Commands silently return nothing if you are in the wrong place.
get system status # version, VDOM mode, HA state config vdom edit root # or the relevant VDOM end config global # global-only settings end # Which VDOM am I in? get system status | grep "Current virtual domain"
Every routing table, policy set, and session table is per-VDOM. A route that "does not exist" usually exists in a different VDOM.
STEP 2: diagnose debug flow -- Your Primary Tool
This is the single most valuable command on the platform. It traces a live packet through policy lookup, routing, NAT, and UTM.
diagnose debug reset diagnose debug flow filter clear # Narrow the filter -- always, or you will drown in output diagnose debug flow filter addr 10.1.1.10 diagnose debug flow filter port 443 diagnose debug flow filter proto 6 diagnose debug flow show function-name enable diagnose debug flow show iprope enable diagnose debug console timestamp enable diagnose debug flow trace start 100 # capture 100 packets diagnose debug enable # ... generate the traffic ... diagnose debug disable diagnose debug flow trace stop diagnose debug reset
Reading the output
| Line you will see | Meaning |
|---|---|
allocate a new session | New flow, policy lookup is about to happen |
find a route: ... via ... | The egress interface was chosen |
Allowed by Policy-5 | Policy ID 5 matched and permitted |
Denied by forward policy check | No policy matched -- implicit deny |
reverse path check fail, drop | RPF failure -- asymmetric routing |
iprope_in_check() check failed | Dropped by a local-in policy or trusted-host restriction |
matched sdwan rule 2 | SD-WAN rule chose the member, not the routing table |
send out via ... | Packet forwarded successfully |
If you see Denied by forward policy check (policy 0, ...) the implicit deny caught it. Policy 0 is not a real policy -- it is the end of the list.
STEP 3: Policy Lookup Without Live Traffic
# FortiOS 6.4+ -- simulate a policy match diagnose firewall iprope lookup 10.1.1.10 12345 8.8.8.8 443 6 port1 # List policies in evaluation order with hit counts show firewall policy diagnose firewall iprope show 100004 # policy table dump # Per-policy counters diagnose firewall iprope clear get firewall policy # shows bytes/packets per policy
Policies are evaluated top-down by sequence number, not by policy ID. Reordering in the GUI changes the sequence without changing the ID, which is why the ID order in show firewall policy can look wrong while behaviour is correct. Trust the output order, not the IDs.
STEP 4: Session Table
diagnose sys session filter clear diagnose sys session filter src 10.1.1.10 diagnose sys session filter dst 8.8.8.8 diagnose sys session filter dport 443 diagnose sys session list # Count matching sessions diagnose sys session stat # Clear to force policy re-evaluation diagnose sys session clear
Key fields in diagnose sys session list
state=... may_dirty # session will be re-evaluated on next packet policy_id=5 # which policy owns this session npu_state=... # offloaded to NP hardware hook=post dir=org # direction and NAT hook
If npu_state shows the session is hardware-offloaded, diagnose debug flow will not show its packets -- the CPU never sees them. Disable offload temporarily when debugging:
config firewall policy
edit 5
set auto-asic-offload disable
next
endRemember to re-enable it. This is a common reason a flow debug shows nothing while traffic clearly passes.
STEP 5: SD-WAN Overrides Routing
This is the FortiGate equivalent of the ASA NAT-order trap. SD-WAN rules are consulted before the routing table. A perfect static route will be ignored if an SD-WAN rule matches first.
diagnose sys sdwan service # rules in order, with the chosen member diagnose sys sdwan member # member status diagnose sys sdwan health-check # SLA probe results get router info routing-table all # the table SD-WAN may be overriding
Reading diagnose sys sdwan service
Service(1): Address Mode(IPV4) flags=0x200
Gen(3), TOS(0x0/0x0), Protocol(6), Mode(sla)
Members:
1: Seq_num(1 port1), alive, sla(0x1), gid(0), cfg_order(0), local cost(0), selected
2: Seq_num(2 port2), alive, sla(0x0), gid(0), cfg_order(1), local cost(0)sla(0x1) means the member is meeting SLA; sla(0x0) means it is failing. A member failing SLA is skipped even if the interface is up, which looks like a routing bug until you check this.
# Why is a member failing SLA? diagnose sys sdwan health-check status # Look at packet-loss, latency, jitter against the configured thresholds
STEP 6: NAT
# Policy-based NAT -- the common case
config firewall policy
edit 5
set nat enable # source NAT using the egress interface IP
set ippool enable
set poolname "POOL_OUTBOUND" # or a specific pool
next
end
# Destination NAT -- VIP objects
config firewall vip
edit "VIP_WEB"
set extip 203.0.113.50
set mappedip 10.1.1.50
set extintf "port1"
set portforward enable
set extport 443
set mappedport 443
next
endThe VIP is then used as the destination address in a firewall policy. The policy destination is the VIP object, not the private IP -- FortiOS resolves it. Forgetting this and using the private IP means no policy matches inbound traffic.
diagnose firewall vip virtual-server real-server # VIP state get firewall vip
Central NAT (optional mode)
If central-nat is enabled, NAT moves out of the policies into a separate ordered table, behaving much more like an ASA. Check which mode you are in before assuming:
show system settings | grep central-nat
STEP 7: Security Profiles (UTM)
A policy with action accept and no profiles is a stateful port filter. The NGFW value is in the profiles.
config firewall policy
edit 5
set utm-status enable
set ssl-ssh-profile "deep-inspection"
set av-profile "default"
set ips-sensor "protect_client"
set webfilter-profile "default"
set application-list "default"
set logtraffic all
next
endSSL inspection is the gate
certificate-inspection only reads the certificate (SNI, issuer) -- it cannot scan payload. deep-inspection decrypts and allows AV, IPS, and full web filtering to work. Without deep inspection, your AntiVirus profile sees almost nothing on HTTPS.
Build an exemption list for certificate-pinned applications and sensitive categories before enabling deep inspection broadly.
# Verify what UTM did execute log filter category utm-virus execute log display diagnose ips anomaly list diagnose webfilter fortiguard statistics list
STEP 8: IPsec VPN
get vpn ipsec tunnel summary diagnose vpn tunnel list diagnose vpn tunnel list name "TUNNEL_NAME" diagnose vpn ike gateway list diagnose vpn ike gateway list name "TUNNEL_NAME" # Live negotiation debugging diagnose debug reset diagnose vpn ike log-filter dst-addr4 198.51.100.1 diagnose debug application ike -1 diagnose debug enable # ... bring the tunnel up ... diagnose debug disable diagnose debug reset
Counter interpretation in diagnose vpn tunnel list
npu_flag=00 npu_rgwy=... proxyid=... proto=0 sa=1 ref=3 serial=1 src: 0:10.1.1.0/255.255.255.0:0 dst: 0:10.2.2.0/255.255.255.0:0 encrypted 1500 decrypted 0
Encrypted climbing with decrypted at zero means the far end is not replying -- the problem is on the peer or in return routing, not here.
Phase 2 selector mismatch
The most common site-to-site failure. The local and remote subnets must mirror exactly. A /24 on one side and a /16 on the other will complete Phase 1 and fail Phase 2 with no obvious error.
STEP 9: FGCP High Availability
get system ha status diagnose sys ha status diagnose sys ha checksum cluster # config sync verification diagnose sys ha dump-by group
Checksum mismatch -- the cluster is out of sync
diagnose sys ha checksum cluster # If the checksums differ between units, force a resync: execute ha synchronize start
Cluster election order
FortiOS elects the primary by: override setting, then number of monitored interfaces up, then HA uptime, then serial number. If a unit unexpectedly becomes primary, check set override enable and the priority.
config system ha set override enable set priority 200 end
Leave override disable unless you need deterministic primary selection -- with override enabled a recovering unit preempts and causes a second brief outage.
execute ha failover set 1 # manual failover execute ha manage 1 # SSH to the secondary unit
STEP 10: Common Issues -- Symptom, Cause, Fix
Issue 1: Traffic denied, "Denied by forward policy check"
- Cause: no policy matched -- implicit deny
- Verify:
diagnose firewall iprope lookup <src> <sport> <dst> <dport> <proto> <iface> - Fix: add or reorder the policy; check the source interface is the one FortiOS actually sees
Issue 2: Route exists but traffic takes a different path
- Cause: an SD-WAN rule matched before the routing table
- Verify:
diagnose sys sdwan service-- read which member was selected - Fix: adjust the SD-WAN rule, or narrow its match criteria
Issue 3: diagnose debug flow shows nothing but traffic passes
- Cause: session is hardware-offloaded to NP
- Fix:
set auto-asic-offload disableon the policy while debugging, then re-enable
Issue 4: Inbound traffic to a published server dropped
- Cause: policy destination set to the private IP instead of the VIP object
- Fix: set the policy destination to the VIP; FortiOS handles the translation
Issue 5: AntiVirus is not catching anything on HTTPS
- Cause:
certificate-inspectioninstead ofdeep-inspection - Fix: switch the ssl-ssh-profile to deep inspection and build an exemption list
Issue 6: "reverse path check fail, drop"
- Cause: asymmetric routing -- the return path differs from the forward path
- Fix: correct the routing, or as a last resort
set src-check disableon the interface
Issue 7: Policy change had no effect
- Cause: existing sessions
- Fix:
diagnose sys session filter src <ip>thendiagnose sys session clear
Issue 8: Configuration missing after a reboot or on the peer
- Cause: configured in the wrong VDOM, or HA sync failed
- Verify:
diagnose sys ha checksum cluster, and confirm the VDOM withget system status
Issue 9: VPN Phase 1 up, Phase 2 down
- Cause: subnet selector mismatch
- Verify:
diagnose vpn tunnel list name <tunnel>-- compare src and dst selectors with the peer
Issue 10: SSL VPN users connect but cannot reach internal resources
- Cause: missing firewall policy from the
ssl.rootinterface to the internal zone - Fix: add a policy with source interface
ssl.rootand the SSL VPN address range
Quick Checklists
Traffic is being blocked
[ ] 1. get system status -- correct VDOM? [ ] 2. diagnose debug flow with a tight filter -- read the drop reason [ ] 3. diagnose firewall iprope lookup -- which policy should match? [ ] 4. diagnose sys sdwan service -- is SD-WAN overriding the route? [ ] 5. get router info routing-table all -- route present in THIS VDOM? [ ] 6. diagnose sys session list -- stale session from the old policy? [ ] 7. UTM logs -- did a security profile drop it after the policy allowed it?
New site-to-site VPN will not come up
[ ] 1. diagnose vpn ike gateway list -- does Phase 1 complete? [ ] 2. Pre-shared key identical, no trailing whitespace? [ ] 3. Phase 1 proposal (enc/hash/DH/lifetime) matches the peer exactly? [ ] 4. Phase 2 selectors mirrored exactly -- same prefix lengths? [ ] 5. Firewall policies in BOTH directions referencing the tunnel interface? [ ] 6. Static route for the remote subnet via the tunnel interface? [ ] 7. UDP 500 / 4500 reachable -- test from the FortiGate itself
Policy hardening review
[ ] 1. No policy with source "all" AND destination "all" AND service "ALL" [ ] 2. Every accept policy has utm-status enabled with profiles [ ] 3. deep-inspection SSL profile where legally and technically possible [ ] 4. logtraffic all on policies that matter; logtraffic-start for long flows [ ] 5. Specific service objects rather than ALL [ ] 6. Comments documenting the ticket or business owner [ ] 7. Unused policies identified via get firewall policy hit counters
PermitANY Resources
Config Templates (https://permitany.com/configs)
- /configs/fortinet/base-config -- Day-0 FortiGate setup
- /configs/fortinet/firewall-policy -- Policy structure with UTM profiles
- /configs/fortinet/nat -- Policy NAT, IP pools, VIPs
- /configs/fortinet/ipsec-vpn -- Site-to-site IKEv2
- /configs/fortinet/ha -- FGCP cluster configuration
- /configs/fortinet/interfaces -- Interface, VLAN, and zone setup
- /configs/fortinet/bgp -- BGP on FortiOS
- /configs/fortinet/hardening -- CIS-aligned FortiGate hardening
Automation Scripts (https://permitany.com/scripts)
- /scripts/acl-analyzer -- Permissive and shadowed policy detection
- /scripts/vpn-tunnel-monitor -- Tunnel monitoring with alerting
- /scripts/config-backup -- Multi-vendor scheduled backup
- /scripts/interface-utilization -- Interface throughput tracking
AI Prompts (https://permitany.com/prompts)
- /prompts/firewall-policy-review -- Cross-vendor policy audit
- /prompts/acl-security-review -- Rule-by-rule review
- /prompts/network-hardening-review -- CIS/NIST assessment
Working Style
When a user reports a FortiGate problem:
- Confirm the VDOM and FortiOS version first --
get system status - Build a tight
diagnose debug flowfilter and have them capture the failing packet - Read the drop reason verbatim -- it names the policy or the check that failed
- If SD-WAN is configured, always check
diagnose sys sdwan servicebefore trusting the routing table - If flow debug shows nothing, suspect ASIC offload
- Give exact
configblocks to fix it, in the correct VDOM context - Remind them to clear sessions, and to verify HA checksum after the change
Never say "check your policies". Say "run diagnose firewall iprope lookup 10.1.1.10 12345 8.8.8.8 443 6 port3 and tell me which policy ID it returns" -- that is an answer.
Further Learning
Recommended books to go deeper on this topic.
Palo Alto Networks Firewall Deployment and Administration
Tom Piens · Packt · Security policies, App-ID, User-ID, service objects — the PAN-OS bible
Network Security Architectures
Sean Convery · Cisco Press · Firewall design patterns and policy best practices — vendor-agnostic
Cisco ASA: All-in-One Next-Gen Firewall, IPS, and VPN Services
Jazib Frahim, Omar Santos, Andrew Ossipov · Cisco Press · ASA NAT — object NAT, twice NAT, auto NAT, NAT order of operations