Hub-Spoke静态路由问题

网络拓扑

image-20240102143844149

  1. Hub设备位于数据中心,配在port2配置“拨号用户(Dynamic)”模式的IPSec连接。
  2. Spoke1与Spoke2均在port2上配置“静态IP地址(Static)”类型的IPSec连接,与Hub建立IPSec隧道。
  3. Hub与Spoke之间通过静态路由进行通信。

配置信息

仅以Hub和Spoke1为例。基础网络IP、路由配置略。

Hub

  1. IPSec隧道配置,隧道类型为dynamic,第二阶段保护网段为0.0.0.0/0↔︎0.0.0.0/0,add-route功能为关闭状态。

    config vpn ipsec phase1-interface
        edit "Hub"
            set type dynamic
            set interface "port2"
            set ike-version 2
            set peertype any
            set net-device disable
            set proposal aes128-sha256
            set add-route disable
            set dpd on-idle
            set psksecret ENC YsyLk34z2H6ffoT8QYhgsX5aS5FN4Vq3g9IpjKgh/7uBJdl+W3IMHDuXxXpT1a+ZyxR37cOfpB1Uzf0Vnv8D2Q0E+3259DPYr556hZRDGYo46f=
            set dpd-retryinterval 60
        next
    end
    
    config vpn ipsec phase2-interface
        edit "Hub"
            set phase1name "Hub"
            set proposal aes128-sha1
            set keepalive enable
        next
    end
    
  2. 配置IPSec Tunnel IP。

    config system interface
        edit "Hub"
            set ip 10.10.10.1 255.255.255.255
            set type tunnel
            set remote-ip 10.10.10.254 255.255.255.0
            set interface "port2"
        next
    end
    
  3. 配置防火墙策略放通IPSec隧道与内网口port3之间的流量。

    config firewall policy
        edit 1
            set name "VPN_Hub"
            set srcintf "Hub" "port3"
            set dstintf "Hub" "port3"
            set action accept
            set srcaddr "all"
            set dstaddr "all"
            set schedule "always"
            set service "ALL"
        next
    end
    
  4. 配置去往Spoke1内网网段(192.168.1.0/24)和Spoke2内网网段(192.168.2.0/24)的静态路由,出接口选择IPSec Tunnel接口。

    config router static
        edit 2
            set dst 192.168.1.0 255.255.255.0
            set device "Hub"
        next
        edit 3
            set dst 192.168.2.0 255.255.255.0
            set device "Hub"
        next
    end
    

Spoke1

  1. IPSec隧道配置,隧道类型为static,第二阶段保护网段为0.0.0.0/0↔︎0.0.0.0/0。

    config vpn ipsec phase1-interface
        edit "Spoke1"
            set interface "port2"
            set ike-version 2
            set peertype any
            set net-device disable
            set proposal aes128-sha256
            set remote-gw 100.1.1.2
            set dpd on-idle
            set psksecret ENC fDnGerNZb+ogGLimNoAdp/nQj8tOZRBwu91bMs1MqK4oB/t1Szc8C1Ma43Pga8cW8Qxdew7TgFECbvwq1nYxPqVU6pnbj/DkpT/nuGzvTietA0mjCBubl/1jPU8wkFWABfIXsivn0YOSyjHmQx5LSdbhjvM9FTI6CKjixMszGuC8T8kpczpL2h1FAX1SkytiKeztJg==
        next
    end
    
    config vpn ipsec phase2-interface
        edit "Spoke1"
            set phase1name "Spoke1"
            set proposal aes128-sha1
            set auto-negotiate enable
        next
    end
    
  2. 配置IPSec Tunnel IP。

    config system interface
        edit "Spoke1"
            set ip 10.10.10.2 255.255.255.255
            set type tunnel
            set remote-ip 10.10.10.254 255.255.255.0
            set interface "port2"
        next
    end
    
  3. 配置防火墙策略放通IPSec隧道与内网口port3之间的流量。

    config firewall policy
        edit 1
            set name "VPN_Spoke1"
            set srcintf "port3" "Spoke1"
            set dstintf "port3" "Spoke1"
            set action accept
            set srcaddr "all"
            set dstaddr "all"
            set schedule "always"
            set service "ALL"
        next
    end
    
  4. 配置去往Hub内网网段(192.168.0.0/24)的静态路由,出接口选择IPSec Tunnel接口。

    config router static
        edit 2
            set dst 192.168.0.0 255.255.255.0
            set device "Spoke1"
        next
    end
    

