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.
GeorgeZhong
Staff
Staff
Article Id 307683
Description

This article describes the potential routing issue on the Dialup hub caused by the routing behavior change in v7.0.

This issue often happens after upgrading the firmware version from v6.x to v7.0 onwards.

Scope

FortiGate v7.0.0+, Dialup VPN, static route.

Solution

The below topology is an example. Both Spoke-1 and Spoke-2 connect to the Hub via the Dialup IPsec VPN:

 

GeorgeZhong_0-1711946914940.png

 

Static routes are manually configured on the hub and each spoke is linked to the IPsec tunnel.

 

Hub:

 

config router static

    edit 1

        set dst 10.11.0.0 255.255.0.0

        set device "Dialup"

    next

        edit 2

            set dst 10.30.0.0 255.255.0.0

            set device "Dialup"

        next

    end

 

Spoke:

 

config router static

    edit 1

        set device "To_hub_test"

    next

end

 

In v6.4, the routing table should be like below. The next-hop IP 198.19.18.254 is the remote-ip configured on the tunnel interface.

 

S       10.11.0.0/16 [10/0] via 198.19.18.254, Dialup

S       10.30.0.0/16 [10/0] via 198.19.18.254, Dialup

 

Same as spoke site:

 

S       0.0.0.0/0 [10/0] via 198.19.18.1, To_hub_test

 

By doing the ping test from Hub to Spoke, it works:

 

c3po-kvm23 # execute ping 10.11.0.221

PING 10.11.0.221 (10.11.0.221): 56 data bytes

64 bytes from 10.11.0.221: icmp_seq=0 ttl=255 time=1.4 ms

64 bytes from 10.11.0.221: icmp_seq=1 ttl=255 time=0.3 ms

64 bytes from 10.11.0.221: icmp_seq=2 ttl=255 time=0.2 ms

64 bytes from 10.11.0.221: icmp_seq=3 ttl=255 time=0.3 ms

64 bytes from 10.11.0.221: icmp_seq=4 ttl=255 time=0.3 ms

 

--- 10.11.0.221 ping statistics ---

5 packets transmitted, 5 packets received, 0% packet loss

round-trip min/avg/max = 0.2/0.5/1.4 ms

 

However, when upgrading to v7.0 onwards, it stops working:

 

c3po-kvm23 # execute ping 10.11.0.221

^CPING 10.11.0.221 (10.11.0.221): 56 data bytes

 

--- 10.11.0.221 ping statistics ---

3 packets transmitted, 0 packets received, 100% packet loss

 

This is because of the new IPsec kernel design from FortiOS 7.0.

 

With the new IPsec kernel design, the 'route tree', which was used to select a tunnel by next-hop, is no longer available in the IPsec tunnel list. Now, the 'tunn-id' will be generated automatically and used to link routes with the IPsec tunnel as a gateway.

In this case, the tunnel interface IP will become useless. 

 

This feature was introduced in this related KB article:

Technical Tip: Static route for IPsec VPN shows gateway configured

 

