AWS构建健壮的混合云网络——BJS VPN篇
构建健壮的混合云网络——BJS VPN篇
背景介绍:
近年来,随着公有云的普及,一方面,越来越多的用户选择利用公有云在弹性、灵活性等方面的优势,在云上部署新的应用系统,另一方面,大量的企业有很多现有的本地基础设施投资,所以企业上云的过程并不是一触而就的,期间势必存在云应用与本地数据中心应用并存的局面,为了更好的融合云与本地数据中心的应用环境,实现整体应用系统的稳定性和高可用性,构建一个健壮的混合云网络至关重要。
在AWS上,用来连接AWS与本地数据中心的方式主要有以下3种:
1. 纯VPN组网
2. 纯专线组网
3. VPN与专线的混合组网
其中,对于AWS中国区来讲,由于AWS自身的VPN服务VGW目前尚未落地,客户急需要一个替代方案,能够达到类似于VGW的冗余及故障切换功能。
本篇主要讲述第一种组网方式,着眼点在于如何实现混合云网络的健壮性及故障自愈,并不会讲述太多的IPSec VPN知识。
对于第二,第三种组网方式的高可用实现,请参考:
《构建健壮的混合云网络——BJS DX篇》
《构建健壮的混合云网络——BJS DX+VPN篇》
对于如何实现对VPN流量的监控、故障告警及事件日志搜集,请参考:
《构建健壮的混合云网络——BJS DX+VPN篇》
拓扑图:
Strongswan-1和Strongswan-2分别作为Region A两个AZ内的VPN设备,与客户本地站点的internet出口设为分别建立两条VPN隧道,Private-1和Private-2分别模拟Region A两个AZ中的两台内网设备。
本场景需要实现如下目的:
1. Private-1,Private-2能够与本地站点内的设备通过私网互通
2. AWS侧能够检测VPN连接的健康状态并实现自动的故障切换
3. AWS侧能够检测VPN设备的健康状态并实现自动的故障切换
4. 本地站点侧能够检测VPN连接的健康状态并实现自动的故障切换
5. 本地站点侧能够检测VPN设备的健康状态并实现自动的故障切换
系统工作流程:
1. Strongswan-1和Strongswan-2设置开机自动运行vpn_monitor.sh脚本,该脚本首先会将Private-1和Private-2去往本地站点的路由分别指向本AZ中的VPN设备,即:Strongswan-1和Strongswan-2
2. 接着Strongswan-1和Strongswan-2会通过互相ping来检测对端的可达性,同时通过ping本地站点VPN设备的tunnel地址来检测VPN连接的可达性。
3. 如果Strongswan-1的VPN连接发生故障,Strongswan-1会将Private-1路由的target从Strongswan-1修改为指向Strongswan-2,连接恢复后,Strongswan-1会将路由切换回自身
4. 如果Strongswan-1发生故障,Strongswan-2的ping检测失败,Strongswan-2会将Private-1路由的target从Strongswan-1修改为指向Strongswan-2
5. Strongswan-2接着会对Strongswan-1做stop,start操作
6. 当Strongswan-1在另外一台物理机上启动后,自动运行的脚本会将Private-1路由从Strongswan-2修改为指向Strongswan-1
配置步骤:
1. 为Strongswan-1和Strongswan-2创建合适的角色并关联
由于Strongswan-1和Strongswan-2需要对VPC路由表及EC2实例做操作,所以需要创建合适的角色并与实例关联。
在IAM服务中选择策略->创建策略
选择创建您自己的策略
使用如下内容设置策略文档,并点击创建策略
在IAM服务中选择角色->创建新角色
设置角色名称
选择AWS服务角色->Amazon EC2
选择筛选条件为客户管理的策略,并勾选之前创建的Strongswan_Policy
审核配置并点击创建角色
在创建Strongswan-1和Strongswan-2的EC2时,关联Strongswan_role角色
需要注意为Strongswan-1,Strongswan-2关联EIP,避免IP发生变化导致VPN无法建立,并且需要在控制台关闭源/目地址检查
2. VPC网络规划
本场景的VPC的CIDR为172.16.0.0/16,一共需要至少四个子网分别对应4台EC2,Strongswan-1和Strongswan-2可以共用一张路由表,默认路由到IGW,Private-1和Private-2分别需要一张独立的路由表,关于如何配置VPC,子网,IGW,路由表等内容,可以参考如下文档:
Amazon Virtual Private Cloud用户指南
http://docs.amazonaws.cn/AmazonVPC/latest/UserGuide/VPC_Introduction.html
Strongswan-1和Strongswan-2所在子网的路由表设置如下
Private-1所在子网的路由表设置如下,eni-23fbd87a为Strongswan-1的网卡ID,10.10.0.0/16为本地站点网段
Private-2所在子网的路由表设置如下,eni-2d75e606为Strongswan-2的网卡ID,10.10.0.0/16为本地站点网段
3. 配置Strongswan
3.1 在Strongswan-1及Strongswan-2的/etc/sysctl.conf文件中添加如下内容,开启转发,关闭重定向及反向路径过滤:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.rp_filter = 2
运行sysctl –p使修改生效
3.2 安装Strongswan
修改/etc/yum.repos.d/epel.repo,将enabled=0修改成enabled=1
wget ftp://fr2.rpmfind.net/linux/centos/6.8/os/x86_64/Packages/trousers-0.3.13-2.el6.x86_64.rpm
rpm -ivh trousers-0.3.13-2.el6.x86_64.rpm
yum install strongswan -y
chkconfig strongswan on
3.3 配置Strongswan-1的strongswan
修改Strongswan-1的/etc/strongswan/ipsec.conf,添加如下内容,其中172.16.1.157为Strongswan-1的私网地址,54.223.192.238为Strongswan-1的公网地址,52.50.130.77为本地站点路由器的公网地址:
conn vpn1
type=tunnel
mobike=no
authby=secret
keyexchange=ikev1
ike=aes128-sha1-modp1024
esp=aes128-sha1-modp1024
left=172.16.1.157
leftid=54.223.192.238
leftsubnet=0.0.0.0/0
right=52.50.130.77
rightsubnet=0.0.0.0/0
auto=start
dpddelay=3
dpdtimeout=15
dpdaction=restart
mark=100
3.4 创建Strongswan-1的/etc/strongswan/ipsec.secrets文件,添加如下内容:
54.223.192.238 52.50.130.77 : PSK "cisco"
3.5 配置Strongswan-2的strongswan
修改Strongswan-2的/etc/strongswan/ipsec.conf,添加如下内容,其中172.16.2.126为Strongswan-2的私网地址,54.222.191.34为Strongswan-2的公网地址,52.51.34.140为本地站点路由器的公网地址:
conn vpn1
type=tunnel
mobike=no
authby=secret
keyexchange=ikev1
ike=aes128-sha1-modp1024
esp=aes128-sha1-modp1024
left=172.16.2.126
leftid=54.222.191.34
leftsubnet=0.0.0.0/0
right=52.51.34.140
rightsubnet=0.0.0.0/0
auto=start
dpddelay=3
dpdtimeout=15
dpdaction=restart
mark=100
3.6 创建Strongswan-2的/etc/strongswan/ipsec.secrets文件,添加如下内容:
54.222.191.34 52.51.34.140 : PSK "cisco"
3.7 下载脚本到Strongswan-1和Strongswan-2,修改如下内容
脚本下载地址:https://s3.cn-north-1.amazonaws.com.cn/junyublog/vpn_monitor.sh
VPN_ID="i-0430fe110cdec5835"
VPN_RT_ID="rtb-4b8f522f"
Remote_IP="169.254.40.105"
My_RT_ID="rtb-468f5222"
VPN_ID为peer的instance id,对于运行在Strongswan-1上的脚本,该值为Strongswan-2的instance id,对于运行在Strongswan-2上的脚本,该值为Strongswan-1的instance id
对于运行在Strongswan-1上的脚本,VPN_RT_ID为Private-2所在子网关联的路由表,对于运行在Strongswan-2上的脚本,VPN_RT_ID为Private-1所在子网关联的路由表
Remote_IP为对端本地站点路由器的tunnel地址
My_RT_ID为本机负责转发的EC2的路由表ID,对于运行在Strongswan-1上的脚本,该值为Private-1的路由表ID,对于运行在Strongswan-2上的脚本,该值为Private-2的路由表ID
4. 创建tunnel接口及路由表
在/etc/rc.d/rc.local文件中添加如下内容:
Strongswan-1:
litterbin=$(ip link add tunnel1 type vti local 172.16.1.157 remote 52.50.130.77 key 100)
litterbin=$(ip add add 169.254.100.2/30 remote 169.254.100.1/30 dev tunnel1)
litterbin=$(ip link set tunnel1 up mtu 1436)
litterbin=$(ip rule add priority 10 from all lookup 10)
ip route add 169.254.100.0/30 via 169.254.100.1 table 10
ip route add 10.10.0.0/16 via 169.254.100.1 table 10
/bin/bash ./home/ec2-user/vpn_monitor.sh > /tmp/log
其中169.254.100.2为Strongswan-1的tunnel口地址,169.254.100.1为对端本地站点路由器的tunnel口地址,172.16.1.157为Strongswan-1的私网地址,52.50.130.77为对端本地站点路由器的出口地址
Strongswan-2
litterbin=$(ip link add tunnel1 type vti local 172.16.2.126 remote 52.51.34.140 key 100)
litterbin=$(ip add add 169.254.200.2/30 remote 169.254.200.1/30 dev tunnel1)
litterbin=$(ip link set tunnel1 up mtu 1436)
litterbin=$(ip rule add priority 10 from all lookup 10)
ip route add 169.254.200.0/30 via 169.254.200.1 table 10
ip route add 10.10.0.0/16 via 169.254.200.1 table 10
/bin/bash ./home/ec2-user/vpn_monitor.sh > /tmp/log
其中169.254.200.2为Strongswan-2的tunnel口地址,169.254.200.1为对端本地站点路由器的tunnel口地址,172.16.2.126为Strongswan-1的私网地址,52.51.34.140为对端本地站点路由器的出口地址
5. 本地站点路由器参考配置
此处以Cisco路由器为例,思路如下:
a. 创建tunnel-based ipsec vpn
b. 通往VPC网段的路由指向tunnel接口,并且使用ip sla track
c. 设置ip sla检测Strongswan的tunnel ip可达性
d. 本地内网配置IGP,将静态路由重分发到IGP中
Cisco Router 1:
track 100 ip sla 10 reachability
!
crypto keyring KEYRING
local-address 10.10.1.100
pre-shared-key address 54.223.192.238 key cisco
!
crypto isakmp policy 100
encr aes
authentication pre-share
group 2
lifetime 28800
crypto isakmp keepalive 10 10
crypto isakmp profile isakmp-profile
keyring KEYRING
match identity address 54.223.192.238 255.255.255.255
local-address 10.10.1.100
!
crypto ipsec security-association replay window-size 128
!
crypto ipsec transform-set TRAN esp-aes esp-sha-hmac
mode tunnel
crypto ipsec df-bit clear
!
crypto ipsec profile ipsec-profile
set transform-set TRAN
set pfs group2
!
interface Tunnel100
ip address 169.254.100.1 255.255.255.0
ip tcp adjust-mss 1387
tunnel source 10.10.1.100
tunnel mode ipsec ipv4
tunnel destination 54.223.192.238
tunnel protection ipsec profile ipsec-profile
ip virtual-reassembly
!
router ospf 100
router-id 1.1.1.1
redistribute static subnets route-map static2ospf
!
ip route 172.16.0.0 255.255.0.0 Tunnel100 169.254.100.2 tag 100 track 100
!
ip sla 10
icmp-echo 169.254.100.2 source-ip 169.254.100.1
frequency 5
ip sla schedule 10 start-time now
!
route-map static2ospf permit 10
match tag 100
Cisco Router 2:
track 100 ip sla 10 reachability
!
crypto keyring KEYRING
local-address 10.10.2.100
pre-shared-key address 54.222.191.34 key cisco
!
crypto isakmp policy 100
encr aes
authentication pre-share
group 2
lifetime 28800
crypto isakmp keepalive 10 10
crypto isakmp profile isakmp-profile
keyring KEYRING
match identity address 54.222.191.34 255.255.255.255
local-address 10.10.2.100
!
crypto ipsec security-association replay window-size 128
!
crypto ipsec transform-set TRAN esp-aes esp-sha-hmac
mode tunnel
crypto ipsec df-bit clear
!
crypto ipsec profile ipsec-profile
set transform-set TRAN
set pfs group2
!
interface Tunnel100
ip address 169.254.200.1 255.255.255.0
ip tcp adjust-mss 1387
tunnel source 10.10.2.100
tunnel mode ipsec ipv4
tunnel destination 54.222.191.34
tunnel protection ipsec profile ipsec-profile
ip virtual-reassembly
!
router ospf 100
router-id 2.2.2.2
redistribute static subnets route-map static2ospf
!
ip route 172.16.0.0 255.255.0.0 Tunnel100 169.254.200.2 tag 100 track 100
!
ip sla 10
icmp-echo 169.254.200.2 source-ip 169.254.200.1
frequency 5
ip sla schedule 10 start-time now
!
route-map static2ospf permit 10
match tag 100
构建健壮的混合云网络——BJS DX篇
背景介绍:
近年来,随着公有云的普及,一方面,越来越多的用户选择利用公有云在弹性、灵活性等方面的优势,在云上部署新的应用系统,另一方面,大量的企业有很多现有的本地基础设施投资,所以企业上云的过程并不是一触而就的,期间势必存在云应用与本地数据中心应用并存的局面,为了更好的融合云与本地数据中心的应用环境,实现整体应用系统的稳定性和高可用性,构建一个健壮的混合云网络至关重要。
在AWS上,用来连接AWS与本地数据中心的方式主要有以下3种:
1. 纯VPN组网
2. 纯专线组网
3. VPN与专线的混合组网
其中,对于AWS中国区来讲,由于AWS自身的VPN服务VGW目前尚未落地,客户急需要一个替代方案,能够达到类似于VGW的冗余及故障切换功能。
本篇主要讲述第二种组网方式,着眼点在于如何实现混合云网络的健壮性及故障自愈。
对于第一,第三种组网方式的高可用实现,请参考:
《构建健壮的混合云网络——BJS VPN篇》
《构建健壮的混合云网络——BJS DX+VPN篇》
对于如何实现对VPN流量的监控、故障告警及事件日志搜集,请参考:
《构建健壮的混合云网络——BJS DX+VPN篇》
拓扑图:
AWS与本地站点之间建立两条专线,为了保证一条专线故障后,剩下的专线能够承载所有的业务流量,建议使用主备模式,考虑到高可用,建议两条专线分别终结在SINNET和CIDS两个DX Location,并且可以使用两家专线提供商的链路。
配置步骤:
1. 申请专线
小于500M的专线由AWS APN Partner提供,这里以APN Partner方案为例,大于1G的专线接入请参考如下文档:
https://www.amazonaws.cn/en/documentation/directconnect/
向APN Partner申请链路,根据要求提供相关信息,通常包括用户AWS账号,专线带宽等信息。
2. 接受连接并创建virtual interface
当APN Partner建立好专线后,登入management console,选择Direct Connect服务,将可以看到相关的连接,需要选择接受连接。
创建Virtual Interface。
选择创建Private Virtual Interface,设置接口名称并与相关VPC的VGW关联
根据自己的需要设置互联地址及本地站点的AS号
3. 下载本地站点端路由器的配置
4. 修改本地路由器端BGP配置,实现主备冗余
a. AWS侧出向流量主备通过AS-PATH属性实现
b. 本地站点侧出向流量主备通过Local-Preference属性实现
下面是本地站点侧,备份链路路由器上的参考配置:
route-map LOCAL-PRE permit 10
set local-preference 50
!
route-map PREPEND permit 10
set as-path prepend 1111 1111
!
router bgp 1111
network 0.0.0.0
neighbor 169.254.10.2 remote-as 17493
neighbor 169.254.10.2 route-map LOCAL-PRE in
neighbor 169.254.10.2 route-map PREPEND out
5. 确认接口up
6. 设置需要通过专线访问本地站点的路由表的下一跳为VGW
构建健壮的混合云网络——BJS DX+VPN篇
背景介绍:
近年来,随着公有云的普及,一方面,越来越多的用户选择利用公有云在弹性、灵活性等方面的优势,在云上部署新的应用系统,另一方面,大量的企业有很多现有的本地基础设施投资,所以企业上云的过程并不是一触而就的,期间势必存在云应用与本地数据中心应用并存的局面,为了更好的融合云与本地数据中心的应用环境,实现整体应用系统的稳定性和高可用性,构建一个健壮的混合云网络至关重要。
在AWS上,用来连接AWS与本地数据中心的方式主要有以下3种:
1. 纯VPN组网
2. 纯专线组网
3. VPN与专线的混合组网
其中,对于AWS中国区来讲,由于AWS自身的VPN服务VGW目前尚未落地,客户急需要一个替代方案,能够达到类似于VGW的冗余及故障切换功能。
本篇主要讲述第三种组网方式,着眼点在于如何实现混合云网络的健壮性及故障自愈。
此外笔者始终认为“Network is not just ping success”,尤其对于大型企业来说,网络流量的监控,故障事件的告警,日志的搜集检索等功能并非可选项,所以本篇也会顺带介绍如何在AWS云上实现这些功能。
对于第一,第二种组网方式的高可用实现,请参考:
《构建健壮的混合云网络——BJS VPN篇》
《构建健壮的混合云网络——BJS DX篇》
注意:本篇以AWS中国区VGW尚未落地为前提,VPN部分以开源软件实现,但应用场景并不仅限于AWS中国区,如何客户需要一些VGW暂时无法满足的功能,同样可以在AWS Global利用本篇搭建符合自身需求的解决方案,具体可能的需求包括但不限于:
1. 需要使用VGW暂时不支持的加解密算法
2. 需要使用VGW暂时不支持的hash算法
3. 需要使用证书认证
4. All in one解决方案,VPN设备除了提供VPN功能外,还需要提供防火墙,NAT等功能
拓扑图:
对于DX与VPN互备的场景,有如下几种情况:
1. 1条DX+1条VPN
2. 2条DX+1条VPN
3. 1条DX+2条VPN
4. 2条DX+2条VPN
对于1,2两种场景下,可以简单地通过调整Private-1,Private-2的路由表实现AWS侧的主备,即:流量优先选择DX专线,在专线故障时切换到VPN链路。
启用路由传递,路由表中会出现一条10.10.0.0/16,target为VGW的路由
设置一条静态路由10.0.0.0/8,target为VPN设备的eni
由于路由最长匹配的原则,默认去往本地站点10.10.0.0/16的流量会通过VGW走专线,当专线发生故障的时候,10.10.0.0/16的路由不会传递进入路由表,此时10.0.0.0/8的路由生效,流量切换到VPN链路。
对于3,4两种场景下,无法通过上述方式在两条VPN链路之间切换,需要部署拓扑图中的monitor设备来监控DX和VPN链路及VPN设备的健康状态并实现链路切换。
本例主要介绍monitor及Strongswan设备上的脚本功能,及如何与监控,告警相结合。
VPC基本配置,DX基本配置,Strongswan配置及本地站点切换方式请参考:
《构建健壮的混合云网络——BJS VPN篇》
《构建健壮的混合云网络——BJS DX篇》
1. 链路切换逻辑:
当专线链路正常时,设置服务器的路由指向VGW,流量通过专线传输,当监测到专线故障时,将服务器路由指向相同AZ中的Strongswan,并且开始监测Strongswan实例及VPN链路的健康状态,当一条VPN链路发生故障时,切换相应流量跨AZ传输给另一个AZ中的Strongswan,当其中一个AZ的Strongswan发送故障时,切换流量的同时,通过stop/start该Strongswan恢复实例。
2. 除了链路切换功能外,通过monitor及Strongswan上运行脚本能实现故障告警,VPN流量统计及事件日志收集检索功能:
SNS邮件及短信告警:
CloudWatch针对VPN流量监控:
Elasticsearch & Kibana做事件日志收集及检索:
可以针对site,dx,vpn做检索:
所有脚本可以从如下的github上下载得到:
3. 脚本功能说明:
3.1 monitor实例上运行的脚本:
monitor.sh:
1. 实现DX链路,VPN链路及VPN设备的健康检测并修改服务器路由切换流量
2. 发现故障后,产生告警通知,通过SNS服务邮件及短信通知相关运维人员
3. 本地产生故障日志,通过logstash输出到Elasticsearch服务存储
注:SNS短信通知目前BJS暂不支持,Elasticsearch & Kibana服务在BJS需要自己搭建
monitor实例需要对路由表做操作,并与SNS服务交互,所以需要赋予相关的角色
其中,monitor policy的配置如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:DescribeInstances",
"ec2:CreateRoute",
"ec2:ReplaceRoute",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
3.2 Strongswan实例上运行的脚本:
tunnel_init.sh:创建tunnel接口及路由相关流量到tunnel口
traffic_monitor.sh:收集进出tunnel口的VPN流量统计信息,通过自定义metric发送到CloudWatch中,实现VPN流量的监控
ipsec.conf/ipsec.secrets配置文件:Strongswan配置文件,建立ipsec vpn隧道
Strongswan实例需要收集VPN流量信息并与CloudWatch交互,所以需要赋予相关的角色
4. 脚本使用方法:
monitor.sh:运行在monitor实例上,monitor实例需要拥有操控路由表,SNS等
monitor.sh的如下脚本语句需要做相应的修改
VPN_ID1="i-0e1466e8a5dd4892c"
VPN_ID2="i-0430fe110cdec5835"
VGW_ID="vgw-078bcc55"
VPN_RT_ID1="rtb-468f5222"
VPN_RT_ID2="rtb-4b8f522f"
DX_IP="10.10.3.100"
Remote_IP1="169.254.100.1"
Remote_IP2="169.254.200.1"
logstash_site="Singapore"
litterbin=$(aws sns publish --region ap-southeast-1 --topic-arn "arn:aws:sns:ap-southeast-1:93870664XXXX:DCI-Status" --subject "Status of DCI between Singapore and Ireland Changed!" --message file://logfile)
litterbin=$(aws sns publish --region ap-southeast-1 --phone-number "+861860135XXXX" --message file://logfile)
其中VPN_ID1,VPN_ID2分别为Strongswan-1,Strongswan-2的instance id,VGW_ID为VGW的id,VPN_RT_ID1,VPN_RT_ID2分别为Private-1,Private-2关联的路由表id,DX_IP为DX链路的检测ip,通常为专线提供商MPLS VPN网络的PE设备或者是本地站点的出口路由器公网ip,Remote_IP1,Remote_IP2分别为本地站点两条VPN的隧道口ip,logstash_site为AWS站点标示,该值会体现在告警及日志中,用于区分多个AWS站点。
–region,–topic-arn,–phone-number根据需要修改,其中SNS的topic需要事先创建并且通过相关邮箱订阅来接收消息。
所有事件日志会先写入本地/tmp/logstash.txt文件中,通过logstash上传给elasticsearch。
修改/etc/logstash/conf.d/logstash.conf
input {
file {
path => "/tmp/logstash.txt"
codec => json
}
}
output {
elasticsearch {
hosts => "http://search-test-cfwkwatg5unnpsgvbd5lyruquy.ap-southeast-1.es.amazonaws.com"
index => "XXXX"
}
}
可以设置/etc/rc.d/rc.local文件,使monitor实例开机运行monitor.sh脚本
vpn_monitor.sh:运行在Strongswan实例上,创建VPN隧道接口及相关路由
traffic_monitor.sh:运行在Strongswan实例上,收集隧道接口的流量信息并以自定义metric的方式传输给CloudWatch服务
可以设置/etc/rc.d/rc.local文件,使Strongswan实例开机运行vpn_monitor.sh和traffic_monitor脚本