Spoke2

略,与Spoke1一致。

问题现象

  1. IPSec隧道建立后,查看Hub和Spoke的IPSec一阶段状态中的tun_id,可以看到Hub建立了两个动态子IPSec连接(Hub_0和Hub_1),Hub和Spoke显示已建立的隧道ID(tun_id)均为对端公网IP地址。

    Hub # diagnose vpn ike gateway list | grep "name\|tun_id"
    name: Hub_0
    tun_id: 200.1.1.2/::10.0.0.5    <----隧道ID为Spoke1的公网IP
    name: Hub_1
    tun_id: 201.1.1.2/::10.0.0.7    <----隧道ID为Spoke2的公网IP
    
    Spoke1 # diagnose vpn ike gateway list | grep "name\|tun_id"
    name: Spoke1
    tun_id: 100.1.1.2/::100.1.1.2    <----隧道ID为Hub的公网IP
    
    Spoke2 # diagnose vpn ike gateway list | grep "name\|tun_id"
    name: Spoke2
    tun_id: 100.1.1.2/::100.1.1.2    <----隧道ID为Hub的公网IP
    
  2. 使用PC2(Spoke1内网)访问PC1(Hub内网),可以正常通信。

    C:\Users\Administrator.SUMMERICE2019>ipconfig
    Windows IP 配置
    以太网适配器 Ethernet0:
       IPv4 地址 . . . . . . . . . . . . : 192.168.1.100
       子网掩码  . . . . . . . . . . . . : 255.255.255.0
       默认网关. . . . . . . . . . . . . : 192.168.1.1
    
    C:\Users\Administrator.SUMMERICE2019>ping 192.168.0.100
    正在 Ping 192.168.0.100 具有 32 字节的数据:
    来自 192.168.0.100 的回复: 字节=32 时间=3ms TTL=126
    来自 192.168.0.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.0.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.0.100 的回复: 字节=32 时间=2ms TTL=126
    192.168.0.100 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 1ms,最长 = 3ms,平均 = 1ms
    
  3. 使用PC1(Hub内网)访问PC2(Spoke1内网)或PC3(Spoke2内网),无法正常通信。

    C:\Users\Administrator.SUMMERICE2019>ipconfig
    Windows IP 配置
    以太网适配器 Ethernet0:
       IPv4 地址 . . . . . . . . . . . . : 192.168.0.100
       子网掩码  . . . . . . . . . . . . : 255.255.255.0
       默认网关. . . . . . . . . . . . . : 192.168.0.1
    
    C:\Users\Administrator.SUMMERICE2019>ping 192.168.1.100
    正在 Ping 192.168.1.100 具有 32 字节的数据:
    请求超时。
    请求超时。
    请求超时。
    请求超时。
    192.168.1.100 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),
    
  4. 在Hub上抓包显示ICMP Request报文已被送入IPSec Tunnel接口。Debug Flow虽然显示ICMP Request报文已被送入IPSec Tunnel接口,但路由查找的gw(网关)为0.0.0.0,正确的gw应为步骤1中看到的Hub与Spoke1的IPSec子连接Hub_0tun_id 200.1.1.1。

    image-20240508104203455

  5. 在Hub上查看IPSec Tunnel接口的统计信息,可以看到txe(发送错误)计数随着PC1访问PC2的流量在一直增长。

    Hub # diagnose netlink interface list name Hub | grep "txe=\|if="
    if=Hub family=00 type=768 index=16 mtu=1420 link=0 master=0
    stat: rxp=15 txp=15 rxb=900 txb=900 rxe=0 txe=102 rxd=0 txd=0 mc=0 collision=0 @ time=1715074667
    
    Hub # diagnose netlink interface list name Hub | grep "txe=\|^if="
    if=Hub family=00 type=768 index=16 mtu=1420 link=0 master=0
    stat: rxp=15 txp=15 rxb=900 txb=900 rxe=0 txe=108 <----txe计数增长 rxd=0 txd=0 mc=0 collision=0 @ time=1715074676
    