When looking at the routing table on the spoke, instead of using the tunnel interface IP as the next hop, the tunnel ID 10.56.244.208 appears and is the same as the IPsec remote gateway IP by default. (Here is the explanation of the tunnel ID behavior:

Technical Tip : IPsec Tunnel ID expected behavior

 

S       0.0.0.0/20 [10/0] via To_hub_test tunnel 10.56.244.208, [1/0]

 

But on the hub, tunnel-id is not showing in the routing-table and only tunnel IP is there, which is useless.

 

S       10.11.0.0/20 [10/0] via Dialup tunnel 198.19.18.254, [1/0]

S       10.30.0.0/20 [10/0] via Dialup tunnel 198.19.18.254, [1/0]

 

Based on the new kernel design, if the tunnel-id is unknown in the static route, there is no way to identify which sub-tunnel is the correct outgoing interface. So, this will make the communication from Hub to Spoke fail.

 

Although the debug flow indicates the packet has entered the IPsec tunnel Dialup.

 

Debug flow:

 

c3po-kvm23 # id=20085 trace_id=1 func=print_pkt_detail line=5867 msg="vd-root:0 received a packet(proto=1, 10.24.0.208:1024->10.11.0.221:2048) tun_id=0.0.0.0 from local. type=8, code=0, id=1024, seq=0."

id=20085 trace_id=1 func=init_ip_session_common line=6046 msg="allocate a new session-00001a97, tun_id=0.0.0.0"

id=20085 trace_id=1 func=ipsecdev_hard_start_xmit line=669 msg="enter IPSec interface Dialup, tun_id=0.0.0.0"

id=20085 trace_id=2 func=print_pkt_detail line=5867 msg="vd-root:0 received a packet(proto=1, 10.24.0.208:1024->10.11.0.221:2048) tun_id=0.0.0.0 from local. type=8, code=0, id=1024, seq=1."

 

However, the packet will not be able to reach the other end of the tunnel and will be counted as error packets. This can be verified by checking the error packet counter on the interface level:

 

c3po-kvm23 # fnsysctl ifconfig Dialup

Dialup  Link encap:Unknown

        inet addr:198.19.18.1  Mask:255.255.255.0

        UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1420  Metric:1

        RX packets:0 errors:0 dropped:0 overruns:0 frame:0

        TX packets:0 errors:12 dropped:0 overruns:0 carrier:0         <-----  Error counter.

        collisions:0 txqueuelen:0

        RX bytes:0 (0  Bytes)  TX bytes:0 (0  Bytes)

 

The reason why the tunnel ID is not added to the corresponding static route on the hub is that there are more than one spokes connected to the IPsec tunnel ‘Dialup’ so there are multiple tunnel IDs (one for each spoke), thus Hub is not sure which tunnel ID should be the correct next hop for each spoke. On the spoke site, since the tunnel only connects to one destination, there is only one tunnel ID so it is added in the static route automatically.

 

To avoid this situation, instead of configuring a static route for each spoke manually, it is recommended to enable ‘add-route’ option in the IPsec phase1 if a static route is preferred.

By enabling this option, FortiGate will automatically add the static route towards each spoke based on their phase2 selector and tunnel ID will be added in each static route automatically.

 

The below KB article introduces how to enable this option:

Technical Tip: How to add automatic route towards the remote subnets when there are multiple Dial-Up...

 

After enabling this option and deleting those manually configured static routes, static routes for each spoke with the correct tunnel ID are generated automatically:

 

S       10.11.0.0/20 [15/0] via Dialup tunnel 10.56.244.221, [1/0]

S       10.30.0.0/20 [15/0] via Dialup tunnel 10.56.245.12, [1/0]

 

The ping from hub to spoke is successful again as expected.

 

c3po-kvm23 # execute ping 10.11.0.221

PING 10.11.0.221 (10.11.0.221): 56 data bytes

64 bytes from 10.11.0.221: icmp_seq=0 ttl=255 time=1.7 ms

64 bytes from 10.11.0.221: icmp_seq=1 ttl=255 time=1.5 ms

64 bytes from 10.11.0.221: icmp_seq=2 ttl=255 time=0.3 ms

64 bytes from 10.11.0.221: icmp_seq=3 ttl=255 time=0.3 ms

64 bytes from 10.11.0.221: icmp_seq=4 ttl=255 time=0.3 ms

 

--- 10.11.0.221 ping statistics ---

5 packets transmitted, 5 packets received, 0% packet loss

round-trip min/avg/max = 0.3/0.8/1.7 ms

 

In conclusion, after v7.0, on the Dialup VPN hub:

  • Avoid manually configuring static routes for each spoke via the Dialup VPN tunnel.
  • Enabling the ‘add-route’ option in the IPsec phase1 setting to add the static route for each spoke automatically if still prefer using static route.
  • Dynamic routing protocol such as BGP is also recommended to avoid this issue. Refer to ADVPN hub-and-spoke configuration: IPsec VPN wizard hub-and-spoke ADVPN support