FORTINET CERTIFICATION · LAB NOTES
One entry per vocab word or function, going deeper than the study guide can. Every entry gets a plain definition, the mechanism underneath it, and a real packet-by-packet walkthrough — because the exam tests whether you can trace a packet, not whether you can recite a term.
RPF is an anti-spoofing check. For every incoming packet, before the FortiGate does anything else with it, the kernel asks one question: "If I wanted to send a reply back to this packet's source address, would it leave through the same interface this packet just arrived on?" If the answer looks wrong, the packet is dropped — because a source address that shouldn't plausibly be reachable from that interface is a strong sign it's spoofed, or that something is misrouted.
| Loose / Feasible (default) | Strict | |
|---|---|---|
| Check performed | Does any route to the source exist, out any interface? | Is the best route to the source out the same interface the packet arrived on? |
| CLI | config system settings → default, nothing to set | config system settings → set strict-src-check enable |
| Plays well with SD-WAN / multiple WANs? | Yes | Often no — see the trap below |
Loose (feasible) is the FortiGate default. It only asks "is this source reachable at all," not "is it reachable this way." That single word — any vs same — is the entire difference between the two modes.
RPF is a kernel-level routing check, not a firewall policy. It runs early — right after the packet is accepted on an interface, before session lookup and long before any firewall policy is evaluated. That ordering is exactly why a failed RPF check is a routing problem, never a policy problem, no matter how tempting it is to go check the policy first.
diagnose debug flow filter addr 192.0.2.77
diagnose debug flow show function-name enable
diagnose debug flow trace start 100
diagnose debug enable
# look for this line in the output:
reverse path check fail, dropreverse path check fail, drop in debug flow means RPF, full stop. It is not a sign of a missing firewall policy, a bad NAT rule, or a security profile block — those all produce different debug-flow lines. If you see this line, go straight to the routing table, not the policy list.
This is the scenario that actually costs people points, because everything else about the configuration is correct. A dual-ISP FortiGate, one internal server, one outbound API call.
ISP-A (203.0.113.0/30)
|
+-------[port1]-------+
| |
10.10.10.50 --[port2]-- LAB-FW1 | default routes:
(LAN server) | | 0.0.0.0/0 via port1 distance 10
| | | 0.0.0.0/0 via port3 distance 20
+-------[port3]-------+
|
ISP-B (198.51.100.0/30)
Destination: SaaS API at 192.0.2.77
PBR rule: traffic to 192.0.2.0/24 forwards out port3 (cost reasons)
strict-src-check: ENABLEDNote the trap already baked into the topology: a policy route (PBR) sends this specific destination out port3. Policy routes change where a packet is forwarded. They do not touch the routing table (RIB) that RPF reads. The RIB still says the best path to anything in 0.0.0.0/0 — including 192.0.2.77 — is port1, because that route has the lower administrative distance.
10.10.10.50 opens a session to 192.0.2.77:443. The SYN arrives on port2. No RPF concern here — port2 is the ingress interface for the LAN, and the source is internal.192.0.2.0/24 and forwards the SYN out port3 instead of the default port1. SNAT overload rewrites the source to 198.51.100.1 (port3's public IP). This is a forwarding decision — the RIB is untouched.198.51.100.1, the internet routes the reply straight back to that address — which means it lands on port3. Symmetric at the IP layer, no surprise yet.port3. RPF check runs: source is 192.0.2.77, ingress interface is port3. The kernel looks up 192.0.2.77 in the routing table (not the PBR table) — best match is the default route via port1, distance 10. Ingress interface (port3) does not match the best-route interface (port1).
STRICT: FAIL LOOSE: PASS
reverse path check fail, drop. Under loose RPF it passes, because a route to 192.0.2.77 exists (via port1), and loose mode doesn't care that it's not the same interface the packet arrived on.Under strict RPF the session just hangs and times out. NAT is right, the PBR rule is right, the firewall policy is right — none of it matters, because the packet never gets that far. This is the classic exam scenario: "a policy route works fine until strict RPF is enabled, then traffic through it silently breaks." The fix is either leave strict-src-check disabled (the default, and the correct choice whenever SD-WAN, PBR, or multiple WAN links are in play), or add a matching static route for that destination via port3 so the RIB agrees with the PBR decision and the two interfaces line up again.
This is exactly why loose/feasible is the FortiGate default and why the exam expects you to know it. Strict RPF is a deliberate, narrow hardening option for topologies where every path really is expected to be symmetric — not something you turn on casually on a box running SD-WAN.
get router info routing-table all # what RPF actually consults diagnose firewall proute list # the policy routes RPF does NOT consult get system settings | grep strict-src-check diagnose sniffer packet port3 'host 192.0.2.77' 4 0 a
If routing-table all shows a lower-distance default route out a different interface than the one your PBR or SD-WAN rule is using, and strict-src-check is enable, that mismatch is the outage. No amount of staring at the firewall policy or the NAT rule will find it.
config system settings → set strict-src-check enable.reverse path check fail, drop.A Performance SLA is a continuous, per-link health check. It doesn't just ask "is this WAN interface up" — it asks "is this WAN interface good enough, right now, for the traffic I want to send over it." An SD-WAN member can be fully up and routable and still get skipped by an SLA-gated rule, exactly as if it were down, because it's too slow, too jittery, or dropping too many probes.
| Metric | What it actually captures | Typical threshold |
|---|---|---|
| Latency | Round-trip time of the probe packet | e.g. ≤150 ms for voice |
| Jitter | How much that RTT varies probe to probe | e.g. ≤30 ms for voice |
| Packet loss | % of probes that got no reply at all | e.g. ≤1% |
The three required SLA metrics are latency, jitter, and packet loss. Bandwidth is an optional fourth criterion, measured separately and used mainly by the Maximize Bandwidth (SLA) strategy rather than by the health check itself.
| Protocol | Notes |
|---|---|
| Ping (ICMP) | Simplest to stand up. Least trustworthy — many ISPs rate-limit or deprioritize ICMP, so it can report a healthier link than the real application traffic actually experiences. |
| HTTP / HTTPS | Round-trips against a real web server, so it reflects TCP/application-layer handling rather than just ICMP. |
| DNS | Round-trips a DNS resolution — useful when the WAN is mainly serving DNS-dependent traffic. |
| TCP-echo / UDP-echo | Fortinet-defined echo probes. Need a responder on the far end (another FortiGate, or FortiOS's own probe-response service). |
| TWAMP | RFC 5357 two-way active measurement. Timestamps both directions independently, so it's the most accurate protocol for jitter specifically. Needs a TWAMP reflector configured on the far end. |
config system sdwan
config health-check
edit "voip-sla"
set server "203.0.113.50" # probe target / reflector
set protocol twamp
set interval 500 # ms between probes
set failtime 5 # consecutive fails to mark down
set recoverytime 5 # consecutive passes to mark back up
config sla
edit 1 # this is "SLA target 1" — rules reference this id
set latency-threshold 150
set jitter-threshold 30
set packetloss-threshold 1
next
end
set members 1 2 # which SD-WAN members this check applies to
next
end
endTypical FortiOS defaults are interval 500, failtime 5, recoverytime 5 — so, roughly, 2.5 seconds of consistently bad probes to fail a link out, and another 2.5 seconds of consistently good probes to bring it back. Voice-sensitive deployments often tighten this; bulk-data links often loosen it.
| Strategy | What it actually does |
|---|---|
| Lowest Cost (SLA) | Among members meeting the target, picks the one with the lowest configured cost (priority). The usual production default. |
| Best Quality | Among members meeting the target, ranks by one or more measured link-cost factors (latency, jitter, packet loss) and picks the best-scoring one. |
| Maximize Bandwidth (SLA) | Weighted-ECMPs traffic across every member meeting the target, proportional to each member's configured bandwidth. |
ISP-A (port1, cost 10)
|
10.20.30.0/24 --[port2]-- FGT1
(VoIP phones) |
[port3]
ISP-B (port3, cost 20)
Health-check "voip-sla": TWAMP probe to 203.0.113.50 every 500 ms
SLA target 1: latency <=150ms, jitter <=30ms, loss <=1% (members: port1, port3)
SD-WAN Rule "VoIP-to-HQ": src 10.20.30.0/24, dst app SIP/RTP
strategy: Lowest Cost (SLA), SLA target 1port1 and port3 pass every threshold in SLA target 1 on every probe cycle. Lowest Cost (SLA) picks the cheapest of the two that qualifies — port1, cost 10. Every new SIP call egresses port1.interval 500 and failtime 5, the health check needs 5 consecutive failing probes — 2.5 seconds — before it acts. This isn't instant, and that's intentional: a single slow probe shouldn't flap a link.port1 flips to "alive, NOT meeting SLA target 1." Nothing changed at the routing level — get router info routing-table all still lists the port1 default route exactly as before. This is a health-check state change, not a link-down event.port1 stay on port1 — SD-WAN doesn't relocate an established session mid-call. Any call placed from this moment on is (re-)evaluated fresh: port1 no longer qualifies, so Lowest Cost (SLA) selects the next-cheapest qualifying member, port3.recoverytime 5, another 2.5 s), port1 flips back to "meeting SLA" and becomes eligible again for the next new call. Calls already running on port3 are not moved back — SD-WAN never migrates an in-progress session either direction.Seeing a member fail an SLA and assuming the ISP link "went down" is the wrong read — and the classic wrong answer on exhibits. diagnose sys sdwan member and the routing table both still show it alive. The correct read: it's alive, it just failed the SLA gate for that rule, which is a normal, self-healing, per-probe-cycle event — not an outage.
diagnose sys sdwan health-check status voip-sla # measured latency/jitter/loss + pass/fail per SLA id, per member diagnose sys sdwan member # alive/dead, cost, configured bandwidth, per member diagnose sys sdwan service <rule-id> # which interface a rule is choosing right now, and why get router info routing-table all # confirms the route is still present during an SLA fail
If a "why did my VoIP quality dip" ticket lines up with a window where health-check status shows port1 failing SLA target 1, that's the whole story — no policy, NAT, or firewall change needed to explain it.
interval × failtime; recovery speed ≈ interval × recoverytime.diagnose sys sdwan health-check status <name> is the command that shows the actual measured numbers and pass/fail per SLA id.Full (deep) SSL inspection is a genuine, deliberate man-in-the-middle. The FortiGate doesn't peek at an encrypted stream — it terminates the client's TLS handshake itself, decrypts the traffic in RAM, inspects the real plaintext, then opens its own separate TLS session to the real server and re-encrypts on the way out. Two fully independent TLS tunnels exist for what looks to the user like one connection: client↔FortiGate, and FortiGate↔server.
| Certificate inspection | Full (deep) inspection | |
|---|---|---|
| What FortiGate sees | SNI + the server's real certificate CN, from the handshake headers only | The complete decrypted payload |
| Decryption happens? | No — the handshake passes through untouched | Yes — two independently terminated TLS sessions |
| Client must trust FortiGate's CA? | No | Yes |
| Enables | Web filter by hostname only | AV, IPS, DLP, app control, and full URL filtering over HTTPS |
Client 10.10.10.50 on the LAN browses to https://app.example.com. The matching firewall policy has a security profile whose SSL/SSH inspection profile is set to deep-inspection, re-signing CA Fortinet_CA_SSL.
app.example.com) toward the real server's IP. The FortiGate intercepts it — it does not forward this handshake through unmodified.app.example.com, sending a normal ClientHello of its own and validating the real server's certificate chain — exactly like any TLS client would.CN=app.example.com on the fly, signed by its configured re-signing CA, Fortinet_CA_SSL.Fortinet_CA_SSL root is already installed and trusted on the client, the browser accepts it without any warning. Two independent TLS tunnels now exist.If step 2 finds the real server's certificate invalid instead (expired, self-signed, wrong hostname), the FortiGate deliberately re-signs the substitute leaf with Fortinet_CA_Untrusted rather than Fortinet_CA_SSL — on purpose, so the browser warning still reaches the user. Silently hiding a genuinely bad certificate behind a trusted one would be a security regression, not a convenience.
Certificate pinning and HSTS break this, no matter how correctly it's configured. A pinning app (common in banking apps, and in OS-level services like Windows Update or Apple's update channel) doesn't trust the OS/browser certificate store at all — it hardcodes the real server's key or chain and rejects anything else outright, including a perfectly validly-signed substitute from a CA the device already trusts. Installing Fortinet_CA_SSL everywhere does not fix this. The correct answer on an exhibit is always an SSL exemption for that specific destination or category — never "turn off inspection." Finance and Health categories are exempted by default for exactly this reason.
Every certificate object — the re-signing CA, imported CAs, server/leaf certificates with their private keys, peer certs — is managed under config vpn certificate (local, ca, remote), even when it has nothing to do with a VPN. The SSL inspection profile just references a cert name that lives in that tree by set caname. Also know the distinction between a CA certificate with a private key (used to re-sign traffic) and a plain server certificate (used for the admin GUI or SSL VPN) — different object, different purpose, common exhibit trap.
config vpn certificate local
show # local certs — includes the re-signing CA's cert+key
end
config vpn certificate ca
show # trusted CA roots
end
config firewall ssl-ssh-profile
edit "deep-inspection"
show # confirm mode, caname, untrusted-caname, exemptions
next
enddiagnose debug application wad -1 # WAD is the proxy that terminates both TLS legs diagnose test application wad 5 # WAD process status / stats diagnose sys session list # proxy-based deep inspection: look for TWO session # entries for one logical browser connection — # client<->FortiGate and FortiGate<->server, because # WAD genuinely terminates both sides independently
Related knobs worth knowing under config firewall ssl-ssh-profile: set untrusted-caname (which CA re-signs an invalid server cert), set allow-invalid-server-cert, and set expired-server-cert — these control exactly how the FortiGate reacts when the real server's certificate is the one that's broken.
Fortinet_CA_SSL; an invalid server cert gets re-signed with Fortinet_CA_Untrusted instead, on purpose.config vpn certificate, not under the inspection profile itself.