使用 VPN 网关配置 IPsec-VPN 连接(双隧道模式)连接 VPC 和本地数据中心,避免单隧道故障导致业务中断,保障连接高可用。
工作原理
某公司在阿里云新加坡地域创建 VPC(主网段为 192.168.0.0/16),且在新加坡部署本地数据中心(网段为 172.16.0.0/16)。因业务发展,本地数据中心需要访问 VPC 中的资源。公司可使用 VPN 网关建立 VPC 与本地数据中心的 IPsec 连接(双隧道模式)。
双隧道模式,即包含一条主隧道和一条备隧道。系统自动检测主隧道的连通性,当检测到主隧道中断后,VPN 网关会自动将流量切换到备隧道。待主隧道恢复后,流量将自动切回。
VPN 网关创建时会分配两个公网 IP 地址,分别用于建立主隧道和备隧道。每条隧道独立完成 IKE 协商与密钥交换,并承载数据流量。
以本地网关设备部署 strongSwan 软件为例。其他本地网关设备配置示例。
适用范围
本地数据中心的网关设备:
网关设备必须配置公网 IP 地址。建议配置 2 个公网 IP 地址或本地数据中心部署 2 个网关设备,每个网关设备均配置 1 个公网 IP 地址。
网关设备必须支持 IKEv1 或 IKEv2 协议。
VPC:以下地域和可用区支持双隧道模式的 IPsec-VPN 连接。
本地数据中心的网段与 VPC 的网段没有重叠。
操作步骤
第一步:创建 VPN 网关
前往VPN网关管理控制台。
实例名称、资源组:可结合使用,统一标识云资源。
地域:选择 VPC 所在地域。本文为新加坡。
网关类型:选择普通型。
网络类型:选择公网。
隧道:选择双隧道。
专有网络:选择计划与本地数据中心连通的 VPC。
虚拟交换机1、虚拟交换机2:选择 VPC 下不同可用区的 2 个交换机。
带宽峰值:使用默认值。
流量:选择按流量计费。
开启IPsec-VPN,关闭SSL-VPN。
购买时长:使用默认值。
服务关联角色:确保创建服务关联角色AliyunServiceRoleForVpn,VPN 网关使用此角色来访问其他云产品中的资源。

返回VPN网关页面,VPN网关实例的初始状态为准备中,约1~5分钟左右会转换为正常。系统会为 VPN 网关分配两个公网 IP 地址,分别用于建立主隧道和备隧道。本示例中,系统分配的两个公网 IP 地址为:IPsec地址1:
120.XX.XX.152(IPsec地址1 - 主隧道)、120.XX.XX.0(IPsec地址2 - 备隧道)。
第二步:创建用户网关
前往VPN - 用户网关页面,单击创建用户网关。
分别创建 2 个用户网关用于创建 2 个加密隧道。
|
|
第三步:创建 IPsec 连接
前往VPN - 创建IPsec连接页面,配置完成后单击确定。
IPsec配置
地域:选择 VPC 所在地域。本文为新加坡。
绑定VPN网关:选择第一步创建的 VPN 网关。
路由模式:选择目的路由模式,基于目的 IP 地址路由和转发流量。
立即生效:选择是,配置完成后立即进行协商。

隧道配置
启用BGP:本文选择不启用。
Tunnel:分别配置主隧道和备隧道。


