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:

  1. An accept rule for your specific IPs.
  2. 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.