FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
gmanea
Staff
Staff

Description
This article describes how to configure VXLAN over IPsec in Hub and Spoke topology, where there is single subnet in different locations and to keep communication between Spoke and HUB and between Spokes.

This will use single dynamic IPsec tunnel on HUB.
All spokes are connecting to HUB via this dynamic tunnel.
VXLAN interfaces (VTEP) will be bounded over this tunnel on HUB.

Because of this, this is applicable on the units that are running 6.4 and higher.
In this example, VXLAN will be configured in way, that it will allow configuration between all units.
It means that the spoke1 will be able to reach spoke2 internal network.
All traffic from spoke to spoke will be always routed via HUB.


Solution
Topology.



 
 
Configuration.

HUB.

Ipsec configuration.
# config vpn ipsec phase1-interface
    edit "VXLAN-IPSEC"
        set type dynamic
        set interface "port1"
        set mode aggressive
        set peertype any
        set net-device disable
        set proposal des-md5 des-sha1
        set dpd on-idle
        set xauthtype auto
        set authusrgrp "Spokes"
        set psksecret secretpassword
        set dpd-retryinterval 60
    next
end
# config vpn ipsec phase2-interface
    edit "vxlan-phase2"
        set phase1name "VXLAN-IPSEC"
        set proposal null-md5
    next
end
# config system interface
    edit "VXLAN-IPSEC"
        set vdom "root"
        set ip 169.254.10.1 255.255.255.255
        set type tunnel
        set remote-ip 169.254.10.254 255.255.255.0
        set snmp-index 13
        set interface "port1"
    next
end
It is possible to use only PSK authentication if needed.
Net-device on the HUB needs to be disabled.
 
Firewall policy is needed to active IPsec tunnel:
# config firewall policy
    edit 1
        set name "ActiveIpsec”
        set srcintf "VXLAN-IPSEC"
        set dstintf "VXLAN-IPSEC"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
    next
end
VXLAN configuration.
# config system vxlan
    edit "Vxlan2"
        set interface "VXLAN-IPSEC"
        set vni 2
        set remote-ip "169.254.10.3"
    next
    edit "Vxlan1"
        set interface "VXLAN-IPSEC"
        set vni 1
        set remote-ip "169.254.10.2"
    next
end
# config system switch-interface
    edit "VXLAN_SWITCH"
        set vdom "root"
        set member "port2" "Vxlan1" "Vxlan2"
    next
end
For each pair HUB-SpokeX it is necessary to separate VNI.
This VNI needs to be the same.
o between HUB and Spoke1 VNI is 1, between HUB and spoke2 VNI is 2.
On HUB, only option how to bound all interfaces together is software switch.
Recommending keep intra-switch-policy implicit.
Port2 is LAN interface behind HUB.
If needed, it is possible to configure IP address on software switch.

Spoke1.

IPsec configuration.
# config vpn ipsec phase1-interface
    edit "VXLAN-IPSEC"
        set interface "port1"
        set mode aggressive
        set peertype any
        set net-device disable
        set proposal des-md5 des-sha1
        set localid "Spokes"
        set xauthtype client
        set authusr "fgta"
        set authpasswd secretuserpassowrd
        set remote-gw 172.16.0.1
        set psksecret secretpassowrd
    next
end
# config vpn ipsec phase2-interface
    edit "phase2Vxlan"
        set phase1name "VXLAN-IPSEC"
        set proposal null-md5
        set src-subnet 169.254.10.2 255.255.255.255 <<< Tunnel IP address
    next
end
# config system interface
    edit "VXLAN-IPSEC"
        set vdom "root"
        set ip 169.254.10.2 255.255.255.255
        set type tunnel
        set remote-ip 169.254.10.1 255.255.255.0
        set snmp-index 13
        set interface "port1"
    next   
end
Important is to make sure, the Tunnel has configured correct IP address.
Again, similar to HUB, firewall policy is needed to activate the IPsec tunnel.
 
