Fortigate Best practices – CLI Examples (7.6)
Below is a hardened, modular baseline that merges your management/HA/monitoring/logging snippets with additional controls for loopback-VPN, strict local-in rules, and geo-fencing. Each block stands alone and can be applied independently. Citations point to where the Fortinet Best Practices guide aligns with the control.
Management (admin surface hardening)
Central identity for admin (LDAP/SAML) + MFA
Use LDAPS (not LDAP), least-privileged bind, or RADSEC for RADIUS or SAML.
enable MFA on admin accounts.
# Example LDAPS server (minimum hardening)
config user ldap
edit "ad-ldaps"
set server "dc01.example.com"
set cnid "sAMAccountName"
set dn "dc=example,dc=com"
set type regular
set username "CN=ldap-reader,OU=Svc,DC=example,DC=com"
set password ********
set secure ldaps
set port 636
next
end
# Map LDAP group to an admin profile
config system accprofile
edit "Ops-Admins"
set secfabgrp read-write
set sysgrp read-write
set fwgrp read-write
set loggrp read-write
next
end
config system admin
edit "ops-admins-sso"
set remote-auth enable
set accprofile "Ops-Admins"
set wildcard enable
set two-factor email
set email-to "[email protected]"
next
end
Example for SAML for Admin login – View the post –> Here
config vpn certificate remote
edit "EntraID-SSO-Admins"
set remote "-----BEGIN CERTIFICATE-----
MIIDijCCAnKgAwIBAgIEXXGa6TANBgkqhkiG9w0BAQsFADBbMScwJQYDVQQDDB5SZWdlcnkgU2Vs
Zi1TaWduZWQgQ2VydGlmaWNhdGUxIzAhBgNVBAoMGlJlZ2VyeSwgaHR0cHM6Ly9yZWdlcnkuY29t
MQswCQYDVQQGEwJVQTAgFw0yNTA5MjEwMDAwMDBaGA8yMTI1MDkyMTE3MTI0NFowTDEYMBYGA1UE
AwwPZ29vZC1qb2IudG8ueW91MSMwIQYDVQQKDBpSZWdlcnksIGh0dHBzOi8vcmVnZXJ5LmNvbTEL
MAkGA1UEBhMCVUEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPS1Qo5AJ7Fuw7TozG
Mu3vFnShXpkav3qzKbYlu6KhPHdY81Qgc5Sop/vk3+QusezrWKr1YYsusWWXMjvgX10IGI4CNM4l
CIpBl2irzfRUidw7Phxg/C9SfXKLzK0tFb0WN7VMbB6/4heR3EdjBDxl0WuWrIM8CjPNkGD+QX1C
YygUZum1g2TJo2pyz9mXRnZfFrNkrPbvayL30RmdLfOMdgyGfiwrALVLnBXN/mMBSk4T2OLxhljN
JS+duy1jJmrkjZmDyefGxKMf4+xqAgyJJgE99vNp+7dFvgirDab7lxEhT5DN+QP8ezzZhLw2vbEu
B1ajMAHi1GcQQiPfrQWNAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG
MB0GA1UdDgQWBBSWwTYTdCaXXZ9WnDrvCEuI4u8yDDAfBgNVHSMEGDAWgBSWwTYTdCaXXZ9WnDrv
CEuI4u8yDDANBgkqhkiG9w0BAQsFAAOCAQEAjTRYXUgD/kkpNJagn4kNMHyt13T0tckdfCSMbRky
GCjYrHNO37f51k1CG0qhh9iwPCVrGOngiRoLcDK+QvYpmx/DpI48PlaUgZXNt58l8Y+PwLV/0hmP
paLG7VNwV4gOxN0imNEitpMKorR6PZsjVB3SYeekzn1P07kwR/qrYn5fNlu280tQg5j8DMKklQSP
KLzxRanjSgdx8bWtNebtm+ELcArFvfR/DNuacQF64/Rub229lei1A4vAutdFDl4oGePm9ElKJFgJ
KYTHoeqrKgVmgOFWKQKpEruUPQA1DaVh5V6t9rS5Agru59GZK3y4E1YXFanLTBtaVc18ikN52Q==
-----END CERTIFICATE-----"
next
end
config system saml
set status enable
set default-login-page normal
set default-profile "super_admin"
set entity-id "http://192.168.1.1:1234/metadata/"
set idp-entity-id "https://sts.windows.net/b793f2e8-DDD-4e8d-9305-2e0c2178f9a1/"
set idp-single-sign-on-url "https://login.microsoftonline.com/b793f2e8-DDD-4e8d-9305-2e0c2178f9a1/saml2"
set idp-single-logout-url "https://login.microsoftonline.com/b793f2e8-DDD-4e8d-9305-2e0c2178f9a1/saml2"
set idp-cert "EntraID-SSO-Admins"
set server-address "192.168.1.1:1234"
end
Web/SSH ports, hostname/alias, LLDP (your snippet, kept modular)
config system global
set admin-port 8080
set admin-scp enable
set admin-sport 4443
set admintimeout 30
set alias "FortiGate01"
set hostname "FGT01"
set lldp-reception enable
set lldp-transmission enable
set timezone 20
end
Limit where admins can log in from (your snippet, + idle timeout & strong crypto)
config system admin
edit "admin"
set trusthost1 10.10.10.0 255.255.255.0
set accprofile "super_admin"
set password XXXXXXXXXX
next
edit "backup_user"
set trusthost1 10.10.10.10 255.255.255.255
set accprofile "super_admin_readonly"
set vdom "root"
set password XXXXXXXXXX
next
end
config system global
set admin-console-timeout 10
set strong-crypto enable
set ssl-static-key-ciphers disable
set dh-params 8192
end
API user with trust host
config system api-user
edit "apiuser"
set api-key XXXXXX
set accprofile "API_Profile"
set vdom "root"
config trusthost
edit 1
set ipv4-trusthost 192.168.188.0 255.255.255.0
next
end
next
end
DNS
Not harding, but use trusted DNS Sources for your firewall
config system dns
set primary 1.1.1.1
set secondary 8.8.8.8
set protocol cleartext dot doh
set server-hostname "globalsdns.fortinet.net"
set domain "fgt1800.local"
end
NTP
Not harding, but use trusted NTO Sources for your firewall. It is important that the time is correct across all devices.
config system ntp
set ntpsync enable
set type custom
set syncinterval 60
config ntpserver
edit 1
set server "dk.pool.ntp.org"
set ntpv3 disable
set authentication disable
set interface-select-method auto
next
end
set source-ip 0.0.0.0
set source-ip6 ::
set server-mode enable
set authentication disable
set interface "internal1" "internal2"
end
High Availability
Fortinet recommends HA for resilience; ensure unique group-id per L2 domain.
In a Fortinet FortiGate high availability (HA) cluster, the HA group ID determines the virtual MAC addresses (VMACs) for the interfaces. By default, all interfaces in a cluster use a shared VMAC, but this can be changed by assigning a unique group ID to prevent MAC address conflicts, especially if multiple clusters are on the same network segment.
config system ha
set group-id 0
set group-name "clu01"
set mode a-p
set password XXXX
set hbdev "ha1" 0
set sync-config enable
set gratuitous-arps enable
set ha-mgmt-status enable
config ha-mgmt-interfaces
edit 1
set interface "mgmt1"
set dst 0.0.0.0 0.0.0.0
set gateway 10.10.10.1
set gateway6 ::
next
end
set override enable
set priority 150
set monitor "ha1" "lacp_Inside" "lacp_outside"
set ha-direct disable
end
Monitoring
Fortinet highlights SNMPv3/NetFlow/sFlow for baselining and monitoring.
config system snmp sysinfo
set status enable
set description "FGTclu01"
set contact-info "Persons Name"
set location "Datacenter - Cluster"
end
config system snmp community
edit 1
set name "Anchor4143"
config hosts
edit 1
set ip 10.10.10.10 255.255.255.255
set ha-direct enable
next
edit 2
set ip 10.10.10.12 255.255.255.255
set ha-direct enable
next
edit 3
set ip 177.177.177.177 255.255.255.255
next
end
set query-v1-status disable
set trap-v1-status disable
set events cpu-high mem-low log-full intf-ip vpn-tun-up vpn-tun-down ha-switch ha-hb-failure ips-signature ips-anomaly av-virus av-oversize ...
next
end
config system snmp user
edit "Roster5647"
set notify-hosts 10.10.10.10
set security-level auth-priv
set auth-proto sha512
set auth-pwd xxxx
set priv-proto aes256
set priv-pwd xxxx
next
end
Logging
Fortinet: encrypt to FortiAnalyzer by default; secure channel for third-party logging/VPN if needed. Remember to enable per-policy logging.
config log syslogd setting
set status enable
set server "10.10.10.10"
set mode udp
set port 514
set facility local7
set source-ip "10.10.10.1"
set format cef
set priority default
set max-log-rate 0
set interface-select-method auto
end
config log syslogd filter
set severity information
set forward-traffic enable
set local-traffic enable
set multicast-traffic enable
set sniffer-traffic enable
set ztna-traffic enable
set anomaly enable
set voip enable
end
config log eventfilter
set event enable
set system enable
set vpn enable
set user enable
set router enable
set wireless-activity enable
set wan-opt enable
set endpoint enable
set ha enable
set security-rating enable
set fortiextender enable
set connector enable
set sdwan enable
set cifs enable
set switch-controller enable
end
# Repeat on all rules (example)
config firewall policy
edit 1
set logtraffic all
next
end
Local-In Policy Baseline (tight management & routing daemons)
Fortinet recommends restricting local services using local-in-policy and avoiding WAN admin.
Allow management only from defined subnets
# Define mgmt source(s)
config firewall address
edit "Mgmt-Nets"
set subnet 10.10.10.0 255.255.255.0
next
end
# Allow HTTPS/SSH only from Mgmt-Nets to mgmt port(s)
config firewall local-in-policy
edit 10
set intf "mgmt1"
set srcaddr "Mgmt-Nets"
set dstaddr "all"
set action accept
set service "HTTPS" "SSH"
set schedule "always"
set status enable
next
end
Deny OSPF/BGP on WAN by default; allow only explicit peers
# Explicit peers/routers if needed
config firewall address
edit "ISP-BGP-Peer"
set subnet 203.0.113.1 255.255.255.255
next
edit "Upstream-OSPF"
set subnet 203.0.113.2 255.255.255.255
next
end
# Allow only specific routing peers on WAN
config firewall local-in-policy
edit 20
set intf "wan1"
set srcaddr "ISP-BGP-Peer"
set dstaddr "all"
set action accept
set service "BGP"
next
edit 21
set intf "wan1"
set srcaddr "Upstream-OSPF"
set dstaddr "all"
set action accept
set service "OSPF"
next
edit 29
set intf "wan1"
set action deny
set service "BGP" "OSPF"
next
end
Geo-block management/VPN access on WAN
Fortinet supports Geo objects in local-in-policy; this is commonly used to fence IKE/SSL admin reachability.
# Denmark + Greenland only
config firewall address
edit "Geo-DK-GL"
set type geography
set country DN GL
next
end
# Permit IKE/HTTPS/SSH only from DK/GL; default deny after
config firewall local-in-policy
edit 40
set intf "wan1"
set srcaddr "Geo-DK-GL"
set dstaddr "all"
set action accept
set service "IKE" "HTTPS" "SSH"
set schedule "always"
next
edit 49
set intf "wan1"
set action deny
set service "IKE" "HTTPS" "SSH"
next
end
Loopback-Terminated VPN
Using a loopback for IKE/IPsec termination lets you apply local-in and Geo controls consistently and avoid changing peer configs when WAN links change. Ensure the loopback address is routable/advertised on the internet (e.g., via static/public route from ISP).
You can use NAT into the Loopback for the VPN usage also, if it is not possible to get a routed public ip to your firewall.
# 1) Create loopback for VPN endpoint
config system interface
edit "loopback-vpn"
set type loopback
set ip 198.51.100.10 255.255.255.255 # public /32 routed to you
next
end
# 2) Bind IPsec Phase1 to loopback
config vpn ipsec phase1-interface
edit "siteA-vpn"
set interface "loopback-vpn"
set peertype any
set proposal aes256-sha256
set dhgrp 21
set npu-offload enable
next
end
# 3) Local-in policy to fence IKE to loopback via WAN
config firewall local-in-policy
edit 60
set intf "wan1"
set srcaddr "Geo-DK-GL" # or use specific peers
set dstaddr "all"
set action accept
set service "IKE"
next
edit 69
set intf "wan1"
set action deny
set service "IKE"
next
end
# 4) Route return traffic (ensure ISP routes 198.51.100.10 to your WAN)
config router static
edit 1
set dst 0.0.0.0 0.0.0.0
set gateway 203.0.113.254
set device "wan1"
next
end
DoS protection for mgmt/VPN on WAN
Fortinet recommends enabling DoS policies to drop floods before heavier processing.
config firewall DoS-policy
edit 100
set interface "wan1"
config anomalies
edit "tcp_syn_flood"
set status enable
set log enable
set action block
next
edit "ike"
set status enable
set log enable
set action block
next
edit "https_flood"
set status enable
set log enable
set action block
next
end
next
end
Close “override” ports used by replacement messages (optional hardening)
If you run WebFilter/UTM and fail PCI scans due to 8008/8010/8015/8020 being probed, close them.
config webfilter fortiguard
set close-ports enable
end
# Or keep features but move to high ephemeral
config webfilter fortiguard
set ovrd-auth-port-http 38008
set ovrd-auth-port-https 38010
set ovrd-auth-port-https-flow 38015
set ovrd-auth-port-warning 38020
end
# Disable app replacement message (closes 8008 for AppCtrl)
config application list
edit "default"
set app-replacemsg disable
next
end
Secure password storage + encrypted backups
Fortinet recommends enabling private-data encryption and encrypting backups; 7.6.1+ uses generated keys—mind RMA/restore implications.
# Pre-7.6.1 (manual key) — read the doc before enabling in prod
config system global
set private-data-encryption enable
end
# Then follow prompts for 32-hex key at the console.
# Encrypted backup
execute backup config flash encrypted fgt.conf "<StrongPassphrase>"
Firmware hygiene, PSIRT, strong cipher posture
Keep current patch, review PSIRT advisories, use strong crypto (already set above), and avoid WAN admin.
# Auto-patch minor updates (standalone devices) – review in change control first
config system autoupdate schedule
set status enable
set day monday
set time 03:30
end
Policy hygiene (least privilege)
Fortinet stresses specific interfaces/objects, top-down specificity, avoid any-any, and VIP priority/match-vip behavior in deny rules.
# Example: deny first with match-vip, then allow
config firewall policy
edit 10
set name "Deny-from-HostX-to-VIP"
set srcintf "wan1"
set dstintf "dmz"
set srcaddr "HostX"
set dstaddr "WebVIP"
set action deny
set match-vip enable
set logtraffic all
next
edit 20
set name "Internet-to-WebVIP"
set srcintf "wan1"
set dstintf "dmz"
set srcaddr "all"
set dstaddr "WebVIP"
set action accept
set schedule "always"
set service "HTTPS"
set logtraffic all
next
end
Summary of what you gain
- Admin/API exposure reduced to known sources and geographies; WAN daemons fenced by default.
- Consistent mgmt/VPN reachability even when WAN changes (loopback model) where public routing permits.
- Lower attack surface (closed override ports, DoS filters, strong crypto).
- Auditable operations (policy logging, SNMPv3, time sync).
- Safer backups and predictable HA behavior.