Description
This article describes how to restrict IPsec VPN access to certain countries. Indeed, by default, dialup IPsec VPN’s are accessible to all public IP addresses on the Internet.
Scope
FortiGate.
Solution
FortiGates have built-in Security Profiles called 'Local-In' policies. These policies exist to permit access to various services and to support the inner workings of the FortiGate, including access to ports used by IPsec VPN.
In v7.2.4 and above, Local-in polices do not apply to IPsec tunnels by default. The handling of unknown ESP packets is done by the IKE process directly. If it is a requirement to block this traffic before it makes it to a process on the FortiGate, it is possible to enable a CLI option to have local-in policies take effect:
config system settings
set detect-unknown-esp disable
end
See more details in this document, EAP-TTLS support for IPsec VPN 7.4.3: Blocking unwanted IKE negotiations and ESP packets with a local-in policy.
By configuring a Local-In policy in conjunction with a Geography address object, it is possible to modify the default behaviour and restrict access to IPsec VPN to IP Addresses originating from certain countries.
The example below assumes that an IPsec VPN is already set up and accessible via a static IP Address on Interface WAN1 and that access is only required from VPN clients originating from IP addresses from a certain country.
(For this step, it is needed to connect to the Firewall’s command line using SSH).
Once connected via SSH, enter the following commands to create the Local-In policy.
config firewall local-in-policy
edit 1
set intf “wan1” <----- Or whichever interface the VPN is accessible via.
set srcaddr “Allowed_IP_Sec_IP” <----- The name given in 2).
set dstaddress “WAN_IP” <----- The name given in 1).
set action accept <----- Allow the connection.
set service “IKE” <----- This is a built in service for UDP port 500 and port 4500 as used by IPsec.
set schedule “always’ <----- Always allow the policy.
next
end
config firewall local-in-policy
edit 2
set intf “wan1” <----- Or whichever interface the VPN is accessible via.
set srcaddr “all” <----- In the first policy, there are specified trusted sources, in this policy source 'all' will be used.
set dstaddress “WAN_IP” <----- The name given 1).
set action deny <----- Deny the connection from the rest sources that are not present in the first local-in policy.
set service “IKE” <----- This is a built-in service for UDP port 500 and port 4500 as used by IPsec.
set schedule “always’ <----- Always allow the policy.
next
end
Note:
When configuring local-in policies, make sure that the first policy is to allow access from the trusted sources, and the second policy is to deny the rest sources that are not included in the first policy.
At the final, there are two local-in policies, 1th policy to allow the traffic from trusted sources, 2nd policy to deny service for the rest untrusted sources.
config firewall local-in-policy
edit 1
set intf "wan1"
set srcaddr "GEO-IP - Canada" "G - ALL PRIVATE ADDRESS RANGES" "GEO-IP - USA"
set dstaddr "WAN_IP"
set action accept
set service "IKE"
set schedule "always"
next
edit 2
set intf "wan1"
set srcaddr "all"
set dstaddr "WAN_IP"
set service "IKE"
set schedule "always"
next
end
Another way to design the local-in-policy is to use the 'srcaddr-negate'. This option acts as a logical 'NOT' or 'XOR' condition where the action of the policy will apply to all addresses except the address option in the 'srcaddr' field:
config firewall local-in-policy
edit 1
set intf "wan1"
set srcaddr "GEO-IP-ALLOWED"
set srcaddr-negate enable <--- Means the srcaddr "GEO-IP-ALLOWED" is the only object excluded from the deny action on this policy.
set dstaddr "WAN_IP"
set action deny
set service "IKE"
set schedule "always"
next
end
To verify that all works as expected:
diagnose debug disable
diagnose debug reset
diagnose debug flow filter clear
diagnose debug flow show function-name enable
diagnose debug flow filter daddr x.x.x.x <----- x.x.x.x will be the WAN1 IP address.
diagnose debug flow filter port 500
diagnose debug flow trace start 100
diagnose debug enable
When traffic is blocked, debug output will be visible with the message:
msg="iprope_in_check() check failed on policy 2, drop"
To disable debug:
diagnose debug disable
diagnose debug reset
diagnose debug flow filter clear
The packet sniffer should only show that there is incoming traffic from blocked IPs and no response from FortiGate:
diagnose sniff packet any 'host <blocked client public IP> and host <WAN IP> and port 500' 4 0 l
To stop the sniffer in the end, press Ctrl + C.
Note: After v7.6.1+, local-in policies can not be configured with individual SD-WAN member interfaces but must be configured with the SD-WAN zone.
For more information, see Troubleshooting Tip: Local-in, Central-SNAT, DoS policies etc are missing after upgrade to FortiOS v....
The Fortinet Security Fabric brings together the concepts of convergence and consolidation to provide comprehensive cybersecurity protection for all users, devices, and applications and across all network edges.
Copyright 2025 Fortinet, Inc. All Rights Reserved.