VXLAN configuration.
# config system vxlan
    edit "Vxlan1"
        set interface "VXLAN-IPSEC"
        set vni 1
        set remote-ip "169.254.10.1”
    next
end
# config system switch-interface
    edit "VXLAN_SWITCH"
        set vdom "root"
        set member "port2" "Vxlan1"
    next
end
On spoke, there is flexibility to use software switch or Virtual-wire pair.
Based on this, if  Virtual-wire pair is chosen, it is necessary to have virtual-wire pair policy between LAN interface and VXLAN interface.
If software switch is chosen, if intra-switch-policy is implicit, no firewall policy is needed.
If intra-switch-policy is explicit, additional firewall policy between LAN interface and VXLAN interface is needed.

Spoke2.

Configuration for Spoke2 is the same as Spoke1, except couple of things.
Tunnel IP address needs to be correct, in our case spoke2 has 169.154.10.3. Based on this adjust src-subnet in phase2.
 
For VXLAN part, VNI will be 2 to be matching HUB’s configuration.
# config system vxlan
    edit "Vxlan1"
        set interface "VXLAN-IPSEC"
        set vni 2
        set remote-ip "169.254.10.1"
    next
end
# config system switch-interface
    edit "VXLAN_SWITCH"
        set vdom "root"
        set member "port2" "Vxlan1"
    next
end
Verification.

Client1 behind spoke1 has IP address 192.168.1.100.
Client2 behind spoke2 has IP address 192.168.1.200.
As a result of the configuration, if everything is configured correctly, Client1 should be able to reach Client2.
The traffic will go from Spoke1 to HUB and to Spoke2.
root@client1:~# ping 192.168.1.200                                                                                                                                                                                 
PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.                                                                                                                                                           
64 bytes from 192.168.1.200: icmp_seq=1 ttl=64 time=4.84 ms                                                                                                                                                        
64 bytes from 192.168.1.200: icmp_seq=2 ttl=64 time=3.89 ms                                                                                                                                                        
64 bytes from 192.168.1.200: icmp_seq=3 ttl=64 time=2.35 ms                                                                                                                                                        
^C                                                                                                                                                                                                                 
--- 192.168.1.200 ping statistics ---                                                                                                                                                                              
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
                                                                                                                                                 

Sniffer from each unit:
Spoke1# diag sniffer packet any "host 192.168.1.200 and icmp" 4 0 l
Using Original Sniffing Mode
interfaces=[any]
filters=[host 192.168.1.200 and icmp]
2021-05-12 04:49:52.326749 port2 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.326906 Vxlan1 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.329074 Vxlan1 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:52.329088 port2 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:59.526139 port2 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:59.526247 Vxlan1 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:59.527629 Vxlan1 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:59.527651 port2 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply

HUB #  diag sniffer packet any "host 192.168.1.200 and icmp" 4 0 l

Using Original Sniffing Mode.
interfaces=[any]
filters=[host 192.168.1.200 and icmp]
2021-05-12 04:49:52.918545 Vxlan1 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.918569 Vxlan2 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.919803 Vxlan2 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:52.919808 Vxlan1 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:50:00.117684 Vxlan1 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:50:00.117697 Vxlan2 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:50:00.118503 Vxlan2 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:50:00.118507 Vxlan1 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply

Spoke2 #  diag sniffer packet any "host 192.168.1.200 and icmp" 4 0 l
Using Original Sniffing Mode
interfaces=[any]
filters=[host 192.168.1.200 and icmp]
2021-05-12 04:49:52.665259 Vxlan1 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.665283 port2 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:52.665727 port2 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:52.665731 Vxlan1 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:59.864173 Vxlan1 in 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:59.864186 port2 out 192.168.1.100 -> 192.168.1.200: icmp: echo request
2021-05-12 04:49:59.864529 port2 in 192.168.1.200 -> 192.168.1.100: icmp: echo reply
2021-05-12 04:49:59.864535 Vxlan1 out 192.168.1.200 -> 192.168.1.100: icmp: echo reply

 

 

Contributors