This article describes the steps to configure IPsec tunnels from Hub to Spokes where 2 or more spokes have overlapping subnets.
Table of Contents
Scope
FortiOS.
Topology:
In this topology, spoke1 and Spoke2 have overlapping LAN subnets as 10.1.1.0/24. Whereas the hub has a LAN subnet of 172.16.24.0/24.
If IPsec tunnels are created without the steps below then the hub would have a route to 10.1.1.0/24 from both the tunnels and may create unwanted routing issues in the network.
Solution
In this case, one of the spoke needs to NAT the traffic to another subnet so that the hub can differentiate between the traffic on each spoke.
Spoke1 in this case will NAT the traffic of subnet 10.1.1.0/24 to subnet 10.8.8.0/24.
Configuration on Spoke1
Step 1: Create an IP pool on Spoke1 for subnet 10.8.8.0/24
Navigate to Policy and Objects > IP Pools > Create New.
CLI:
config firewall ippool edit "10.8.8.0" set startip 10.8.8.1 set endip 10.8.8.253 next end
This pool will be used later in the configuration to NAT the outgoing traffic on the tunnel.
Step 2: Create address object group for NAT subnet and Remote subnet:
config firewall address edit "ToHub-01_local_subnet_1" set uuid 0cd01c80-4a0a-51ef-7505-6b1be4991022 set allow-routing enable set subnet 10.8.8.0 255.255.255.0 next end config firewall address edit "ToHub-01_remote_subnet_1" set uuid 0cfe079e-4a0a-51ef-2e51-484123864b62 set allow-routing enable set subnet 172.16.24.0 255.255.255.0 next end config firewall addrgrp edit "ToHub-01_local" set uuid 0ce6c0b6-4a0a-51ef-f609-cb6510cf82de set member "ToHub-01_local_subnet_1" set allow-routing enable next end config firewall addrgrp edit "ToHub-01_remote" set uuid 0d1406c0-4a0a-51ef-1c29-99cb2d3dd2f3 set member "ToHub-01_remote_subnet_1" set allow-routing enable next end
Step 3: Create an IPsec tunnel using the wizard or CLI:
config vpn ipsec phase1-interface edit "ToHub-01" set interface "port1" set peertype any set net-device disable set proposal aes128-sha256 aes256-sha256 aes128-sha1 aes256-sha1 set remote-gw 10.0.1.1 set psksecret fortinet next end config vpn ipsec phase2-interface edit "ToHub-01" set phase1name "ToHub-01" set proposal aes128-sha1 aes256-sha1 aes128-sha256 aes256-sha256 aes128gcm aes256gcm chacha20poly1305 set src-addr-type name set dst-addr-type name set src-name "ToHub-01_local" set dst-name "ToHub-01_remote" next end
Step 4: Create a VIP on Spoke1 to DNAT the traffic from 10.8.8.0/24 to 10.1.1.0/24
Navigate to Policy and Objects > Virtual IPs > Create New.
Make sure to select the tunnel interface in the interface field.
CLI:
config firewall vip edit "ToInternal" set uuid a957d080-4a09-51ef-ad23-f92d9327b98e set extip 10.8.8.1-10.8.8.253 set mappedip "10.1.1.1-10.1.1.253" set extintf "ToHub-01" next end
Step 5: Create route to the destination:
config router static edit 2 set device "ToHub-01" set dstaddr "ToHub-01_remote" end
Step 6: Create firewall policies:
Outgoing policy with the IP pool created above:
config firewall policy edit 1 set srcintf "port2" set dstintf "ToHub-01" set action accept set srcaddr "all" set dstaddr "ToHub-01_remote" set schedule "always" set service "ALL" set nat enable set ippool enable set poolname "10.8.8.0" next end
Note that the srcaddr is set to ALL. It can be either set to ALL or the real LAN subnet i.e. 10.1.1.0/24 in this case.
Incoming policy with the VIP (‘ToInternal’) created above.
config firewall policy edit 2 set srcintf "ToHub-01" set dstintf "port2" set action accept set srcaddr "all" set dstaddr "ToInternal" set schedule "always" set service "ALL" next end
Configuration on Hub
Tunnel to Spoke1.
Hub needs a basic IPsec tunnel configuration where the local subnet is 172.16.24.0/24 and the remote subnet is the NAT subnet of the remote site i.e. 10.8.8.0/24 in this case.
Step 1: Create address groups for the remote and local subnets:
config firewall address edit "ToSpoke01_remote_subnet_1" set uuid 7c62fd20-4a09-51ef-2d7d-8a4a4f8327aa set allow-routing enable set subnet 10.8.8.0 255.255.255.0 next end config firewall address edit "ToSpoke01_local_subnet_1" set uuid 7c32565c-4a09-51ef-b490-07c9f1e4e800 set allow-routing enable set subnet 172.16.24.0 255.255.255.0 next end config firewall addrgrp edit "ToSpoke01_local" set uuid 7c4afcb6-4a09-51ef-19de-928137c00d99 set member "ToSpoke01_local_subnet_1" set comment "VPN: ToSpoke01 (Created by VPN wizard)" set allow-routing enable next end config firewall addrgrp edit "ToSpoke01_remote" set uuid 7c79a70a-4a09-51ef-bb60-d67b224b033e set member "ToSpoke01_remote_subnet_1" set comment "VPN: ToSpoke01 (Created by VPN wizard)" set allow-routing enable next end
Step 2: Create IPsec tunnel using the wizard or the CLI –
edit "ToSpoke01" set interface "port1" set peertype any set net-device disable set proposal aes128-sha256 aes256-sha256 aes128-sha1 aes256-sha1 set wizard-type static-fortigate set remote-gw 10.0.2.2 set psksecret Fortinet end edit "ToSpoke01" set phase1name "ToSpoke01" set proposal aes128-sha1 aes256-sha1 aes128-sha256 aes256-sha256 aes128gcm aes256gcm chacha20poly1305 set src-addr-type name set dst-addr-type name set src-name "ToSpoke01_local" set dst-name "ToSpoke01_remote" next
Step 3: Create route to the destination:
config router static edit 2 set device "ToSpoke01" set dstaddr "ToSpoke01_remote" next end
Step 4: Create firewall policies to allow the traffic:
config firewall policy edit 2 set srcintf "port2" set dstintf "ToSpoke01" set action accept set srcaddr "ToSpoke01_local" set dstaddr "ToSpoke01_remote" set schedule "always" set service "ALL" next end config firewall policy edit 3 set srcintf "ToSpoke01" set dstintf "port2" set action accept set srcaddr "ToSpoke01_remote" set dstaddr "ToSpoke01_local" set schedule "always" set service "ALL" next end
Configuration for the tunnel to spoke2
Step 1: Create address groups for the remote and local subnets:
config firewall address edit "ToSpoke-02_local_subnet_1" set uuid dd037ad2-4a0a-51ef-992b-b79a6e16af65 set allow-routing enable set subnet 172.16.24.0 255.255.255.0 next end config firewall address edit "ToSpoke-02_remote_subnet_1" set uuid dd2fbade-4a0a-51ef-8f78-1c1b8502973a set allow-routing enable set subnet 10.1.1.0 255.255.255.0 next end config firewall addrgrp edit "ToSpoke-02_local" set uuid dd18dae4-4a0a-51ef-eee3-751e89af4049 set member "ToSpoke-02_local_subnet_1" set comment "VPN: ToSpoke-02 (Created by VPN wizard)" set allow-routing enable next end config firewall addrgrp edit "ToSpoke-02_remote" set uuid dd45110e-4a0a-51ef-5f36-7db6e93cb756 set member "ToSpoke-02_remote_subnet_1" set comment "VPN: ToSpoke-02 (Created by VPN wizard)" set allow-routing enable next end
Step 2: Create an IPsec tunnel using the wizard or the CLI:
config vpn ipsec phase1-interface edit "ToSpoke-02" set interface "port1" set peertype any set net-device disable set proposal aes128-sha256 aes256-sha256 aes128-sha1 aes256-sha1 set wizard-type static-fortigate set remote-gw 10.0.3.2 set psksecret fortinet next end config vpn ipsec phase2-interface edit "ToSpoke-02" set phase1name "ToSpoke-02" set proposal aes128-sha1 aes256-sha1 aes128-sha256 aes256-sha256 aes128gcm aes256gcm chacha20poly1305 set src-addr-type name set dst-addr-type name set src-name "ToSpoke-02_local" set dst-name "ToSpoke-02_remote" next end
Step 3: Create a route to the destination:
config router static edit 4 set device "ToSpoke-02" set dstaddr "ToSpoke-02_remote" next end
Step 4: Create firewall policies to allow the traffic:
config firewall policy edit 4 set srcintf "port2" set dstintf "ToSpoke-02" set action accept set srcaddr "ToSpoke-02_local" set dstaddr "ToSpoke-02_remote" set schedule "always" set service "ALL" next end config firewall policy edit 5 set srcintf "ToSpoke-02" set dstintf "port2" set action accept set srcaddr "ToSpoke-02_remote" set dstaddr "ToSpoke-02_local" set schedule "always" set service "ALL next end
Configuration on Spoke2
For spoke2 it is a basic IPsec Site to-site tunnel to Hub:
Step 1: Create address groups for the remote and local subnets:
config firewall address edit "Spoke2ToHub_local_subnet_1" set uuid be72c370-4a0a-51ef-c957-29cebc142031 set allow-routing enable set subnet 10.1.1.0 255.255.255.0 next end config firewall address edit "Spoke2ToHub_remote_subnet_1" set uuid bea0cda6-4a0a-51ef-38d2-d819065c2f1f set allow-routing enable set subnet 172.16.24.0 255.255.255.0 next end config firewall addrgrp edit "Spoke2ToHub_local" set uuid be8ac5c4-4a0a-51ef-22b4-6846265abc18 set member "Spoke2ToHub_local_subnet_1" set comment "VPN: ToHub (Created by VPN wizard)" set allow-routing enable next end edit "Spoke2ToHub_remote" set uuid beb71cc8-4a0a-51ef-a264-ac44632b711f set member "Spoke2ToHub_remote_subnet_1" set comment "VPN: ToHub (Created by VPN wizard)" set allow-routing enable next end
Step 2: Create an IPsec tunnel using the wizard or the CLI:
edit "Spoke2ToHub" set interface "port1" set peertype any set net-device disable set proposal aes128-sha256 aes256-sha256 aes128-sha1 aes256-sha1 set remote-gw 10.0.1.1 set psksecret fortine next end config vpn ipsec phase2-interface edit "Spoke2ToHub" set phase1name "Spoke2ToHub" set proposal aes128-sha1 aes256-sha1 aes128-sha256 aes256-sha256 aes128gcm aes256gcm chacha20poly1305 set src-addr-type name set dst-addr-type name set src-name "Spoke2ToHub_local" set dst-name "Spoke2ToHub_remote" next end
Step 3: Create route to the destination:
config router static edit 2 set device "Spoke2ToHub" set dstaddr "Spoke2ToHub_remote" next
Step 4: Create firewall policies to allow the traffic:
config firewall policy edit 1 set srcintf "port2" set dstintf "Spoke2ToHub" set action accept set srcaddr "Spoke2ToHub_local" set dstaddr "Spoke2ToHub_remote" set schedule "always" set service "ALL" next edit 2 set srcintf "Spoke2ToHub" set dstintf "port2" set action accept set srcaddr "Spoke2ToHub_remote" set dstaddr "Spoke2ToHub_local" set schedule "always" set service "ALL" next end
Result
When LAN devices behind the hub in subnet 172.16.24.0/24 have to reach LAN devices on Spoke1, they will use destination IP such as 10.8.8.2. When this traffic is received on the spoke1, then it will get DNAT using the VIP and should reach the destination.
Example 1: Device on 172.16.24.2 trying to reach 10.1.1.2 on Spoke1 LAN will use 10.8.8.2.
Following is an example of the debug flow of this traffic on the spoke1 site:
Spoke-01 # 2024-07-24 16:18:56 id=65308 trace_id=1 func=print_pkt_detail line=5857 msg="vd-root:0 received a packet(proto=1, 172.16.24.2:49928->10.8.8.2:2048) tun_id=10.0.1.1 from ToHub-01. type=8, code=0, id=49928, seq=0." 2024-07-24 16:18:56 id=65308 trace_id=1 func=init_ip_session_common line=6043 msg="allocate a new session-0000077f, tun_id=10.0.1.1" 2024-07-24 16:18:56 id=65308 trace_id=1 func=get_new_addr line=1239 msg="find DNAT: IP-10.1.1.2, port-0(fixed port)" 2024-07-24 16:18:56 id=65308 trace_id=1 func=fw_pre_route_handler line=184 msg="VIP-10.1.1.2:49928, outdev-ToHub-01" 2024-07-24 16:18:56 id=65308 trace_id=1 func=__ip_session_run_tuple line=3445 msg="DNAT 10.8.8.2:8->10.1.1.2:49928" 2024-07-24 16:18:56 id=65308 trace_id=1 func=__vf_ip_route_input_rcu line=2001 msg="find a route: flag=00000000 gw-0.0.0.0 via port2" 2024-07-24 16:18:56 id=65308 trace_id=1 func=__iprope_tree_check line=535 msg="gnum-100004, use addr/intf hash, len=2" 2024-07-24 16:18:56 id=65308 trace_id=1 func=fw_forward_handler line=1000 msg="Allowed by Policy-2:" 2024-07-24 16:18:56 id=65308 trace_id=1 func=ip_session_confirm_final line=3090 msg="npu_state=0x100, hook=4"
Example 2: Device on 10.1.1.2 behind spoke1 trying to reach 172.16.24.2.
Following is an example of the debug flow of this traffic on the spoke1 site:
Spoke-01 # 2024-07-24 16:20:29 id=65308 trace_id=35 func=print_pkt_detail line=5857 msg="vd-root:0 received a packet(proto=1, 10.1.1.2:41480->172.16.24.2:2048) tun_id=0.0.0.0 from port2. type=8, code=0, id=41480, seq=0." 2024-07-24 16:20:29 id=65308 trace_id=35 func=init_ip_session_common line=6043 msg="allocate a new session-0000079d, tun_id=0.0.0.0" 2024-07-24 16:20:29 id=65308 trace_id=35 func=__vf_ip_route_input_rcu line=2001 msg="find a route: flag=00000000 gw-10.0.1.1 via ToHub-01" 2024-07-24 16:20:29 id=65308 trace_id=35 func=__iprope_tree_check line=535 msg="gnum-100004, use addr/intf hash, len=2" 2024-07-24 16:20:29 id=65308 trace_id=35 func=get_new_addr line=1239 msg="find SNAT: IP-10.8.8.32(from IPPOOL), port-41480" 2024-07-24 16:20:29 id=65308 trace_id=35 func=get_new_addr line=1239 msg="find DNAT: IP-10.8.8.2, port-0(fixed port)" 2024-07-24 16:20:29 id=65308 trace_id=35 func=fw_forward_handler line=1000 msg="Allowed by Policy-1: SNAT" 2024-07-24 16:20:29 id=65308 trace_id=35 func=ip_session_confirm_final line=3090 msg="npu_state=0x100, hook=4" 2024-07-24 16:20:29 id=65308 trace_id=35 func=__ip_session_run_tuple line=3432 msg="SNAT 10.1.1.2->10.8.8.32:41480" 2024-07-24 16:20:29 id=65308 trace_id=35 func=ipsecdev_hard_start_xmit line=662 msg="enter IPSec interface ToHub-01, tun_id=0.0.0.0" 2024-07-24 16:20:30 id=65308 trace_id=35 func=_do_ipsecdev_hard_start_xmit line=222 msg="output to IPSec tunnel ToHub-01 vrf 0"