问题原因

  1. 这是由于FortiOS 7.0新的IPSec内核设计导致的。FortiOS 7.0之前版本的Dynamic模式IPSec使用“route tree”功能查找流量应该匹配的子隧道。FortiOS 7.0之后将“route tree”功能移除,使用“tunn-id”用于标识Dynamic模式IPSec连接生成的每个子连接。当Dynamic模式的IPSec连接生成子连接(如Hub_0,Hub_1……)时,将自动分配一个tunn-id给这个子连接,默认配置下,使用对端的公网IP作为隧道的tunn-id

  2. 在Spoke1(Static类型的IPSec)上查看去往Hub内网网段(192.168.0.0/24)的路由,可以看到路由信息中有对应的tun_id,为Hub的公网地址100.1.1.2,所以Spoke内网PC去往Hub内外PC的流量可以正确送入对应tun_id的IPSec隧道。

    Spoke1 # get router info routing-table all | grep 192.168.0.0
    S       192.168.0.0/24 [10/0] via Spoke1 tunnel 100.1.1.2, [1/0]
    
  3. 在Hub上查看路由表,可以看到已配置的Hub去往Spoke1和Spoke2的静态路由在路由表中显示为Tunnel接口的直连路由,并未显示对应的tun_id(这里应为Spoke1和Spoke2的公网IP)。这是由于在Hub上配置的去往Spoke内网的静态路由并未指定出接口和下一跳为哪个IPSec子连接(Hub_0或Hub_1)。

    Hub # get router info routing-table all | grep 192.168
    C       192.168.0.0/24 is directly connected, port3
    S       192.168.1.0/24 [10/0] is directly connected, Hub, [1/0]
    S       192.168.2.0/24 [10/0] is directly connected, Hub, [1/0]
    
  4. 当PC1(Hub内网)访问PC2(Spoke1内网)或PC3(Spoke2内网)时,发起流量进入Hub的IPSec隧道后,由于路由中没有tun_id标识,IPSec不知道应该将其送往哪个子IPSec连接(Hub_0或Hub_1)。

解决方法1-使用add-route

  1. 在Spoke上的IPSec二阶段配置中,修改源保护网段为明细保护网段,目标保护网段仍为0.0.0.0/0。

    Spoke1:
    config vpn ipsec phase2-interface
        edit "Spoke1"
            set src-subnet 192.168.1.0 255.255.255.0
        next
    end
    
    Spoke2:
    config vpn ipsec phase2-interface
        edit "Spoke1"
            set src-subnet 192.168.2.0 255.255.255.0
        next
    end
    
  2. 将Hub上配置的去往Spoke内外的静态路由禁用或删除。

    config router static
        edit 2
            set status disable
            set dst 192.168.1.0 255.255.255.0
            set device "Hub"
        next
        edit 3
            set status disable
            set dst 192.168.2.0 255.255.255.0
            set device "Hub"
        next
    end
    
  3. 在Hub上的IPSec一阶段配置中,将add-route功能开启,根据Spoke协商的源保护网段自动添加去往Spoke内网的路由。

    config vpn ipsec phase1-interface
        edit "Hub"
            set add-route enable
        next
    end
    
  4. 在Hub上查看路由表,可以看到通过add-route功能添加的去往Spoke内网的路由自动添加了tunn-id标记,去往Spoke1内网的路由指定的是IPSec子连接Hub_0的tunn-id,去往Spoke2内网的路由指定的是IPSec子连接Hub_1的tunn-id

    Hub # get router info routing-table all | grep 192.168
    C       192.168.0.0/24 is directly connected, port3
    S       192.168.1.0/24 [15/0] via Hub tunnel 200.1.1.2, [1/0]
    S       192.168.2.0/24 [15/0] via Hub tunnel 201.1.1.2, [1/0]
    
  5. 使用PC1(Hub内网)访问PC2(Spoke1内网)或PC3(Spoke2内网),可以正常通信。

    C:\Users\Administrator.SUMMERICE2019>ipconfig
    以太网适配器 Ethernet0:
       IPv4 地址 . . . . . . . . . . . . : 192.168.0.100
       子网掩码  . . . . . . . . . . . . : 255.255.255.0
       默认网关. . . . . . . . . . . . . : 192.168.0.1
    
    C:\Users\Administrator.SUMMERICE2019>ping 192.168.1.100
    正在 Ping 192.168.1.100 具有 32 字节的数据:
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=3ms TTL=126
    192.168.1.100 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 1ms,最长 = 3ms,平均 = 1ms
    
  6. Debug Flow显示ICMP Request报文到达FortiGate后,路由查找网关为Hub与Spoke1的IPSec子隧道Hub_0的tun_id 200.1.1.2。该流量最终可以被送入IPSec子隧道Hub_0送往Spoke1。

    image-20240508103440939

