Configuring FortiGate Local-In Policies: Hardening the Control Plane
Learn how to secure your FortiGate's control plane using local-in policies. Learn CLI configuration, handle auto-created rules, and restrict VPN access by geography.
While standard security profiles and firewall rules control the data plane—traffic flowing through the FortiGate—they don't protect the appliance itself. To control inbound traffic destined specifically for a FortiGate interface (the control plane), you need local-in policies.
Administrative access traffic (HTTPS, PING, SSH, etc.) can be partially controlled by allowing or denying services in the interface settings, or by configuring trusted hosts under an administrator profile. However, local-in policies give you granular control, allowing you to define source and destination addresses, incoming interfaces, and specific services.
Whether you need to lock down administrative access or secure services like VPNs, local-in policies are the proper tool for the job. You can define source addresses or address groups to restrict access, such as utilizing geographic-type addresses to block or allow entire geographic regions.
Operational Realities: What You Need to Know
Before jumping into the configuration, there are a few architectural quirks and operational realities you need to understand to avoid troubleshooting headaches later.
1. The GUI is Misleading
By default, there are no restrictions on local-in traffic. Starting in FortiOS 7.x, local-in policies are visible in the GUI (in older versions, you must enable it via System → Feature Visibility → Local-in Policy).
However, the GUI display is read-only and only shows default, auto-created rules. It will not display any custom rules you configure via the CLI. This discrepancy often confuses engineers into thinking their CLI-configured rules aren't working.
My advice: Forget about the GUI for local-in policies. Work exclusively in the CLI from the beginning.
2. Overriding Auto-Created Rules
The control plane listens for services like SSH, HTTPS, VPN, and routing protocols. Local-in policies sit directly in front of this control plane.
When you enable a service, the FortiGate automatically creates default rules. You cannot disable, delete, or manipulate these auto-created rules without disabling the service itself.
The custom rules we create on the CLI override (sit above) these default rules, but they do not remove them. Because the default action in rules is deny (if you see no action in a show output, assume deny), you must take the auto-created rules into account.
For example, configuring IPSec VPN opens UDP port 4500 and 500 to ALL. To restrict IPSec VPN to specific IPs, you need two rules:
- An accept rule for your specific IPs.
- A deny rule for ALL to UDP port 4500 and 500.
This prevents the traffic from falling through to the default auto-created allow rule.
3. VIPs Override Local-in Policies
Local-in policies do NOT control NAT or port-forwarded rules, known as Virtual IPs (VIPs). If you configure a port-forwarding VIP or a one-to-one NAT in your Security Rules, the FortiGate will process the Security Rules and entirely ignore the Local-in policy for those same IPs. Simply put: VIPs override Local-in policies.
4. Logging is Disabled by Default
By default, Local-in policy hits are not logged. If you are actively dropping traffic, you want to see it. You must navigate to Log Settings → Log All and ensure denied packets are logged. You can review these logs in the Local Traffic section.
Basic CLI Syntax Reference
Local-in policies are split into IPv4 (local-in-policy) and IPv6 (local-in-policy6). When configuring via CLI, you must specify the incoming interface, source/destination addresses, schedule, and service.
config firewall {local-in-policy | local-in-policy6}
edit <policy_number>
set intf <interface>
set srcaddr <source_address> [source_address] ...
set dstaddr <destination_address> [destination_address] ...
set action {accept | deny}
set service <service_name> [service_name] ...
set schedule <schedule_name>
set comments <string>
next
end
Practical Task: Restricting Site-to-Site VPN by Geography
Let's put this into practice. We need to restrict a FortiGate to only accept Site-to-Site VPN connections (IKE and ESP) from specific geographic locations. In this scenario, we only want to allow peers originating from Qatar and Sri Lanka (SL) on our WAN interface (port1).
Step 1: Create the Firewall Address Objects and Group
First, we define our geographic locations and bundle them into an address group.
config firewall address
edit "Qatar"
set type geography
set country "QA"
next
edit "SL"
set type geography
set country "LK"
next
end
config firewall addrgrp
edit "Allowed-Geography"
set member "Qatar" "SL"
next
end
Step 2: Create the Accept Rule
Next, we create the local-in policy to explicitly allow IKE and ESP from our newly created geographic group on the WAN interface.
config firewall local-in-policy
edit 1
set intf "port1"
set srcaddr "Allowed-Geography"
set dstaddr "all"
set action accept
set service "IKE" "ESP"
set schedule "always"
next
end
Step 3: Create the Deny Rule
Finally, we must block the services from everyone else to prevent the traffic from hitting the default allow rules that FortiOS generates when IPsec is configured.
config firewall local-in-policy
edit 99
set intf "port1"
set srcaddr "all"
set dstaddr "all"
set action deny
set service "IKE" "ESP"
set schedule "always"
next
end
Done. Now, this FortiGate will only answer to IPsec negotiations originating from Qatar and Sri Lanka.
Verification and Troubleshooting
Once applied, you'll want to verify your configuration and monitor traffic hitting your policies.
To view your active local-in policy configuration:
show firewall local-in-policy
To check the policy hit counts and confirm your rules are actively matching traffic, use the iprope diagnostic command (note that 00100001 targets the IPv4 local-in policy table):
diag firewall iprope show 00100001 policy-id
By mastering local-in policies, you ensure that the device protecting your network is, itself, properly protected.