在创建成功对话框,单击取消。单击创建的 IPsec 连接操作列的生成对端配置。复制配置并保存在本地,用于后续配置本地网关设备。
第四步:配置本地网关设备
本文以本地网关设备部署 strongSwan 软件(下文简称为“ strongSwan 设备”)为例。
其他本地网关设备配置示例。
以下内容包含的第三方产品信息仅供参考。阿里云对第三方产品的性能、可靠性以及操作可能带来的潜在影响,不做任何暗示或其他形式的承诺。
以下步骤以运行CentOS Stream 9 64位操作系统的strongSwan设备为例。其他操作系统,请参考strongSwan官方文档。放通防火墙策略:在 strongSwan 设备上放通 ESP 协议( IP 协议号 50)、UDP 500端口、UDP 4500端口。
iptables -I INPUT -p 50 -j ACCEPT iptables -I INPUT -p udp --dport 500 -j ACCEPT iptables -I INPUT -p udp --dport 4500 -j ACCEPT执行
echo 1 > /proc/sys/net/ipv4/ip_forward开启流量转发。执行
dnf install epel-release -y和dnf install strongswan -y安装 strongSwan 软件。配置双隧道:
双出口基于 XFRM 虚拟网络接口实现,使用XFRM虚拟网络接口需要安装strongSwan 5.8.0或以上版本,同时要求Linux内核版本为4.19及以上、iproute2版本为5.1.0及以上,且内核支持xfrm模块(
lsmod | grep xfrm无显示则不支持)。更多信息,请参见XFRM Interfaces on Linux。添加指向阿里云侧2个 IPsec 地址的路由,使 IPsec 地址1通过 eth0 出口访问,IPsec 地址2通过 eth1 出口访问,确保 IPsec 地址可 ping 通。
ip route add 120.XX.XX.152 via 172.16.1.253 dev eth0 #172.16.1.253是eth0私网网关地址 ip route add 120.XX.XX.0 via 172.16.2.253 dev eth1 #172.16.2.253是eth1私网网关地址创建2个虚拟网络接口,分别用于建立 IPsec-VPN 主备隧道。
ip link add ipsec0 type xfrm dev eth0 if_id 42 # 创建隧道1 XFRM虚拟网络接口,接口ID为42,底层接口为公网接口eth0。 ip link add ipsec1 type xfrm dev eth1 if_id 43 # 创建隧道2 XFRM虚拟网络接口,接口ID为43,底层接口为公网接口eth1。 ip link set ipsec0 up # 启动隧道1 XFRM虚拟网络接口。 ip link set ipsec1 up # 启动隧道2 XFRM虚拟网络接口。修改 strongSwan 配置文件。
执行
mv /etc/strongswan/swanctl/swanctl.conf /etc/strongswan/swanctl/swanctl.conf.bak备份原始配置文件。执行
vi /etc/strongswan/swanctl/swanctl.conf,按照 IPsec 连接的配置,添加、修改并保存如下配置。connections { vco1 { # 添加IPsec-VPN隧道1的VPN配置 version = 2 # 指定IKE版本,需与阿里云隧道1的IKE版本保持一致,2表示IKEv2。 local_addrs = 172.16.0.93 # 第1个本地网卡的ip地址 remote_addrs = 120.XX.XX.152 # 指定隧道1对端的IP地址为阿里云隧道1的网关IP地址,即IPsec地址1。 dpd_delay = 10 rekey_time = 84600 # 指定隧道1的SA生存周期,需与阿里云隧道1 IKE配置中的SA生存周期保持一致。 over_time = 1800 proposals = aes-sha1-modp1024 # 指定隧道1的加密算法、认证算法、DH分组,需与阿里云隧道1 IKE配置保持一致,group2对应的是modp1024。 encap = yes local { auth = psk # 本段认证方式选择PSK模式,即预共享密钥方式。 id = 47.XX.XX.198 # 第1个本地公网出口IP,需与阿里云隧道1的RemoteId保持一致。 } remote { auth = psk # 对端认证方式选择PSK方式,即阿里云使用预共享密钥方式。 id = 120.XX.XX.152 # 阿里云侧IPsec地址1,需与阿里云隧道1的LocalId保持一致。 } children { vco_child1 { local_ts = 0.0.0.0/0 remote_ts = 0.0.0.0/0 mode = tunnel rekey_time = 85500 life_time = 86400 # 指定隧道1的SA生存周期,需与阿里云隧道1 IPsec配置中的SA生存周期保持一致。 dpd_action = restart start_action = start close_action = start esp_proposals = aes-sha1-modp1024 # 指定隧道1的加密算法、认证算法、DH分组,需与阿里云隧道1 IPsec配置保持一致,group2对应的是modp1024。 if_id_out = 42 # 指定隧道1的出接口和入接口为隧道1 XFRM虚拟网络接口。 if_id_in = 42 updown = /root/connect_1.sh # 根据隧道1的UP和DOWN状态执行/root/connect_1.sh脚本,以配置路由。 } } } vco2 { # 添加IPsec-VPN隧道2的VPN配置 version = 2 # 指定IKE版本,需与阿里云隧道2的IKE版本保持一致,2表示IKEv2。 local_addrs = 172.16.2.57 # 第2个本地网卡的ip地址。 remote_addrs = 120.XX.XX.0 # 指定隧道2对端的IP地址为阿里云隧道2的网关IP地址,即IPsec地址2。 dpd_delay = 10 rekey_time = 84600 # 指定隧道2的SA生存周期,需与阿里云隧道2 IKE配置中的SA生存周期保持一致。 over_time = 1800 proposals = aes-sha1-modp1024 # 指定隧道2的加密算法、认证算法、DH分组,需与阿里云隧道2 IKE配置保持一致,group2对应的是modp1024。 encap = yes local { auth = psk # 本端认证方式选择PSK方式,即预共享密钥方式。 id = 47.XX.XX.181 # 第2个本地公网出口IP,,需与阿里云隧道2的RemoteId保持一致。 } remote { auth = psk # 对端认证方式选择PSK方式,即阿里云使用预共享密钥方式。 id = 120.XX.XX.0 # 阿里云侧IPsec地址2,需与阿里云隧道2的LocalId保持一致。 } children { vco_child2 { local_ts = 0.0.0.0/0 remote_ts = 0.0.0.0/0 mode = tunnel rekey_time = 85500 life_time = 86400 # 指定隧道2的SA生存周期,需与阿里云隧道1 IPsec配置中的SA生存周期保持一致。 dpd_action = restart start_action = start close_action = start esp_proposals = aes-sha1-modp1024 # 指定隧道2的加密算法、认证算法、DH分组,需与阿里云隧道2 IPsec配置保持一致,group2对应的是modp1024。 if_id_out = 43 # 指定隧道2的出接口和入接口为隧道2 XFRM虚拟网络接口。 if_id_in = 43 updown = /root/connect_2.sh # 根据隧道2的UP和DOWN状态执行/root/connect_2.sh脚本,以配置路由。 } } } } # 此处的密钥配置不指定id,所有隧道共享。不指定id时,请确保两个密钥的内容相同,否则可能协商失败。 secrets { ike-vco1 { secret = <指定隧道1的预共享密钥> # 与阿里云隧道1的预共享密钥保持一致。 } ike-vco2 { secret = <指定隧道2的预共享密钥> # 与阿里云隧道2的预共享密钥保持一致。 } }
重启 strongSwan 进程,重新加载 strongSwan 配置,查看隧道状态。
sudo systemctl restart strongswan swanctl --load-all watch swanctl --list-sas如下图所示,strongSwan设备和 VPN 网关之间已经成功建立 IPsec-VPN 连接。

配置路由:
执行
vi /root/connect_1.sh,添加并保存以下配置。# 如果隧道1的状态是UP,则添加路由使本地数据中心去往阿里云VPC(192.168.0.0/16)的流量通过隧道1 XFRM虚拟网络接口传输 # 同时指定该路由的metric值为100,使该路由的优先级高于指向隧道2 XFRM虚拟网络接口的路由。 # 如果隧道1的状态是DOWN,则撤销该路由。 #!/usr/bin/env bash if [ x"$PLUTO_VERB" == "xup-client" ]; then echo "ip route add 192.168.0.0/16 dev ipsec0" >> /root/vpn_route.log;ip route add 192.168.0.0/16 dev ipsec0 metric 100 elif [ x"$PLUTO_VERB" == "xdown-client" ]; then echo "ip route del 192.168.0.0/16 dev ipsec0" >> /root/vpn_route.log;ip route del 192.168.0.0/16 dev ipsec0 metric 100 fi执行
vi /root/connect_2.sh,添加并保存以下配置。# 如果隧道2的状态是UP,则添加路由使本地数据中心去往阿里云VPC(192.168.0.0/16)的流量通过隧道2 XFRM虚拟网络接口传输 # 同时指定该路由的metric值为101,使该路由的优先级低于指向隧道1 XFRM虚拟网络接口的路由。 # 如果隧道2的状态是DOWN,则撤销该路由。 #!/usr/bin/env bash if [ x"$PLUTO_VERB" == "xup-client" ]; then echo "ip route add 192.168.0.0/16 dev ipsec1" >> /root/vpn_route.log;ip route add 192.168.0.0/16 dev ipsec1 metric 101 elif [ x"$PLUTO_VERB" == "xdown-client" ]; then echo "ip route del 192.168.0.0/16 dev ipsec1" >> /root/vpn_route.log;ip route del 192.168.0.0/16 dev ipsec1 metric 101 fi执行
sudo chmod +x /root/connect_1.sh和sudo chmod +x /root/connect_2.sh赋予可执行权限。执行
sudo systemctl restart strongswan重启 strongSwan 进程。执行
route -n确认路由是否配置成功。
为本地数据中心内、计划与 VPC 连通的服务器配置目标网段为 VPC 网段、下一跳为 strongSwan 设备的路由。
执行以下命令关闭 rp_filter,避免因非对称路由导致无法连通。
sudo sysctl -w net.ipv4.conf.all.rp_filter=0 sudo sysctl -w net.ipv4.conf.eth0.rp_filter=0 sudo sysctl -w net.ipv4.conf.eth1.rp_filter=0
第五步:配置 VPN 网关路由
前往VPN - VPN 网关页面,单击第一步创建的 VPN 网关 ID。
单击目的路由表页签,选择添加路由条目。
|
|
验证测试
测试本地数据中心和 VPC 的连通性:登录 VPC 中的 ECS 实例,执行
ping <本地数据中心服务器私网IP地址>,收到本地数据中心服务器的回复报文,即可正常通信。测试 IPsec-VPN 连接的高可用性。
登录 VPC 中的 ECS 实例,执行
ping <本地数据中心服务器私网IP地址> -c 10000连续向本地数据中心发送访问报文。中断 IPsec-VPN 连接的主隧道:可通过修改 IPsec 连接主隧道的预共享密钥,主隧道因两端的预共享密钥不一致而中断。
中断主隧道后,观察 VPC 中 ECS 实例的通信情况:流量在短暂中断后,又重新恢复通信,则表示在主隧道中断后,流量自动通过备隧道进行通信。