解决方法2-配置VPN路由下一跳

此方法要求Spoke的公网IP不会变化。

  1. Spoke IPSec二阶段仍然配置0.0.0.0↔︎0.0.0.0的保护网段,Hub关闭add-route功能。

  2. 在Hub上修改去往Spoke的静态路由,配置下一跳为Spoke对应的公网IP(tun_id)。

    出接口为IPSec Tunnel时,相关路由的下一跳(gateway)只能在CLI下配置。

    config router static
        edit 2
            set dst 192.168.1.0 255.255.255.0
            set gateway 200.1.1.2
            set device "Hub"
        next
        edit 3
            set dst 192.168.2.0 255.255.255.0
            set gateway 201.1.1.2
            set device "Hub"
        next
    end
    
  3. 在Hub查看路由表,去往Spoke内网的路由下一跳变为Spoke1和Spoke2的公网IP,对应相关已建立的IPSec子隧道Hub_0、Hub_1的tun_id

    Hub # get router info routing-table all | grep 192.168
    C       192.168.0.0/24 is directly connected, port3
    S       192.168.1.0/24 [10/0] via Hub tunnel 200.1.1.2, [1/0]
    S       192.168.2.0/24 [10/0] via Hub tunnel 201.1.1.2, [1/0]
    
  4. 使用PC1(Hub内网)访问PC2(Spoke1内网)或PC3(Spoke2内网),可以正常通信。

    C:\Users\Administrator.SUMMERICE2019>ipconfig
    以太网适配器 Ethernet0:
       IPv4 地址 . . . . . . . . . . . . : 192.168.0.100
       子网掩码  . . . . . . . . . . . . : 255.255.255.0
       默认网关. . . . . . . . . . . . . : 192.168.0.1
    
    C:\Users\Administrator.SUMMERICE2019>ping 192.168.1.100
    正在 Ping 192.168.1.100 具有 32 字节的数据:
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=3ms TTL=126
    192.168.1.100 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 1ms,最长 = 3ms,平均 = 1ms
    
  5. Debug Flow显示ICMP Request报文到达FortiGate后,路由查找网关为Hub与Spoke1的IPSec子隧道Hub_0的tun_id 200.1.1.2。该流量最终可以被送入IPSec子隧道Hub_0送往Spoke1。

    image-20240508113057131

