Created on
09-23-2024
04:33 AM
Edited on
06-29-2025
12:38 PM
By
Jean-Philippe_P
| Description |
This article describes a solution to set up VPNs for loopback interfaces in FortiOS versions before v7.0.11.
Interface-based IPsec was added in FortiOS v3.0. When this was first introduced, VRFs were not a feature, and the decision was made that if an IPsec interface is tied to a WAN interface, the route lookup for ESP in the IPsec layer could include the WAN interface index and therefore ensure that the route on that interface was found.
This solution has proved successful for many customers. However, it does not work if the IPsec interface is bound to a loopback with the goal that routing finds the most appropriate WAN interface. As VRF0 by default is utilized by management traffic, a default static route is added to the route table, which will take precedence for encapsulated traffic bound to a loopback interface.
|
| Scope | FortiGate. |
| Solution |
Example:
config system interface
edit "port2"
set vdom "root"
set vrf 30
set ip 192.168.1.2 255.255.255.0
set allowaccess ping
set type physical
set snmp-index 2
next
edit "port3"
set vdom "root"
set ip 10.254.3.254 255.255.255.0
set allowaccess ping
set type physical
set snmp-index 3
next
edit "port4"
set vdom "root"
set vrf 30
set ip 192.168.35.254 255.255.255.0
set allowaccess ping
set type physical
set snmp-index 4
next
edit "loopback1-vpn"
set vdom "root"
set vrf 30
set ip 10.206.0.1 255.255.255.0
set allowaccess ping
set type loopback
set snmp-index 15
next
edit "TEST_VPN"
set vdom "root"
set vrf 30
set type tunnel
set snmp-index 9
set interface "loopback1-vpn"
next
config vpn ipsec phase1-interface
edit "TEST_VPN"
set interface "loopback1-vpn"
set peertype any
set net-device disable
set proposal aes128-sha256 aes256-sha256 aes128-sha1 aes256-sha1
set remote-gw 10.106.0.1
set psksecret ENC BS4N729Il+L3jr1AAZy56wP9IGgASw4AzAW3j7UnRnhFhHLOgBYK1uZxXBFafV6aGqj
N/AoWzkgFO4NMGCPts7yyF4o61EXbimudHorOaXLIQ/qNzPXwZNGJKvADaFKUDAEBQGKT+K2sMlQwXi/SUn8iPGxrV7
xPmzrWC6rw0ViEEHQx00BhzvoQRmqS21vAiBIXTg==
next
config router static
edit 1
set gateway 10.254.3.1
set device "port3"
next
edit 2
set dst 172.16.0.1 255.255.255.255
set device "TEST_VPN"
next
edit 4
set gateway 192.168.1.1
set distance 5
set device "port2"
next
get router info routing-table all
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
* - candidate default
Routing table for VRF=0
S* 0.0.0.0/0 [10/0] via 10.254.3.1, port3, [1/0] <- Static route for VRF0.
C 10.254.1.0/24 is directly connected, port1
C 10.254.3.0/24 is directly connected, port3
Routing table for VRF=30
S* 0.0.0.0/0 [5/0] via 192.168.1.1, port2, [1/0] <- Static route for VRF30.
C 10.206.0.0/24 is directly connected, loopback1-vpn
S 172.16.0.1/32 [10/0] via TEST_VPN tunnel 10.106.0.1, [1/0]
C 192.168.1.0/24 is directly connected, port2
C 192.168.35.0/24 is directly connected, port4
For source traffic from port4 in VRF30, the flow trace shows the route found via port3 in VRF0 instead of port2 in VRF30, even though the default in VRF30 has a lower administrative distance.
diagnose debug flow filter addr 172.16.0.1
diagnose debug flow trace start 100
diagnose debug enable
id=20085 trace_id=1 func=print_pkt_detail line=5871 msg="vd-root:30 received a packet(proto=6, 192.168.35.1:20504->172.16.0.1:443) tun_id=0.0.0.0 from port4. flag [S], seq 2733273465, ack 0, win 29200"
id=20085 trace_id=1 func=init_ip_session_common line=6050 msg="allocate a new session-000004ad, tun_id=0.0.0.0"
id=20085 trace_id=1 func=vf_ip_route_input_common line=2605 msg="find a route: flag=04000000 gw-10.106.0.1 via TEST_VPN"
id=20085 trace_id=1 func=fw_forward_handler line=881 msg="Allowed by Policy-1:"
id=20085 trace_id=1 func=ipsecdev_hard_start_xmit line=669 msg="enter IPSec interface TEST_VPN, tun_id=0.0.0.0"
id=20085 trace_id=1 func=_do_ipsecdev_hard_start_xmit line=229 msg="output to IPSec tunnel TEST_VPN" <- Should flow via Tunnel interface...
id=20085 trace_id=1 func=esp_output4 line=844 msg="IPsec encrypt/auth"
id=20085 trace_id=1 func=ipsec_output_finish line=544 msg="send to 10.254.3.1 via intf-port3" <- Instead, a route via port1 default GW is seen.
To Stop Debug:
diagnose debug disable diagnose debug reset Packet capture shows the SYN packet forwarded correctly to the VPN interface.
diagnose sniffer packet any 'host 172.16.0.1' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[host 172.16.0.1]
14.663333 port4 in 192.168.35.1.20540 -> 172.16.0.1.443: syn 4021015288
14.663789 TEST_VPN out 192.168.35.1.20540 -> 172.16.0.1.443: syn 4021015288
15.715398 port4 in 192.168.35.1.20540 -> 172.16.0.1.443: syn 4021015288
15.715481 TEST_VPN out 192.168.35.1.20540 -> 172.16.0.1.443: syn 4021015288
However, when checking which interface ESP traffic is initiated on, it appears to be forwarded via port3 instead of port2:
diagnose sniffer packet any 'esp' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[esp]
29.546111 port3 out 10.206.0.1 -> 10.106.0.1: ESP(spi=0x04705e16,seq=0x23)
30.594988 port3 out 10.206.0.1 -> 10.106.0.1: ESP(spi=0x04705e16,seq=0x24)
Workaround:
get router info routing-table all
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
* - candidate default
Routing table for VRF=0
S <FGT HA>/32 [10/0] via 10.254.3.1, port3, [1/0] <- Specific routes via port1 for HA management traffic.
S <FMG IP>/32 [10/0] via 10.254.3.1, port3, [1/0] <- Specific routes via port1 for FortiManager management traffic.
S <FAZ IP>/32 [10/0] via 10.254.3.1, port3, [1/0] <- Specific routes via port1 for FortiAnalyzer management traffic.
C 10.254.1.0/24 is directly connected, port1
C 10.254.3.0/24 is directly connected, port3
Routing table for VRF=30
S* 0.0.0.0/0 [5/0] via 192.168.1.1, port2, [1/0]
C 10.206.0.0/24 is directly connected, loopback1-vpn
S 172.16.0.1/32 [10/0] via TEST_VPN tunnel 10.106.0.1, [1/0]
C 192.168.1.0/24 is directly connected, port2
C 192.168.35.0/24 is directly connected, port4
get router info routing-table all
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
* - candidate default
Routing table for VRF=0
S* 0.0.0.0/0 [10/0] via 10.254.3.1, port3, [1/0]
C 10.254.1.0/24 is directly connected, port1
C 10.254.3.0/24 is directly connected, port3
Routing table for VRF=30
S* 0.0.0.0/0 [5/0] via 192.168.1.1, port2, [1/0]
S 10.106.0.1/32 [10/0] via 192.168.1.1, port2, [1/0] <- Specific route for VPN remote gateway IP.
C 10.206.0.0/24 is directly connected, loopback1-vpn
S 172.16.0.1/32 [10/0] via TEST_VPN tunnel 10.106.0.1, [1/0]
C 192.168.1.0/24 is directly connected, port2
C 192.168.35.0/24 is directly connected, port4
The above 2 workarounds will result in the following flow:
diagnose debug flow filter addr 172.16.0.1
diagnose debug flow trace start 100
diagnose debug enable
id=20085 trace_id=36 func=print_pkt_detail line=5871 msg="vd-root:30 received a packet(proto=6, 192.168.35.1:20618->172.16.0.1:443) tun_id=0.0.0.0 from port4. flag [S], seq 3084778468, ack 0, win 29200"
id=20085 trace_id=36 func=init_ip_session_common line=6050 msg="allocate a new session-000017cd, tun_id=0.0.0.0"
id=20085 trace_id=36 func=vf_ip_route_input_common line=2605 msg="find a route: flag=04000000 gw-10.106.0.1 via TEST_VPN"
id=20085 trace_id=36 func=fw_forward_handler line=881 msg="Allowed by Policy-1:"
id=20085 trace_id=36 func=ipsecdev_hard_start_xmit line=669 msg="enter IPSec interface TEST_VPN, tun_id=0.0.0.0"
id=20085 trace_id=36 func=_do_ipsecdev_hard_start_xmit line=229 msg="output to IPSec tunnel TEST_VPN"
id=20085 trace_id=36 func=esp_output4 line=844 msg="IPsec encrypt/auth"
id=20085 trace_id=36 func=ipsec_output_finish line=544 msg="send to 192.168.1.1 via intf-port2" <- Traffic now exits via port2.
To stop the debug:
diagnose debug disable diagnose debug reset
diagnose sniffer packet any 'esp' 4 0
Using Original Sniffing Mode
interfaces=[any]
filters=[esp]
14.199569 port2 out 10.206.0.1 -> 10.106.0.1: ESP(spi=0x04705e16,seq=0x2c)
15.255492 port2 out 10.206.0.1 -> 10.106.0.1: ESP(spi=0x04705e16,seq=0x2d)
|
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.