本文介紹如何使用strongSwan作為本地網關,實現雲上和雲下的網路互連。
strongSwan是一個開源、基於IPsec的VPN解決方案,配置簡單,可部署在主流的Linux發行版,快速地與阿里雲建立IPsec-VPN串連。
情境樣本
以下圖情境為例,您可以在本地網關裝置上部署strongSwan軟體(下文簡稱為“strongSwan裝置”),與阿里雲建立雙隧道模式的IPsec-VPN串連,實現雲上雲下網路互連。
IP地址規劃
本地IDC側
私網網段:10.0.0.0/16
strongSwan裝置
網卡eth0: 10.0.0.1,NAT映射公網出口1:1.1.XX.XX
(可選)網卡eth1: 10.0.0.2,NAT映射公網出口2: 2.2.XX.XX
說明非NAT情境,請參見“strongSwan裝置網卡綁定了公網IP地址,如何配置?”。
無論您的裝置有1個公網出口(單出口),還是有2個公網出口(雙出口),均可與阿里雲建立雙隧道模式的IPsec-VPN串連,本文會分別給出樣本。
阿里雲側
VPC網段:172.16.0.0/16
交換器1網段:172.16.1.0/24
交換器2網段:172.16.2.0/24
VPN網關
IPsec地址1: 3.3.XX.XX
IPsec地址2: 4.4.XX.XX
說明建立VPN網關執行個體後,系統會自動為VPN網關執行個體分配兩個IPsec地址。
VPN參數配置規劃
本文的2條隧道使用相同的樣本值。注意每條隧道下,strongSwan裝置側和阿里雲側的配置要保持相同。
預先共用金鑰:ChangeMe***
IKE配置
IKE版本:ikev2
協商模式:main
密碼編譯演算法:aes
認證演算法:sha1
DH分組:group2
SA生存周期(秒):86400
IPsec配置:
密碼編譯演算法:aes
認證演算法:sha1
DH分組:group2
SA生存周期(秒):86400
阿里雲側的準備工作
配置strongSwan裝置之前,請先根據情境樣本中的規劃,在阿里雲側完成建立VPN網關執行個體、建立使用者網關、建立IPsec串連、配置VPN網關路由的步驟。具體操作,請參見建立VPC到本機資料中心的串連(雙隧道模式)。
根據strongSwan裝置的公網出口數量,阿里雲側的配置有如下區別:
單出口
使用者網關:因為只有1個公網出口IP,只需建立1個使用者網關。
IPsec串連:
每條隧道的路由模式選擇感興趣流模式。
本端網段填寫阿里雲側VPC的網段 172.16.0.0/16
對端網段填寫本地IDC側的私網網段 10.0.0.0/16
使用者網關選擇同1個。
雙出口
使用者網關:因為有2個公網出口IP,需要對應建立2個使用者網關。
IPsec串連:
選擇路由模式時,2條隧道都選擇目的路由模式。
選擇使用者網關時,隧道1對應公網出口1,隧道2對應公網出口2。
開始配置strongSwan裝置
下文步驟以運行“CentOS Stream 9 64位作業系統”的strongSwan裝置為例。其他動作系統,請參考strongSwan官方文檔。
1. 放通防火牆策略
放通strongSwan裝置的ESP協議(IP協議號50)、UDP500連接埠、UDP4500連接埠。
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
2. 開啟流量轉寄功能
echo 1 > /proc/sys/net/ipv4/ip_forward
上述命令為臨時性命令,strongSwan裝置重啟後需重新設定該命令。您可以參見以下內容永久開啟strongSwan裝置的流量轉寄功能。
3. 安裝strongSwan軟體
dnf install epel-release -y
dnf install strongswan-5.9.10 -y
4. 配置雙隧道
單出口
單出口基於strongSwan感興趣流進行配置,直接可以實現雙隧道主備切換功能。
備份原始strongSwan設定檔
mv /etc/strongswan/swanctl/swanctl.conf /etc/strongswan/swanctl/swanctl.conf.bak
建立strongSwan設定檔
vi /etc/strongswan/swanctl/swanctl.conf
根據情境樣本中的規劃,添加並儲存如下配置
connections { vco1 { # 添加IPsec-VPN隧道1的VPN配置 version = 2 # 指定IKE版本,需與阿里雲隧道1的IKE版本保持一致,2表示IKEv2。 local_addrs = 10.0.0.1 # 本地網卡的ip地址 remote_addrs = 3.3.XX.XX # 指定隧道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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 encap = yes local { auth = psk # 本段認證方式選擇PSK模式,即預先共用金鑰方式。 id = 1.1.XX.XX # 本地公網出口IP,需與阿里雲隧道1的RemoteId保持一致。 } remote { auth = psk # 對端認證方式選擇PSK方式,即阿里雲使用預先共用金鑰方式。 id = 3.3.XX.XX # 阿里雲側IPsec地址1,需與阿里雲隧道1的LocalId保持一致。 } children { vco_child1 { local_ts = 10.0.0.0/16 # 本地側感興趣流,填寫本地私網網段10.0.0.0/16。 remote_ts = 172.16.0.0/16 # 阿里雲側感興趣流,填寫VPC網段172.16.0.0/16。 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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 } } } vco2 { # 添加IPsec-VPN隧道2的VPN配置 version = 2 # 指定IKE版本,需與阿里雲隧道2的IKE版本保持一致,2表示IKEv2。 local_addrs = 10.0.0.1 # 本地網卡的ip地址 remote_addrs = 4.4.XX.XX # 指定隧道 址,即IPsec地址2。 dpd_delay = 10 rekey_time = 84600 # 指定隧道2的SA生存周期,需與阿里雲隧道2 IKE配置中的SA生存周期保持一致。 over_time = 1800 proposals = aes-sha1-modp1024 # 指定隧道2的密碼編譯演算法、認證演算法、DH分組,需與阿里雲隧道2 IKE配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 encap = yes local { auth = psk # 本端認證方式選擇PSK方式,即預先共用金鑰方式。 id = 1.1.XX.XX # 本地公網出口IP,與阿里雲隧道2的RemoteId保持一致。 } remote { auth = psk # 對端認證方式選擇PSK方式,即阿里雲使用預先共用金鑰方式。 id = 4.4.XX.XX # 阿里雲側IPsec地址2,需與阿里雲隧道2的LocalId保持一致。 } children { vco_child2 { local_ts = 10.0.0.0/16 # 本地側感興趣流,填寫本地私網網段10.0.0.0/16。 remote_ts = 172.16.0.0/16 # 阿里雲側感興趣流,填寫VPC網段172.16.0.0/16。 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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 } } } } secrets { ike-vco1 { secret = ChangeMe*** # 指定隧道1的預先共用金鑰,需與阿里雲隧道1的預先共用金鑰保持一致。 } ike-vco2 { secret = ChangeMe*** # 指定隧道2的預先共用金鑰,需與阿里雲隧道2的預先共用金鑰保持一致。 } }
重啟strongSwan進程
systemctl restart strongswan
查看隧道狀態
watch swanctl --list-sas
如圖,strongSwan裝置和VPN網關之間已經正常建立了IPsec-VPN串連。
雙出口
雙出口基於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出口訪問
ip route add 3.3.XX.XX via 10.0.0.253 dev eth0 #10.0.0.253是私網網關地址 ip route add 4.4.XX.XX via 10.0.0.253 dev eth1
確保下面2個IPsec地址能ping通
ping 3.3.XX.XX ping 4.4.XX.XX
建立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裝置重啟後,需要重新添加該配置,並執行
sudo systemctl restart strongswan;swanctl --load-all
命令(該命令需要root許可權)。您可以參見以下內容為strongSwan裝置添加開機自動啟動指令碼,strongSwan裝置重啟後會自動重新添加虛擬網路介面。
建立2個指令碼,供strongSwan調用並配置路由,從而控制流程量傳輸
建立並編輯/root/connect_1.sh指令碼
vi /root/connect_1.sh
添加並儲存如下內容:
#!/usr/bin/env bash if [ x"$PLUTO_VERB" == "xup-client" ]; then echo "ip route add 172.16.0.0/16 dev ipsec0" >> /root/vpn_route.log;ip route add 172.16.0.0/16 dev ipsec0 metric 100 elif [ x"$PLUTO_VERB" == "xdown-client" ]; then echo "ip route del 172.16.0.0/16 dev ipsec0" >> /root/vpn_route.log;ip route del 172.16.0.0/16 dev ipsec0 metric 100 fi
指令碼功能:如果隧道1的狀態是UP,則添加路由使本機資料中心去往阿里雲VPC(172.16.0.0/16)的流量通過隧道1 XFRM虛擬網路介面傳輸,同時指定該路由的metric值為100,使該路由的優先順序高於指向隧道2 XFRM虛擬網路介面的路由。如果隧道1的狀態是DOWN,則撤銷該路由。
建立並編輯/root/connect_2.sh指令碼
vi /root/connect_2.sh
添加並儲存如下內容:
#!/usr/bin/env bash if [ x"$PLUTO_VERB" == "xup-client" ]; then echo "ip route add 172.16.0.0/16 dev ipsec1" >> /root/vpn_route.log;ip route add 172.16.0.0/16 dev ipsec1 metric 101 elif [ x"$PLUTO_VERB" == "xdown-client" ]; then echo "ip route del 172.16.0.0/16 dev ipsec1" >> /root/vpn_route.log;ip route del 172.16.0.0/16 dev ipsec1 metric 101 fi
指令碼功能:如果隧道2的狀態是UP,則添加路由使本機資料中心去往阿里雲VPC(172.16.0.0/16)的流量通過隧道2 XFRM虛擬網路介面傳輸,同時指定該路由的metric值為101,使該路由的優先順序低於指向隧道1 XFRM虛擬網路介面的路由。如果隧道2的狀態是DOWN,則撤銷該路由。
為2個指令碼賦予可執行許可權
sudo chmod +x /root/connect_1.sh sudo chmod +x /root/connect_2.sh
修改strongSwan設定檔
備份原始strongSwan設定檔。
mv /etc/strongswan/swanctl/swanctl.conf /etc/strongswan/swanctl/swanctl.conf.bak
建立strongSwan設定檔。
vi /etc/strongswan/swanctl/swanctl.conf
根據情境樣本中IPsec參數規劃,添加並儲存如下配置
connections { vco1 { # 添加IPsec-VPN隧道1的VPN配置 version = 2 # 指定IKE版本,需與阿里雲隧道1的IKE版本保持一致,2表示IKEv2。 local_addrs = 10.0.0.1 # 第1個本地網卡的ip地址 remote_addrs = 3.3.XX.XX # 指定隧道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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 encap = yes local { auth = psk # 本段認證方式選擇PSK模式,即預先共用金鑰方式。 id = 1.1.XX.XX # 第1個本地公網出口IP,需與阿里雲隧道1的RemoteId保持一致。 } remote { auth = psk # 對端認證方式選擇PSK方式,即阿里雲使用預先共用金鑰方式。 id = 3.3.XX.XX # 阿里雲側IPsec地址1,需與阿里雲隧道1的LocalId保持一致。 } children { vco_child1 { local_ts = 0.0.0.0/0 # 阿里雲目的路由模式對應的感興趣流是0.0.0.0/0。 remote_ts = 0.0.0.0/0 # 阿里雲目的路由模式對應的感興趣流是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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,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 = 10.0.0.2 # 第2個本地網卡的ip地址。 remote_addrs = 4.4.XX.XX # 指定隧道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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,group2對應的是modp1024。 encap = yes local { auth = psk # 本端認證方式選擇PSK方式,即預先共用金鑰方式。 id = 2.2.XX.XX # 第2個本地公網出口IP,,需與阿里雲隧道2的RemoteId保持一致。 } remote { auth = psk # 對端認證方式選擇PSK方式,即阿里雲使用預先共用金鑰方式。 id = 4.4.XX.XX # 阿里雲側IPsec地址2,需與阿里雲隧道2的LocalId保持一致。 } children { vco_child2 { local_ts = 0.0.0.0/0 # 阿里雲目的路由模式對應的感興趣流是0.0.0.0/0 remote_ts = 0.0.0.0/0 # 阿里雲目的路由模式對應的感興趣流是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配置中的密碼編譯演算法、認證演算法、DH分組保持一致,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指令碼,以配置路由。 } } } } secrets { ike-vco1 { secret = ChangeMe*** # 指定隧道1的預先共用金鑰,需與阿里雲隧道1的預先共用金鑰保持一致。 } ike-vco2 { secret = ChangeMe*** # 指定隧道2的預先共用金鑰,需與阿里雲隧道2的預先共用金鑰保持一致。 } }
重啟strongSwan進程
vi /etc/strongswan/swanctl/swanctl.conf
查看路由
route -n
查看隧道狀態
watch swanctl --list-sas
如圖,strongSwan裝置和VPN網關之間已經正常建立了IPsec-VPN串連。
5. 驗證連通性和高可用性
驗證strongSwan裝置和VPC之間的連通性。
在strongSwan裝置
ping
阿里雲VPC內的任意1台ECS,如果能Ping通,則證明連通正常。ping <VPC內1台ECS的地址>
驗證IPsec-VPN串連的高可用性。
保持Ping通的情況下,中斷IPsec-VPN串連下的主隧道。
您可以通過修改IPsec串連主隧道的預先共用金鑰來中斷主隧道,主隧道兩端的預先共用金鑰不一致,則主隧道會中斷。
中斷主隧道後,您可以通過
ping
命令觀察兩側的連通情況。您會發現ping
流量在短暫中斷後,又重新恢複通訊。這表示在主隧道中斷後,流量自動通過備隧道進行通訊。
常見問題
IKEv1版本,使用strongSwan建立IPsec-VPN串連時是否支援?
支援。
配置/etc/strongswan/swanctl/swanctl.conf檔案時,指定version = 1
即可。
如何指定感興趣流?
配置/etc/strongswan/swanctl/swanctl.conf檔案時,在以下配置中指定具體網段即可。請確保阿里雲側IPsec串連也配置了感興趣流模式。
如果本機資料中心側或阿里雲側需要指定多個網段,strongSwan裝置和阿里雲IPsec串連均需要使用IKEv2版本。
children {
vco_child1 {
local_ts = 192.168.20.0/24,192.168.50.0/24 # 本機資料中心網段。
remote_ts = 10.0.0.0/16 # 阿里雲VPC側網段。
}
}
strongSwan裝置網卡綁定了公網IP地址,如何配置?
對於非NAT的情境,也就是strongSwan裝置內部可見的地址為公網IP地址,僅需將/etc/strongswan/swanctl/swanctl.conf設定檔中每條隧道的local_addrs欄位改為公網IP地址即可,其他配置不變。
connections {
vco1 {
local_addrs = 1.1.XX.XX # 指定為strongSwan裝置網卡綁定的公網IP地址
}
}
單隧道如何配置?
如果您購買的VPN網關執行個體僅支援建立單隧道模式的IPsec-VPN串連,推薦您升級IPsec-VPN串連為雙隧道模式,雙隧道模式的IPsec-VPN串連支援可用性區域層級的容災,有效提高了網路的高可用性。