解决方法3-使用exchange-ip

  1. Spoke IPSec二阶段仍然配置0.0.0.0↔︎0.0.0.0的保护网段,Hub关闭add-route功能。

  2. 在所有Spoke上修改IPSec一阶段配置,开启exchange-ip功能,Spoke与Hub进行IKE协商时会发送对应隧道已配置的IPSec Tunnel IP地址,隧道建立完成后,Hub将使用Spoke发送的IPSec Tunnel IP作为对应的隧道ID(tun_id)。

    Spoke1:
    config vpn ipsec phase1-interface
        edit "Spoke1"
            set exchange-interface-ip enable
        next
    end
    
    Spoke2:
    config vpn ipsec phase1-interface
        edit "Spoke2"
            set exchange-interface-ip enable
        next
    end
    

    在本文“配置信息”章节中已为所有IPSec Tunnel接口配置了IP。

    如果Spoke的IPSec Tunnel接口没有手动配置IP或没有通过mode-cfg获取IP,则需要手工指定exchange-ip要交换的IP地址(该地址可自定义,不需要是设备上已存在的地址):

    config vpn ipsec phase1-interface
        edit "Spoke2"
            set exchange-interface-ip enable
            set exchange-ip-addr4 10.10.10.2
        next
    end
    
  3. IPSec隧道建立后,查看Hub和Spoke的IPSec一阶段状态中的tun_id,可以看到Hub建立了两个动态子IPSec连接(Hub_0和Hub_1),Hub和Spoke显示已建立的隧道ID(tun_id)均为对端公网IP地址。

    Hub # diagnose vpn ike gateway list | grep "name\|tun_id"
    name: Hub_0
    tun_id: 10.10.10.2/::10.0.0.50    <----隧道ID为Spoke1的IPSec Tunnel IP
    name: Hub_1
    tun_id: 10.10.10.3/::10.0.0.53    <----隧道ID为Spoke2的IPSec Tunnel IP
    
  4. 在Hub上修改去往Spoke的静态路由,配置下一跳为Spoke对应的IPSec Tunnel接口IP。

    出接口为IPSec Tunnel时,相关路由的下一跳(gateway)只能在CLI下配置。

    config router static
        edit 2
            set dst 192.168.1.0 255.255.255.0
            set gateway 10.10.10.2
            set device "Hub"
        next
        edit 3
            set dst 192.168.2.0 255.255.255.0
            set gateway 10.10.10.3
            set device "Hub"
        next
    end
    
  5. 在Hub查看路由表,去往Spoke内网的路由下一跳变为Spoke1和Spoke2的IPSec Tunnel IP,对应相关已建立的IPSec子隧道Hub_0、Hub_1的tun_id

    Hub # get router info routing-table all | grep 192.168
    C       192.168.0.0/24 is directly connected, port3
    S       192.168.1.0/24 [10/0] via Hub tunnel 10.10.10.2, [1/0]
    S       192.168.2.0/24 [10/0] via Hub tunnel 10.10.10.3, [1/0]
    
  6. 使用PC1(Hub内网)访问PC2(Spoke1内网)或PC3(Spoke2内网),可以正常通信。

    C:\Users\Administrator.SUMMERICE2019>ipconfig
    以太网适配器 Ethernet0:
       IPv4 地址 . . . . . . . . . . . . : 192.168.0.100
       子网掩码  . . . . . . . . . . . . : 255.255.255.0
       默认网关. . . . . . . . . . . . . : 192.168.0.1
    
    C:\Users\Administrator.SUMMERICE2019>ping 192.168.1.100
    正在 Ping 192.168.1.100 具有 32 字节的数据:
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=1ms TTL=126
    来自 192.168.1.100 的回复: 字节=32 时间=3ms TTL=126
    192.168.1.100 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 1ms,最长 = 3ms,平均 = 1ms
    
  7. Debug Flow显示ICMP Request报文到达FortiGate后,路由查找网关为Hub与Spoke1的IPSec子隧道Hub_0的tun_id 200.1.1.2。该流量最终可以被送入IPSec子隧道Hub_0送往Spoke1。

    image-20240508105342093

Exchange IP交互报文

  • IKEv1主模式:位于第一阶段第5、6个报文中Payload: Notification (11)Notify Message TypeDOI-specific codes (32249))的Notification DATA

    image-20240508140856010

  • IKEv1野蛮模式:位于第一阶段第2、3个报文中Payload: Notification (11)Notify Message TypeDOI-specific codes (32249))的Notification DATA

    image-20240508141711305

  • IKEv2:位于IKE_AUTH报文中Payload: Notify (41)Notify Message TypePrivate Use - STATUS TYPES (61689))的Notification DATA

    image-20240508114450989

解决方法4-使用动态路由

使用BGP或OSPF等动态路由,自动学习去往Spoke内网网段的路由会携带对应的tun_id

Copyright © 2024 Fortinet Inc. All rights reserved. Powered by Fortinet TAC Team.
📲扫描下方二维码分享此页面👇
该页面修订于: 2024-05-17 15:35:45

results matching ""

    No results matching ""