FortiGate CLI Reference
FortiOS 7.2 / 7.4 / 7.6 · CLI, Debug, Troubleshooting & Automation
ike, sess, bgp, np7.
Default Device Information
| Item | Default Value | Notes |
|---|---|---|
| Management IP | 192.168.1.99 |
port1 (Software Switch LAN1–LANX) or dedicated MGMT port |
| Admin username | admin |
— |
| Admin password | none (blank) | Set a password immediately after first login |
| HTTPS GUI | https://192.168.1.99 |
— |
Serial Console / PuTTY Settings
| Device | Baud Rate | Data Bits | Parity | Stop Bits | Flow Control |
|---|---|---|---|---|---|
| FortiGate (FGT) | 9600 |
8 | N (None) | 1 | Disabled (no RTS/CTS) |
| FortiSwitch (FSW) | 115200 |
8 | N (None) | 1 | Disabled (no RTS/CTS) |
- Baud rate — transmission speed in bits per second
- Data bits: 8 — each packet contains 8 bits of data
- Parity: N — no parity bit used for error checking
- Stop bits: 1 — one stop bit signals the end of each data packet
- Flow control: Disabled — no RTS/CTS hardware handshaking
CLI Command Trees & Abbreviations
FortiOS accepts shortened command prefixes — type just enough letters to be unambiguous:
| Full Command | Short Form | Purpose | Example |
|---|---|---|---|
get |
ge |
Read running/compiled state | ge sys status |
show |
sh |
Display saved config (NVRAM) | sh sys interface |
diagnose |
diag / di |
Diagnostics, debug, real-time views | di sys top |
execute |
exec / ex |
One-shot actions & maintenance | ex ping 8.8.8.8 |
config |
con / co |
Enter a config context to change settings | co sys interface |
Configuration Verbs
| Verb | Meaning |
|---|---|
set |
Assigns a value to a config parameter. Overwrites any existing value. |
unset |
Reverts a config parameter to its factory default value. |
append |
Adds to a multi-value parameter without overwriting existing entries (e.g., adding a DNS server). |
unselect |
Deselects a specific item from a multi-select list without clearing the whole set. |
CLI Navigation & Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| ? after a command | List available sub-commands or arguments at the current level |
| Tab | Auto-complete the current command or argument |
| Ctrl + A | Jump to the start of the line |
| Ctrl + E | Jump to the end of the line |
| Ctrl + R | Reverse search through command history |
| Ctrl + C | Abort current command or stop debug output |
# Output filtering (pipe to grep) show full-configuration | grep <pattern> get system interface | grep -f port1 ← -f includes surrounding context lines # See GUI wizard steps as CLI commands in real time diagnose debug cli 7 diagnose debug enable
VDOM Context
# List and switch VDOMs
config vdom
edit <vdom-name> ← switch CLI context into VDOM
next
end
# Access global or specific VDOM directly via sudo (7.2+)
sudo global
sudo <vdom-name>
# Check current VDOM context
get system status | grep VDOM
get system status ← firmware version, serial, hostname, HA mode, uptime get system performance status diagnose sys top 3 30 ← refresh every 3s, show 30 processes; sort: P=CPU M=Memory diagnose sys top-mem ← processes sorted by memory consumption
execute tac report ← generates a compressed support report (sent to FortiCloud/TAC)
diagnose sys process list diagnose sys process show <pid> diagnose sys kill <signal> <pid> ← signal 11=SIGSEGV; use with care
diagnose debug crashlog read ← view crash log entries diagnose debug config-error-log read ← view config parse errors after firmware upgrades
execute restore image tftp <filename> <tftp-ip> execute restore image ftp <filename> <ftp-ip>[:<port>] [<user> <pass>]
execute backup config tftp <filename> <tftp-ip> execute backup config ftp <filename> <ftp-ip> [<user> <pass>] execute restore config tftp <filename> <tftp-ip>
execute factoryreset ← wipes entire configuration execute factoryreset2 ← wipes config but retains admin account, interfaces & static routes execute factoryreset-shutdown ← factory reset then power off execute factoryreset keepvmlicense ← wipes config but keeps VM licence (VM platforms)
diagnose hardware sysinfo conserve # Example output: # memory conserve mode: off # total RAM: 2043 MB # memory used: 666 MB 32% of total RAM # memory freeable: 317 MB 15% of total RAM # memory used + freeable threshold extreme: 1940 MB 95% of total RAM ← sessions dropped # memory used threshold red: 1797 MB 88% of total RAM ← conserve mode ON # memory used threshold green: 1675 MB 82% of total RAM ← conserve mode OFF # Force recovery — restart memory-heavy scan daemon diagnose sys scanunit restart
diagnose debug enable ← start streaming debug output to console diagnose debug disable ← stop debug output diagnose debug reset ← reset ALL debug levels to 0 diagnose debug console timestamp enable ← prepend timestamp to every debug line # Show GUI WebUI changes as CLI commands in real time: diagnose debug cli 7 diagnose debug enable
execute reboot execute shutdown
get system interface physical ← all physical interfaces with IP/status diagnose ip address list ← all IPs assigned to FGT interfaces diagnose firewall iplist list ← IPs used in VIPs (Virtual IPs) diagnose firewall ippool list ← IPs used in IP pools (SNAT pools) diagnose netlink interface list ← kernel-level list: includes MTU & device ID
get hardware nic <interface> ← driver info, speed, duplex, error counters diagnose hardware deviceinfo nic <intf> ← detailed NIC stats from OS perspective get system interface physical ← includes transceiver signal info for SFP/SFP+
diagnose ip arp list get system arp ← alternative view execute clear system arp table ← flush entire ARP cache
execute ping x.x.x.x execute ping-options source <src-ip> ← must set BEFORE execute ping execute ping-options repeat-count 10 execute ping-options data-size 1400 execute ping-options df-bit yes ← test path MTU execute ping-options timeout 5 execute ping x.x.x.x ← now execute with options
execute traceroute x.x.x.x execute traceroute-options source <src-ip> execute traceroute-options use-sdwan enable ← follow SD-WAN policy
execute telnet x.x.x.x <port> execute telnet-options source <src-ip>
# Via diagnose traffictest (available on all 7.x) diagnose traffictest server-intf <intf> ← set server interface diagnose traffictest client-intf <intf> ← set client interface diagnose traffictest port <port> ← optional: set port (default 5001) diagnose traffictest run -c <iperf-server-ip> # Via execute iperf3 (7.4+ syntax) execute iperf3 server start execute iperf3 client <server-ip> bw 1G duration 30 # Built-in Internet speed test (7.4+) execute speed-test start execute speed-test status
execute nslookup name <hostname> execute nslookup name <hostname> server <dns-ip> diagnose test application dnsproxy 6 ← dump DNS proxy cache
diagnose netlink interface stats <intf> # Shows: rx_packets, rx_bytes, rx_dropped, tx_packets, tx_bytes, tx_dropped, collisions
diagnose netlink lldp list diagnose netlink lldp summary
diagnose system csf upstream ← list upstream Fabric devices diagnose system csf downstream ← list downstream Fabric devices diagnose system csf neighbor list ← MAC/IP list of connected FortiGate devices
diagnose test appl csfd 1 ← display Security Fabric statistics diagnose debug appl csfd -1 ← real-time csf daemon debugger diagnose debug enable
diagnose automation test <stitch_name> ← manually trigger an automation stitch (for testing)
diagnose endpoint record list ← all endpoint records on this FortiGate diagnose endpoint record list <ip> ← filter by endpoint IP
diagnose report-runner trigger security-rating-reports ← manually trigger security rating check
diagnose system modem detect ← detect attached USB modem diagnose debug appl modemd 3 ← modem daemon debugger
diagnose vpn ike gateway list ← all P1 gateways diagnose vpn ike gateway list name <p1> ← specific gateway get vpn ike gateway ← detailed gateway config + runtime info
diagnose vpn tunnel list ← all P2 tunnels diagnose vpn tunnel list name <p2> ← specific tunnel get vpn ipsec tunnel summary get vpn ipsec tunnel details ← includes SPI, bytes, lifetime get vpn ipsec stats tunnel ← detailed tunnel statistics diagnose vpn ipsec status ← IPsec crypto status overview
Sample: diagnose vpn ike gateway list output
vd: root/0 name: to_HQ2 version: 1 interface: port1 11 addr: 172.16.200.1:500 -> 172.16.202.1:500 ← local:remote IP:port created: 5s ago IKE SA: created 1/1 established 1/1 time 0/0/0 ms IPsec SA: created 2/2 established 2/2 time 0/0/0 ms id/spi: 12 6e8d0532e7fe8d84 / 3694ac323138a024 direction: responder ← this unit answered the IKE request status: established 5-5s ago = 0ms proposal: aes128-sha256 lifetime/rekey: 86400 / 86124 ← total SA lifetime / seconds until rekey DPD sent/recv: 00000000 / 00000000
| Field | Meaning |
|---|---|
| IKE SA created/established | Number of IKE SAs created vs successfully established (want equal) |
| IPsec SA created/established | Number of child (data-plane) SAs. Typically 2 (one each direction) |
| direction: responder | Remote peer initiated the IKE exchange; this unit responded |
| lifetime/rekey | SA valid for 86400 s (24 h); rekeying starts at 86124 s remaining |
| DPD sent/recv | Dead Peer Detection counters — 0/0 = healthy, no DPD failures |
Sample: diagnose vpn tunnel list output
name=to_HQ2 ver=1 serial=1 172.16.200.1:0->172.16.202.1:0 tun_id=172.16.202.1 bound_if=11 lgwy=static/1 tun=intf/0 mode=auto/1 encap=none/528 stat: rxp=0 txp=0 rxb=0 txb=0 dpd: mode=on-demand on=1 idle=20000ms retry=3 count=0 natt: mode=none SA: ref=3 options=18227 type=00 mtu=1438 expire=42927/0B replaywin=2048 life: type=01 bytes=0/0 timeout=42930/43200 dec: spi=ef9ca700 esp=aes key=16 ... enc: spi=791e898e esp=aes key=16 ...
| Field | Meaning |
|---|---|
| mtu=1438 | Effective MTU inside tunnel (after ESP/IP overhead) |
| replaywin=2048 | Anti-replay window size in packets |
| natt: mode=none | NAT-Traversal not active (no NAT between peers) |
| dpd: mode=on-demand | DPD only sent when traffic needs to flow but peer appears silent |
| dec: spi / enc: spi | Security Parameter Index for inbound (decrypt) / outbound (encrypt) SA |
# 1. Scope to one peer (prevents log flood) diagnose vpn ike log-filter dst-addr4 <remote-ip> # or use verbosity flag (63 = all IKE events): diagnose debug appl ike 63 # 2. Enable output diagnose debug enable # 3. Flush SA to force re-negotiation diagnose vpn ike gateway flush name <p1-name> # 4. Watch output; stop when done diagnose debug disable diagnose debug reset diagnose vpn ike log-filter clear
log-filter to scope to one peer. Level -1 or 63
is very verbose.diagnose vpn ike gateway flush name <p1-name> ← delete Phase 1 SA diagnose vpn tunnel flush name <p2-name> ← delete Phase 2 SA execute vpn ike restart ← restart iked daemon (ALL tunnels drop)
diagnose vpn ssl list ← active SSL-VPN sessions diagnose vpn ssl statistics get vpn ssl monitor # Debug diagnose debug application sslvpn -1 diagnose debug enable
Common IPsec Error Codes
| Error / Message | Likely Cause | Fix |
|---|---|---|
NO_PROPOSAL_CHOSEN |
Phase 1/2 proposal mismatch | Align encryption/hash/DH group on both peers |
INVALID_ID_INFORMATION |
Local/remote ID mismatch | Check localid / peer-id settings |
AUTHENTICATION_FAILED |
PSK mismatch or cert issue | Re-verify PSK; check cert serial & CA chain |
TS_UNACCEPTABLE |
Traffic selector (Phase 2 subnet) mismatch | Verify Phase 2 subnets match exactly on both sides |
INVALID_PAYLOAD_TYPE |
IKE version mismatch (v1 vs v2) | Set both ends to the same IKE version |
DPD timeout |
Peer unreachable or MTU issue | Check routing; try reducing MTU to 1400 |
delete_ike_sa: error |
iked restarted mid-negotiation | Flush SA and retry; check daemon stability |
get router info routing-table all ← full routing table (active routes only) get router info routing-table connected get router info routing-table static get router info routing-table details <x.x.x.x> ← routing decision for a specific IP get router info routing-table database ← includes inactive (not-best) routes get router info kernel ← kernel FIB (what is actually used for forwarding) get router info protocols ← overview of dynamic routing protocol config
Routing table route type codes
| Code | Meaning |
|---|---|
| K | Kernel route (directly connected, OS-generated) |
| C | Connected network (interface has IP in this subnet) |
| S | Static route (manually configured) |
| R | RIP — Routing Information Protocol |
| B | BGP — Border Gateway Protocol |
| O | OSPF — Open Shortest Path First |
| IA | OSPF inter-area route |
| E1 / E2 | OSPF external type 1 / type 2 |
| N1 / N2 | OSPF NSSA external type 1 / type 2 |
| i / L1 / L2 / ia | IS-IS / level-1 / level-2 / inter-area |
| V | BGP VPNv4 route |
| * | Candidate default route |
diagnose ip rtcache list ← route cache entries (fast-path lookups) diagnose firewall proute list ← policy-based route (PBR) entries with priority/gateway/intf execute router restart ← restart the routing process (brief interruption)
diagnose system link-monitor status ← overall link-monitor state diagnose system link-monitor interface ← per-interface link-monitor detail diagnose system link-monitor launch ← trigger WAN LLB (link load balance)
get router info bgp summary get router info bgp neighbors get router info bgp neighbors <peer-ip> advertised-routes get router info bgp neighbors <peer-ip> received-routes get router info bgp network # Real-time BGP debug diagnose ip router bgp all enable diagnose ip router bgp level info diagnose debug enable # Reset sessions execute router clear bgp all execute router clear bgp neighbor <peer-ip>
get router info ospf status get router info ospf neighbor get router info ospf interface get router info ospf database brief ← LSDB summary get router info ospf database router lsa ← detailed LSA entries get router info ospf database self-originate ← LSAs originated by this unit # Real-time OSPF debug diagnose ip router ospf all enable diagnose ip router ospf level info diagnose debug enable execute router clear ospf process ← restart OSPF (brief neighbor drop)
diagnose sys sdwan health-check status ← SLA states for all health checks diagnose sys sdwan health-check status filter <name> diagnose sys sdwan member ← interface details (bandwidth, latency, jitter) diagnose sys sdwan service <rule-id> ← SD-WAN rule state for specific rule diagnose sys sdwan intf-sla-log <intf-name> ← link traffic history per interface diagnose sys sdwan sla-log <sla> <link_id> ← SLA log on a specific interface/link get system sdwan # Link monitor / debug diagnose test appl lnkmtd 0 ← link-monitor stats (0=reset, 1=print, 2=debug) diagnose debug appl link-mon -1 ← real-time link-monitor debugger diagnose debug enable # 7.4+: passive health check diagnose sys sdwan passive-health-check <member>
ECMP vs SD-WAN Load-Balancing Algorithms
| ECMP Mode | SD-WAN Equivalent | Behavior |
|---|---|---|
| Source IP-based | Source IP | All sessions from the same source IP use the same path (default) |
| Weight-based | Sessions | Workload distributed proportionally by configured weight / session count |
| Usage-based | Spillover | Path used until bandwidth threshold exceeded; traffic spills to next path |
| Source-Destination IP | Source-Destination IP | Hash on src+dst IP pair; same src+dst always use the same path |
diagnose firewall iprope lookup <src-ip> <dst-ip> <proto> <src-port> <dst-port> <in-intf> # Example: HTTP from 10.1.1.10 to 8.8.8.8 via port1 diagnose firewall iprope lookup 10.1.1.10 8.8.8.8 6 12345 80 port1
diagnose firewall iprope show 100004 ← show all policies with hit counters (table 100004) diagnose firewall iprope clear 100004 ← reset all policy hit counters diagnose firewall iprope clear 100004 <id> ← reset counters for a specific policy ID
diagnose test application ipsmonitor 1 diagnose ips filter src-ip <ip> diagnose ips filter enable diagnose debug application ipsengine 7 diagnose debug enable
diagnose antivirus version diagnose test application scanunitd 1 ← scanunit status diagnose test application scanunitd 3 ← scanunit stats & memory diagnose debug application scanunitd 7 diagnose debug enable
diagnose debug application urlfilter -1 diagnose debug enable diagnose test application urlfilter 2 <url> ← FortiGuard category lookup for URL
diagnose firewall ippool-all list diagnose firewall ippool list <pool-name> diagnose sys session filter natsrcip <nat-ip> diagnose sys session list
diagnose debug application ssl -1 diagnose debug enable diagnose test application sslworker 1
get system ha status ← mode, group, heartbeat intf, master/slave priority diagnose system ha history read ← details about past HA events (failovers, etc.) diagnose system ha dump-by vcluster ← show cluster member uptime per vcluster
diagnose sys ha checksum cluster ← compare checksums across all members diagnose sys ha checksum show [vdom] ← detailed checksum for local unit or specific VDOM diagnose sys ha checksum recalculate ← force recalculation when master/slave are out of sync
firewall.policy).diagnose system ha reset-uptime ← lower local uptime → triggers re-election execute ha failover status ← view current failover status execute ha failover set <cluster_id> ← force specific device into failover state (becomes standby) execute ha ignore-hardware-revision status ← view HW revision ignore setting execute ha ignore-hardware-revision enable ← allow HA between different HW revisions (labs/RMA) execute ha ignore-hardware-revision disable # Connect to secondary via HA management tunnel execute ha manage <member-id> <username> diagnose sys ha dump-by-vcluster ← list member IDs
diagnose debug appl hasync -1 diagnose debug appl hatalk -1 diagnose debug enable # Reproduce the issue, then: diagnose debug disable diagnose debug reset
execute ha synchronize stop execute ha synchronize start
HA Status Fields
| Field | Meaning |
|---|---|
is_root_master |
This unit is the active (master) member |
override |
Master override enabled — highest-priority device always wins elections |
ses_pickup |
Session pickup enabled — standby syncs active sessions for graceful failover |
load_balance_all |
FGCP A-A load balancing mode active |
vcluster_state |
Per-VDOM cluster state (used in A-A VDOM mode) |
show log setting show log fortianalyzer setting show log syslogd setting
execute log filter category 1 ← 1=traffic, 2=event, 3=virus, etc. execute log filter start-line 1 execute log filter max-checklines 50 execute log display
diagnose test application miglogd 6 ← FAZ connection status diagnose log test ← send a test log entry to all configured targets diagnose debug application miglogd 255 diagnose debug enable
diagnose sys logdisk usage diagnose sys logdisk stat
Log Category IDs
| ID | Category | Description |
|---|---|---|
| 0000 | traffic | Forward, local, sniffer traffic logs |
| 0001 | event | System, VPN, user, router, WAD events |
| 0002 | virus | AV detections |
| 0003 | webfilter | URL category blocks/monitors |
| 0004 | ips | IPS detections & anomalies |
| 0005 | emailfilter | Spam detections |
| 0006 | anomaly | DoS policy anomalies |
| 0008 | voip | VoIP session tracking |
| 0009 | dlp | Data loss prevention hits |
| 0011 | app-ctrl | Application control hits |
| 0012 | waf | Web application firewall events |
| 0059 | ssh | SSH inspection events |
| 0061 | ssl | SSL inspection events |
Log Severity Levels
| Level | Value | Meaning |
|---|---|---|
| emergency | 0 | System unusable |
| alert | 1 | Immediate action needed |
| critical | 2 | Critical conditions |
| error | 3 | Error conditions |
| warning | 4 | Warning conditions |
| notice | 5 | Normal significant events |
| information | 6 | Informational |
| debug | 7 | Debug-level messages |
Packet Sniffer Syntax
diagnose sniffer packet <interface> '<bpf-filter>' <verbose> <count> <timestamp> # <interface> : interface name or any # <bpf-filter> : BPF expression in single quotes; '' = no filter (all traffic) # <verbose> : 1–6 (see table below) # <count> : number of packets then stop; 0 = infinite (Ctrl+C to stop) # <timestamp> : a = absolute UTC | l = local time | (blank) = relative from start
Verbose levels
| Level | Output |
|---|---|
| 1 | One-line summary (protocol, src/dst, length) |
| 2 | IP header detail |
| 3 | IP header + Ethernet header + hex dump |
| 4 | One-line summary + interface name |
| 5 | IP header + interface name |
| 6 | IP + Ethernet + hex + interface name (convertible to .pcap via Perl script) |
BPF filter options
| Filter | Description |
|---|---|
| host x.x.x.x | Match packets where src OR dst = x.x.x.x |
| src x.x.x.x | Match packets where source IP = x.x.x.x |
| dst x.x.x.x | Match packets where destination IP = x.x.x.x |
| net x.x.x.x/24 | Match any address within the subnet |
| port xx | Match TCP or UDP packets on port xx |
| src port xx | Match packets originating from source port xx |
| dst port xx | Match packets destined to port xx |
| tcp | TCP packets only |
| udp | UDP packets only |
| icmp | ICMP packets only |
| arp | ARP packets only |
| ip proto <n> | Match by IP protocol number |
| ether proto <n> | Match by Ethernet protocol type |
| less <n> | Packets smaller than n bytes |
| greater <n> | Packets larger than n bytes |
and, or, not — e.g.,
'src x.x.x.x and tcp port 443'
Examples
# All traffic to/from 1.2.3.4 on any interface, 1-line, forever diagnose sniffer packet any 'host 1.2.3.4' 1 0 a # 100 packets for HTTPS on port1, with local timestamp diagnose sniffer packet port1 'tcp port 443' 4 100 l # Traffic between two specific hosts diagnose sniffer packet any 'host 10.0.1.1 and host 10.0.2.1' 1 0 a # All traffic except ICMP diagnose sniffer packet any 'not icmp' 1 0 a # Source IP 10.1.1.5 to TCP port 80 diagnose sniffer packet any 'src 10.1.1.5 and tcp port 80' 1 0 a # Full subnet capture diagnose sniffer packet any 'net 192.168.10.0/24' 2 50 a # GUI equivalent: Network > Diagnostics > Packet Capture
# 1. Set filter (mandatory — scopes what gets traced) diagnose debug flow filter addr <src-or-dst-ip> # Alternative filters: diagnose debug flow filter saddr <src-ip> diagnose debug flow filter daddr <dst-ip> diagnose debug flow filter net <x.x.x.x/mask> diagnose debug flow filter port <port> diagnose debug flow filter proto tcp|udp|icmp # Advanced: combine multiple filters diagnose debug flow filter saddr 10.1.1.5 diagnose debug flow filter daddr 8.8.8.8 diagnose debug flow filter port 443 # 2. Enable IP routing and function name display diagnose debug flow show iprop enable diagnose debug flow show function-name enable # 3. Start trace (limit packet count) diagnose debug flow trace start 100 # 4. Enable debug output diagnose debug enable # 5. Trigger traffic (ping, curl, etc.) # 6. Stop when done diagnose debug flow trace stop diagnose debug disable diagnose debug flow filter clear # GUI equivalent: Network > Diagnostics > Debug Flow
Key Debug Flow Messages
| Message | Meaning |
|---|---|
allocate a new session |
New session created in session table |
find a route: gw-> <ip> via <intf> |
Routing lookup result — packet will exit this interface |
Denied by forward policy check |
No matching allow policy found (implicit deny) |
iprope_in_check() check failed |
Packet blocked at policy check (implicit deny) |
SNAT <src> to <nat-ip> |
Source NAT applied |
DNAT <dst> to <real-ip> |
Destination NAT (VIP) applied |
reverse path check fail |
RPF check failed — asymmetric routing |
drop by ips |
IPS engine blocked the packet |
offload to npu |
Session handed to hardware NP processor |
nturbo route |
NTurbo (SW fast-path) is handling this session |
# Set one or more filters, then list or clear diagnose sys session filter src <ip> ← source IP filter diagnose sys session filter dst <ip> ← destination IP filter diagnose sys session filter dport <port> ← destination port diagnose sys session filter sport <port> ← source port diagnose sys session filter proto <6|17|1> ← protocol (TCP/UDP/ICMP) diagnose sys session filter policy <id> ← sessions matching a specific policy ID diagnose sys session filter natsrcip <ip> ← sessions with this NAT source IP # List matching sessions diagnose sys session list # Show stats and memory usage diagnose sys session stat diagnose sys session full-stat ← session counts per VDOM # Clear filter diagnose sys session filter clear # Alternative syntax (both work identically): diagnose system session filter src <ip> diagnose system session list
diagnose sys session clear ← clears ALL sessions (NEVER on production without filter) # Safe: set a filter first diagnose sys session filter src 10.1.1.100 diagnose sys session clear ← clears only sessions matching the filter
diagnose firewall iprope clear 100004 ← reset hit counters for all policies diagnose firewall iprope clear 100004 <id> ← reset counter for one policy # Useful for cleaning up unused policy identification and hardening
Session Flag Bitmask
| Flag | Hex | Meaning |
|---|---|---|
may_dirty |
0x01 | Session may need policy re-evaluation |
dirty |
0x02 | Session flagged for re-check on next packet |
npu |
0x08 | Session offloaded to NP hardware |
nturbo |
0x10 | NTurbo (CPU fast-path) offload active |
synced |
0x20 | Session synced to HA peer |
log |
0x40 | Session logging enabled for this flow |
auth |
0x100 | Session authenticated — user identity known |
redir |
0x400 | Session redirected (WAD/proxy) |
proto_state (TCP)
| proto_state | TCP State | Notes |
|---|---|---|
| 0/0 | NONE | SYN not yet seen |
| 1/0 | SYN_SENT | SYN seen, SYN-ACK not yet received |
| 1/1 | SYN_RCVD | SYN + SYN-ACK seen |
| 2/2 | ESTABLISHED | Full 3-way handshake complete |
| 3/x | FIN_WAIT | FIN sent by client |
| 5/5 | CLOSE_WAIT | Both FINs seen |
| 6/6 | TIME_WAIT | Awaiting timer expiry |
diagnose test authserver ldap <server-name> <username> <password> diagnose test authserver radius <server-name> <auth-type> <username> <password> # auth-type: pap | chap | mschapv2
diagnose firewall auth list ← authenticated firewall users with group membership get user radius get user ldap get user local
diagnose debug authd fsso list ← FSSO sessions (who is logged in) diagnose debug authd fsso server-status ← connectivity to FSSO Collector Agent diagnose debug authd fsso refresh-logons ← force re-poll of logon events
diagnose debug application fnbamd -1 diagnose debug enable # Have user attempt to authenticate, then: diagnose debug disable diagnose debug reset
diagnose endpoint fctems test connectivity <EMS-name> ← verify FGT → EMS reachability diagnose test app fcnacd 2 ← dump EMS connectivity info execute fctems verify <EMS-name> ← verify EMS certificate
diagnose debug application fcnacd -1 diagnose debug enable # Reproduce issue, then: diagnose debug disable
diagnose endpoint record list <ip> ← endpoint record for a specific IP diagnose wad dev query-by ipv4 <ip> ← WAD device info for an IP address diagnose firewall dynamic list ← EMS ZTNA tags + dynamic IP and MAC addresses
diagnose hardware sysinfo cpu ← CPU type, core count, utilisation diagnose hardware sysinfo memory ← total/used/free RAM diagnose hardware sysinfo shm ← shared memory usage (inter-process) diagnose hardware sysinfo conserve ← conserve mode thresholds & current state diagnose hardware test suite all ← full hardware self-test (newer models) get hardware status ← ASIC & NP processor info
get vpn status ssl hw-acceleration-status ← shows whether SSL crypto is NP-offloaded
diagnose npu np6 port-list diagnose npu np6 session-stats diagnose npu np6 stats <np-id> diagnose npu np6 dce <np-id> ← drop/error counters
diagnose npu np7 port-list diagnose npu np7 session-stats diagnose npu np7 stats <np-id> diagnose npu np7 sse-stats <np-id> ← Session Scheduling Engine stats
# Per-policy (preferred — no global CPU impact)
config firewall policy
edit <policy-id>
set auto-asic-offload disable
next
end
# Per VPN Phase 1 (disable NP offload for IPsec)
config vpn ipsec phase1-interface
edit <p1-name>
set npu-offload disable
next
end
# Global (all traffic — AVOID on high-throughput devices)
config system settings
set np-offload-threshold 0
end
Disk Management
diagnose sys logdisk usage diagnose sys logdisk stat diagnose hardware deviceinfo disk ← list all disks and partitions execute disk list ← disk and partition summary execute disk scan [ref_int] ← scan and repair disk errors execute disk format [ref_int] ← format a specific disk/partition (data loss!) then reboot execute formatlogdisk ← format log disk and reboot (clears all logs)
FortiSwitch
get switch-controller managed-switch diagnose switch-controller switch-info <sw-serial> diagnose switch-controller switch-info all execute switch-controller get-conn-status ← connection status for all managed switches execute switch-controller diagnose-connection <switch> ← connectivity diagnostics
diagnose switch-controller switch-info mac-table ← MAC address table for all managed switches diagnose switch-controller switch-info port-stats ← per-port RX/TX/error statistics diagnose switch-controller switch-info trunk ← trunk (LAG) information diagnose switch-controller switch-info mclag ← MC-LAG information diagnose switch-controller switch-info poe <sw-serial> ← PoE status per port
FortiAP (via Wireless Controller)
get wireless-controller wtp ← managed AP list diagnose wireless-controller wlac -c ap-list ← AP details diagnose wireless-controller wlac -c sta-list ← associated client list diagnose wireless-controller wlac -c ap-rogue ← rogue AP list
execute wireless-controller restart-acd ← restart wireless controller daemon execute wireless-controller reset-wtp ← restart all managed FortiAPs
execute wireless-controller spectral-scan <wtp-id> <radio-id> on <duration> <channel> <interval> diagnose wireless-controller wlac -c rf-sa <wtp-id> <radio-id> <channel> get wireless-controller spectral-info <wtp-id> <radio-id>
diagnose wireless-controller wlac -d capwap <ap-name> diagnose debug application cw_acd -1 diagnose debug enable
FortiAP CLI (direct commands on the AP itself)
cfg -a ADDR_MODE=DHCP ← set IP mode to DHCP cfg -a ADDR_MODE=STATIC ← set IP mode to static cfg -a AP_IPADDR="x.x.x.x" ← set static IP cfg -a AP_NETMASK="255.255.255.0" ← set subnet mask cfg -a IPGW="y.y.y.y" ← set gateway cfg -a AC_IPADDR_1="z.z.z.z" ← set Wireless Controller IP cfg -s ← list current config cfg -c ← commit (save) config cfg -x ← reset to factory default
FortiExtender
diagnose extender-controller extender list diagnose extender-controller extender detail <serial> diagnose extender-controller extender modem-status <serial> get extender sys-info <ext-sn> ← FortiExtender system info get extender modem-status <ext-sn> ← detailed modem status execute extender reset-fortiextender ← restart managed FortiExtender execute extender restart-fortiextender-daemon ← restart FortiExtender daemon diagnose debug appl extenderd -1 ← FortiExtender debugging (~5 min capture)
diagnose system lte-modem signal-info ← signal strength (RSSI, RSRQ, RSRP, SNR) diagnose system lte-modem traffic-status ← TX/RX packet and byte counts diagnose system lte-modem modem-details ← hardware/firmware detail diagnose system lte-modem sim-info ← SIM card information diagnose system lte-modem data-session-info ← active data session details diagnose system lte-modem gps-info ← GPS coordinates (if supported) diagnose system lte-modem data-usage ← cumulative data usage diagnose system modem detect ← detect USB modem attached to FGT
config system lte-modem
set status enable
set apn "internet" ← replace with carrier APN
end
# Tip: disable any SIM PIN before deploying to avoid lockout
Signal info output explained
# diagnose system lte-modem signal-info
WCDMA:
RSSI: -57 ← Received Signal Strength; higher (less negative) = stronger
ECIO: 12 ← Energy-to-Interference ratio; higher = cleaner signal
LTE:
RSSI: -67 ← LTE received signal strength (dBm)
RSRQ: -13 ← Reference Signal Received Quality (dB); above -10 = good
RSRP: -98 ← Reference Signal Received Power (dBm); above -100 = acceptable
SNR: 44 ← Signal-to-Noise Ratio (dB); higher = better
| Metric | Good | Acceptable | Poor |
|---|---|---|---|
| LTE RSRP (dBm) | > -80 | -80 to -100 | < -100 |
| LTE RSRQ (dB) | > -10 | -10 to -15 | < -15 |
| LTE SNR (dB) | > 20 | 0 to 20 | < 0 |
Traffic status output explained
# diagnose system lte-modem traffic-status TX packets OK: 8513 ← successfully transmitted packets RX packets OK: 10842 ← successfully received packets TX packets error: 0 ← transmission errors (non-zero = investigate) RX packets error: 0 ← receive errors TX/RX overflows: 0 ← buffer overflows (non-zero = congestion) TX bytes OK: 748973 ← bytes transmitted successfully RX bytes OK: 8770104 ← bytes received successfully TX/RX packets dropped: 0 ← dropped packets (non-zero = congestion or policy)
VDOM Commands
# Enter a VDOM context
config vdom
edit <vdom-name>
end
# Sudo shortcut — run diagnose/execute/show from global scope in a specific VDOM
sudo <vdom-name> diagnose sys top
sudo <vdom-name> execute ping 8.8.8.8
sudo global show system interface
Transparent Mode
diagnose netlink brctl name host <bridge-name> ← show MAC table for a transparent-mode bridge # Useful when FGT is inserted in-line between two switches in L2 mode
Workspace Mode (GUI Multi-Admin)
# Start / commit / abort a workspace session execute config-transaction start execute config-transaction commit execute config-transaction abort # Status and active sessions diagnose system config-transaction status ← enabled/disabled state diagnose system config-transaction show txn-info ← all active workspace locks diagnose system config-transaction show txn-cli-commands ← pending CLI commands in workspace
abort command discards all
uncommitted changes.Syntax
# Debug an application daemon: diagnose debug application <app_name> <level> diagnose debug enable ← must enable to start seeing output # … reproduce the issue … diagnose debug disable diagnose debug reset ← reset all debug levels to 0 # Alternative (older syntax): diagnose debug appl <app_name> <level> # Test/probe a daemon (non-debug status queries): diagnose test appl <app_name> <test_level>
Debug Levels
| Level | Output Verbosity |
|---|---|
-1 |
Most verbose — all available debug info. Use for deep troubleshooting; generates a lot of output quickly. |
0 |
Disable debug for this application. |
1 |
Basic — high-level operations and errors. Good for initial diagnosis. |
2 |
Medium verbosity — more detail without overwhelming output. |
3–7 |
Increasingly detailed. Exact granularity depends on the daemon. |
63 |
IKE-specific: all IKE negotiation events (equivalent to -1 for ike). |
Common Debuggable Applications
| App Name | Daemon / Function | Typical Use |
|---|---|---|
ike |
IKE daemon (iked) | IPsec VPN tunnel negotiation failures |
sslvpn |
SSL-VPN proxy daemon | SSL-VPN connection / access control issues |
fnbamd |
Auth daemon | RADIUS, LDAP, FSSO auth failures |
radiusd |
RADIUS daemon | RADIUS server communication issues |
dnsproxy |
DNS proxy | DNS resolution and split-DNS issues |
dhcp |
DHCP server/relay/client | DHCP lease assignment failures |
httpsd |
HTTPS management daemon | Web GUI access issues |
sshd |
SSH daemon | SSH management access issues |
hasync |
HA sync daemon | HA configuration synchronisation |
hatalk |
HA talk daemon | HA heartbeat / election issues |
csfd |
Security Fabric daemon | Fabric topology and communication |
fcnacd |
FortiClient NAC daemon | EMS / ZTNA connectivity |
miglogd |
Log forwarding daemon | FAZ / syslog forwarding issues |
scanunitd |
UTM scanning daemon | AV/IPS/proxy scanning performance |
ipsengine |
IPS engine | IPS signature matching and drops |
urlfilter |
URL filter daemon | FortiGuard web category lookup |
ntpd |
NTP daemon | Time sync issues (affects cert validation, logs) |
link-mon |
Link monitor | SD-WAN health-check and WAN failover |
cw_acd |
CAPWAP AC daemon | FortiAP management tunnel issues |
extenderd |
FortiExtender daemon | FortiExtender management issues |
modemd |
Modem daemon | USB modem / LTE connectivity |
forticldd |
FortiCloud daemon | FortiCloud / licence connectivity |
wad |
WAD proxy daemon | Explicit proxy, WCCP, SSL deep inspection |
Examples
# IPsec / IKE negotiation diagnose debug application ike -1 diagnose debug enable # SSL-VPN login issues diagnose debug application sslvpn -1 diagnose debug enable # LDAP / RADIUS auth failure diagnose debug application fnbamd -1 diagnose debug enable # DNS resolution issues diagnose debug application dnsproxy -1 diagnose debug enable # DHCP lease problems diagnose debug application dhcp -1 diagnose debug enable # Always clean up afterwards: diagnose debug disable diagnose debug reset
- Must be logged in with a super_admin profile account.
- On FortiGate VMs: requires a paid licence — free evaluation VMs return
Unknown action 0. - CLI-only — no GUI equivalent.
- Executes locally on the unit where the session is initiated. To run on a passive HA member, log in directly to that unit.
- Tab completion does not work with this command.
- Can be used in automation stitches via
set action-type cli-script. - Not available when FIPS-CC mode is enabled — verify with
get system status.
fnsysctl ifconfig ← all interfaces fnsysctl ifconfig port1 ← specific interface
Shows detailed info: IP, MAC, MTU, RX/TX packets, errors, drops,
collisions. More detailed than get system interface physical — includes frame/overrun
counters.
port1 Link encap:Ethernet HWaddr 0A:7C:2A:D2:17:6F
inet addr:10.100.100.227 Bcast:10.100.100.255 Mask:255.255.255.0
link-local6: fe80::87c:2aff:fed2:176f prefixlen 64
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:3537 errors:0 dropped:0 overruns:0 frame:0
TX packets:5436 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1340257 (1.3 MB) TX bytes:4360502 (4.2 MB)
fnsysctl ls /tmp ← list directory fnsysctl ls -al /tmp ← all files, long format (timestamps, sizes, permissions) fnsysctl ls -a /tmp ← all files including dot-files # Flags: -a (all), -l (long), -A (almost all — omit . and ..)
Useful for post-incident forensics — checking for unexpected files that may indicate a compromise (CVE indicators of compromise / IOCs).
fnsysctl ls -al /tmp drwxr-xr-x 2 0 0 Wed Oct 23 01:53:42 2024 40 $$auto-script$$ drwxrwxrwt 60 0 0 Wed Oct 23 02:03:46 2024 4780 . drwxr-xr-x 18 0 0 Wed Oct 23 01:53:40 2024 0 .. srwxr-xr-x 1 0 0 Wed Oct 23 01:53:42 2024 0 .auto_script_server -rw-r--r-- 1 0 0 Wed Oct 23 01:53:42 2024 0 .aws_addrs srwxr-xr-x 1 0 0 Wed Oct 23 01:53:42 2024 0 .cloudapi_fconv.sock srwxr-xr-x 1 0 0 Wed Oct 23 01:53:42 2024 0 .dhcpd.msg srwxr-xr-x 1 0 0 Wed Oct 23 01:53:42 2024 0 .dns_local_server
# Show open TCP connections (FortiGate to/from the management plane) fnsysctl cat /proc/net/tcp # Note: output is in hex — easier alternative: diagnose sys tcpsock | grep 0.0.0.0 # CPU info fnsysctl cat /proc/cpuinfo # CPU interrupt counters (per-core, useful for RSS/IRQ balancing troubleshooting) fnsysctl cat /proc/interrupts # Memory info fnsysctl cat /proc/meminfo # NTurbo acceleration stats for queue 0 fnsysctl cat /proc/nturbo/0/drv
cat: /tmp/cw_ac_key_bak.pem: Not allowedSample: /proc/interrupts
CPU0 CPU1 CPU2 CPU3 142: 3506701 0 0 0 PCI-MSI-edge np6_0-tx-rx0 143: 1 742138 0 0 PCI-MSI-edge np6_0-tx-rx1 144: 1 0 3850634 0 PCI-MSI-edge np6_0-tx-rx2 145: 1 0 0 3319842 PCI-MSI-edge np6_0-tx-rx3 # Each row: interrupt ID, per-CPU count, type, source # Useful for verifying NP/NIC interrupts are spread across CPUs
Sample: /proc/nturbo/0/drv — NTurbo queue stats
Turbo interface ID: 0 Driver RX/TX: 760818543 / 759413272 Free/Used buffers: 109675 / 2965 Alloc fail: 0 RXQ_0(0,20806): IN 64201109 OUT 64201142 DROP 0 NRDY 0 Fullness 0 Peak 282 TXQ_0(0,20806): IN 64083848 OUT 64083848 DROP 0 SHAPER_DROP 0 USR_DROP 117056 BUFERR 0 RXQ_1(1,20808): IN 62241175 OUT 62241191 DROP 0 NRDY 0 Fullness 0 Peak 444 TXQ_1(1,20808): IN 62092654 OUT 62092654 DROP 0 SHAPER_DROP 0 USR_DROP 148288 BUFERR 0 # USR_DROP = packets dropped by the upper-layer user-space process (normal at high rates) # SHAPER_DROP = dropped by traffic shaper (indicates congestion)
fnsysctl date # Output: Wed Oct 23 02:11:03 PDT 2024 # Shows kernel time in Linux format; ignores options
fnsysctl df -h ← human-readable sizes
Filesystem Size Used Available Use% Mounted on none 1.3G 81.6M 1.2G 6% /tmp none 1.3G 4.7M 1.3G 0% /dev/shm /dev/nvme0n1p1 231.9M 129.2M 89.9M 59% /data /dev/nvme0n1p2 1.6G 141.7M 1.4G 9% /data2 /dev/nvme1n1p1 29.4G 54.8M 27.8G 0% /var/log
Useful when NVMe/SSD disks are attached. Monitor
/var/log fill — if at 100% logs stop being written.
fnsysctl du -s ← summary: total size of current tree fnsysctl du -d 1 -a ← 1 level deep, include files fnsysctl du -L ← follow symlinks # Flags: -d n (depth limit), -a (include files), -s (summary only), -L (follow symlinks) # Example: find biggest top-level directories fnsysctl du -d 1 -a
71960 ./new_root 20488 ./migadmin 5344 ./node-scripts 113596 ./bin 131464 ./data 142520 ./data2 147440 ./tmp 715324 . ← total
fnsysctl pwd # Output: / # Note: cd is not available, so the directory is always /
fnsysctl ps
Lists all running processes with PID, UID, GID, state, and command. Most FortiGate daemons are managed by a watchdog — killing them causes an immediate automatic restart.
PID UID GID STATE CMD 1 0 0 S /bin/init 2026 0 0 S /bin/dnsproxy 2045 0 0 S /bin/wad 4 2053 0 0 S /bin/miglogd 1 2095 0 0 S /bin/ipsengine 2119 0 0 S /bin/urlfilter 0 2124 0 0 R /bin/sshd 2125 0 0 S /bin/newcli 2325 0 0 S /bin/httpsd ← S=sleeping R=running I=idle kernel thread
Process state codes
| State | Meaning |
|---|---|
| R | Running (actively using CPU) |
| S | Sleeping (waiting for event) |
| I | Idle kernel thread |
| Z | Zombie (exited but not reaped) |
# Kill by PID (from fnsysctl ps output) fnsysctl kill 2325 ← sends SIGTERM (default) to PID 2325 fnsysctl kill -s 9 2325 ← send specific signal (9=SIGKILL) # Kill by name (more practical — kills all instances) fnsysctl killall httpsd ← restart the HTTPS management daemon fnsysctl killall dnsproxy ← restart DNS proxy fnsysctl killall miglogd ← restart log forwarding daemon
diagnose debug crashlog read).
Not all processes can be killed this way (e.g., hasync is protected).
Most daemons are watched — they restart automatically within seconds.
# Most directories are read-only; /tmp is writable fnsysctl mv /tmp/ipsshm.urldb-whitelist /tmp/ipsshm.urldb-whitelist.orig # Prompts for admin username and password explicitly # Verify result: fnsysctl ls -al /tmp/ipsshm.urldb-whitelist.orig
fnsysctl grep <pattern> <file> fnsysctl grep -i "error" /var/log/messages ← case-insensitive fnsysctl grep -n "sshd" /proc/net/tcp ← show line numbers fnsysctl grep -v "DROP" /tmp/somefile ← invert match (exclude pattern) fnsysctl grep -c "ACCEPT" /tmp/somefile ← count matching lines only fnsysctl grep -A 3 "crash" /var/log/messages ← 3 lines of trailing context fnsysctl grep -B 3 "crash" /var/log/messages ← 3 lines of leading context fnsysctl grep -C 3 "crash" /var/log/messages ← 3 lines both sides
| Flag | Description |
|---|---|
| -i | Ignore case distinctions |
| -l | List only filenames of files containing a match |
| -H | Prefix each output line with the filename |
| -h | Suppress filename prefix |
| -n | Print line number alongside each match |
| -q | Quiet — exit 0 if match found, no output |
| -v | Invert — show lines that do NOT match |
| -s | Suppress file open/read error messages |
| -c | Print only a count of matching lines |
| -A N | Print N lines of trailing context after match |
| -B N | Print N lines of leading context before match |
| -C N | Print N lines of context on both sides of match |
fnsysctl printenv # Output: TERM=vt220 # Very limited — only terminal type is typically visible
Quick Reference — All fnsysctl Sub-commands
| Sub-command | Use Case | Key Flags |
|---|---|---|
ifconfig [intf] |
Interface stats: errors, drops, MTU, RX/TX | interface name (optional) |
ls [flags] [path] |
Filesystem listing; forensic IOC hunting | -a -l -A |
cat <file> |
Read /proc files: cpuinfo, meminfo, interrupts, tcp, nturbo | — |
date |
Show kernel date/time in Linux format | — |
df [-h] |
Filesystem usage (disk partitions, /var/log fill) | -h |
du [flags] [path] |
Directory size breakdown | -d -a -s -L |
pwd |
Show working directory (always /) |
— |
ps |
Full process list with PID, state, command | — |
kill [-s N] <pid> |
Send signal to process by PID | -s <signal> |
killall <name> |
Kill all instances of a daemon by name (watchdog restarts) | process name |
mv <src> <dst> |
Move/rename files in writable dirs (e.g., /tmp) | — |
grep [flags] <pat> <file> |
Search file contents | -i -n -v -c -A -B -C |
printenv |
Show environment variables (limited) | — |
Scenario 1 — IPsec Tunnel Not Coming Up
- Verify Phase 1 state:
diagnose vpn ike gateway list name <p1-name>
- Enable IKE debug scoped to peer:
diagnose vpn ike log-filter dst-addr4 <remote-ip> diagnose debug application ike 63 diagnose debug enable
- Flush SA to force re-negotiation:
diagnose vpn ike gateway flush name <p1-name>
- Interpret output:
NO_PROPOSAL_CHOSEN→ align proposals.AUTHENTICATION_FAILED→ verify PSK.TS_UNACCEPTABLE→ check Phase 2 subnets. - Clean up:
diagnose debug disable diagnose vpn ike log-filter clear
Scenario 2 — Traffic Blocked, No Log
- Run debug flow:
diagnose debug flow filter addr <client-ip> diagnose debug flow show function-name enable diagnose debug flow trace start 50 diagnose debug enable
- Send test traffic. Look for:
Denied by forward policy check(no policy),reverse path check fail(RPF/asymmetric routing),iprope_in_check() check failed(implicit deny). - Verify which policy matches:
diagnose firewall iprope lookup <src> <dst> 6 12345 80 <in-intf>
- Stop debug:
diagnose debug flow trace stop diagnose debug disable
Scenario 3 — HA Sync Issue
- Check HA status:
get system ha status diagnose system ha history read
- Compare checksums — look for mismatched table (e.g.,
firewall.policy):diagnose sys ha checksum cluster
- Enable sync debug:
diagnose debug appl hasync -1 diagnose debug appl hatalk -1 diagnose debug enable
- Force checksum recalculation:
diagnose sys ha checksum recalculate
- If secondary is fully out of sync, re-sync from secondary:
execute ha synchronize stop execute ha synchronize start
Scenario 4 — High Memory / Conserve Mode
- Check state and thresholds:
diagnose hardware sysinfo conserve get system performance status
- Find top consumers:
diagnose sys top-mem
- Check scan unit stats:
diagnose test application scanunitd 3
- Reduce session TTL to flush stale entries:
config system session-ttl set default 300 end - Restart scan unit to release memory (UTM resumes automatically):
diagnose sys scanunit restart
Scenario 5 — Slow Throughput
- Check CPU:
diagnose sys top 1 20 get system performance status
- Verify sessions have
npuflag (NP-offloaded):diagnose sys session filter dport 443 diagnose sys session list | grep flags
- Check NP drop counters:
diagnose npu np7 stats 0
- Check interface errors: Look for non-zero
diagnose netlink interface stats <intf>
rx_dropped,rx_errors,tx_dropped. - Run iPerf baseline:
diagnose traffictest run -c <iperf-server-ip>
Scenario 6 — User Auth Failure
- Test credentials directly:
diagnose test authserver ldap <server> <user> <pass>
- Enable fnbamd debug:
diagnose debug application fnbamd -1 diagnose debug enable
- Have user attempt authentication. Watch for LDAP bind errors, group membership failures, or RADIUS timeout messages.
- Check FSSO if using SSO:
diagnose debug authd fsso list diagnose debug authd fsso server-status
- Clean up:
diagnose debug disable
Use before sharing configs publicly or with support. The script below replaces sensitive values with anonymised placeholders.
Regex Patterns
| Pattern | Matches | Replacement |
|---|---|---|
set password ENC .* |
Encrypted passwords | set password ENC <REDACTED> |
set psksecret .* |
IPsec PSK | set psksecret <REDACTED> |
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b |
IPv4 addresses | <IP> |
set sn .* |
Serial numbers | set sn <SERIAL> |
([0-9a-fA-F]{2}:){5}… |
MAC addresses | <MAC> |
Python Sanitizer Script
#!/usr/bin/env python3
"""Sanitize FortiGate config for safe sharing."""
import re, sys, argparse
RULES = [
(r'(set (?:password|passwd)\s+ENC\s+)\S+', r'\1<REDACTED>'),
(r'(set psksecret\s+)\S+', r'\1<REDACTED>'),
(r'(set (?:secret|key|authkey)\s+)\S+', r'\1<REDACTED>'),
(r'(set sn\s+)\S+', r'\1<SERIAL>'),
(r'(set (?:hostname|alias)\s+)"?([^"\n]+)"?', r'\1"<HOSTNAME>"'),
(r'\b(\d{1,3}\.){3}\d{1,3}\b', '<IP>'),
(r'\b([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\b', '<MAC>'),
]
def sanitize(text):
for pattern, repl in RULES:
text = re.sub(pattern, repl, text)
return text
def main():
ap = argparse.ArgumentParser()
ap.add_argument('infile', nargs='?', default='-')
ap.add_argument('-o', '--out', default='-')
args = ap.parse_args()
src = open(args.infile) if args.infile != '-' else sys.stdin
dst = open(args.out, 'w') if args.out != '-' else sys.stdout
dst.write(sanitize(src.read()))
if __name__ == '__main__':
main()
Usage:
python3 sanitize.py config.conf -o safe_config.conf
REST API — Authentication
# 1. Create REST API admin: System → Administrators → REST API Admin
# 2. Copy the API key (shown only once)
# 3. Use Bearer token in every request:
curl -sk -H "Authorization: Bearer <api-key>" \
https://<fgt-ip>/api/v2/cmdb/system/status | python3 -m json.tool
Key REST API Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/v2/cmdb/system/status |
GET | Firmware version, serial, HA status |
/api/v2/cmdb/firewall/policy |
GET/POST/PUT/DELETE | CRUD on firewall policies |
/api/v2/cmdb/system/interface |
GET/PUT | Interface configuration |
/api/v2/monitor/firewall/session |
GET | Active session table |
/api/v2/monitor/vpn/ipsec |
GET | IPsec tunnel status |
/api/v2/monitor/system/ha-checksums |
GET | HA sync checksum state |
/api/v2/monitor/router/ipv4 |
GET | IPv4 routing table |
/api/v2/cmdb/router/static |
GET/POST | Static routes |
/api/v2/cmdb/log/setting |
GET/PUT | Log settings |
Python API Helper
#!/usr/bin/env python3
import requests, urllib3, json
urllib3.disable_warnings()
class FortiGate:
def __init__(self, host, token, verify=False):
self.base = f"https://{host}/api/v2"
self.s = requests.Session()
self.s.headers['Authorization'] = f"Bearer {token}"
self.s.verify = verify
def get(self, path, **params):
r = self.s.get(f"{self.base}{path}", params=params)
r.raise_for_status(); return r.json()
def put(self, path, data):
r = self.s.put(f"{self.base}{path}", json=data)
r.raise_for_status(); return r.json()
if __name__ == '__main__':
fgt = FortiGate('192.168.1.1', 'YOUR_API_TOKEN')
print(json.dumps(fgt.get('/cmdb/system/status'), indent=2))
Paramiko SSH
#!/usr/bin/env python3
import paramiko, time
def run_commands(host, user, password, commands, port=22):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, port=port, username=user, password=password,
look_for_keys=False, allow_agent=False)
shell = client.invoke_shell(width=220, height=50)
time.sleep(1); shell.recv(4096)
results = {}
for cmd in commands:
shell.send(cmd + '\n'); time.sleep(0.8)
out = b''
while shell.recv_ready(): out += shell.recv(65535)
results[cmd] = out.decode('utf-8', errors='replace')
client.close(); return results
if __name__ == '__main__':
cmds = ['get system status', 'diagnose sys top 1 3']
for cmd, out in run_commands('192.168.1.1', 'admin', '', cmds).items():
print(f"\n=== {cmd} ===\n{out}")
FortiOS CLI Auto-Script
# Upload: execute restore script tftp <filename> <tftp-ip>
# Or paste via GUI: System → Scripts
config system interface
edit port1
set alias "WAN1"
next
end
Ansible — fortinet.fortios Collection
---
- name: Configure FortiGate static route
hosts: fortigates
collections: [fortinet.fortios]
vars:
vdom: "root"
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false
ansible_httpapi_port: 443
tasks:
- name: Add static route
fortios_router_static:
vdom: "{{ vdom }}"
state: present
router_static:
seq_num: 1
dst: "10.10.0.0/16"
gateway: "192.168.1.254"
device: "port1"
Default FortiGate Service Ports
| Port | Protocol | Service | Direction |
|---|---|---|---|
| 22 | TCP | SSH management | Inbound to FGT |
| 23 | TCP | Telnet (disabled by default) | Inbound to FGT |
| 80 | TCP | HTTP management / captive portal | Inbound to FGT |
| 443 | TCP | HTTPS management / SSL-VPN | Inbound to FGT |
| 500 | UDP | IKE (IPsec) | Both |
| 514 | UDP/TCP | Syslog / FortiAnalyzer log | Outbound from FGT |
| 541 | TCP | FortiManager policy push | Inbound to FGT |
| 703 | UDP | HA heartbeat | Between FGT members |
| 1812 | UDP | RADIUS auth | Outbound from FGT |
| 1813 | UDP | RADIUS accounting | Outbound from FGT |
| 4500 | UDP | IKE NAT-T (IPsec) | Both |
| 5246 | UDP | CAPWAP control (FortiAP) | AP → FGT |
| 5247 | UDP | CAPWAP data (FortiAP) | AP → FGT |
| 8008/8009 | TCP | FortiGuard updates / licensing | Outbound from FGT |
| 8890 | TCP | FortiCloud / FortiGate Cloud | Outbound from FGT |
| 10443 | TCP | SSL-VPN (alternate port) | Inbound to FGT |
ICMP Type / Code Reference
| Type | Code | Meaning |
|---|---|---|
| 0 | 0 | Echo Reply (ping reply) |
| 3 | 0 | Destination Unreachable — Net Unreachable |
| 3 | 1 | Destination Unreachable — Host Unreachable |
| 3 | 3 | Destination Unreachable — Port Unreachable |
| 3 | 4 | Fragmentation Needed (MTU discovery) |
| 3 | 13 | Administratively Prohibited (firewall block) |
| 5 | 1 | Redirect — Redirect for Host |
| 8 | 0 | Echo Request (ping) |
| 11 | 0 | TTL Exceeded in Transit (traceroute hop) |
| 11 | 1 | Fragment Reassembly Time Exceeded |
Debug Flow Action Codes
| Action | Debug Flow String | Meaning |
|---|---|---|
| ACCEPT | iprope_in_check: check passed |
Policy matched and allowed |
| DENY | Denied by forward policy check |
Explicit deny or no matching allow policy |
| DROP | drop |
Silent drop (no ICMP unreachable sent) |
| SNAT | SNAT … to … |
Source NAT applied |
| DNAT | DNAT … to … |
Destination NAT (VIP) applied |
| OFFLOAD | offload to npu |
Session handed to hardware NP processor |
| RPF | reverse path check fail |
RPF check failed — asymmetric routing |
| IPS | drop by ips |
IPS engine blocked the packet |
IPsec Error Code Quick Reference
| Error | Cause | Fix |
|---|---|---|
NO_PROPOSAL_CHOSEN |
Encryption/hash/DH group mismatch | Align proposals on both peers |
INVALID_ID_INFORMATION |
Local/remote ID mismatch | Check localid / peer-id |
AUTHENTICATION_FAILED |
Wrong PSK or bad certificate | Re-verify PSK; check CA chain |
TS_UNACCEPTABLE |
Phase 2 subnet mismatch | Match Phase 2 selectors exactly |
INVALID_PAYLOAD_TYPE |
IKE v1 vs v2 mismatch | Set same IKE version both ends |
DPD timeout |
Peer unreachable or MTU issue | Check routing; try MTU 1400 |
Hardware Troubleshooting & HQIP
For detailed hardware troubleshooting steps including built-in diagnostics tools, refer to the Fortinet Community guide:
Technical Tip: RMA - HQIP test (with built-in FortiOS diagnostic commands)