亚马逊AWS官方博客

使用Docker封装IPSec安全网关

随着云成为新常态,越来越多的客户开始采用AWS云服务,使用VPN隧道安全的连接到AWS成为一个常见的场景。本文介绍一种仅需少量交互与配置即可与多个AWS VPC建立动态路由VPN连接并在各个互联VPC之间转发流量的方案。该方案主要使用了Docker、IPSec套件strongSwan、动态路由软件BIRD,并在此基础上,使用AWS SDK for Python( Boto 3)、docker-py等实现快速建立与AWS VPC的动态VPN。

项目中使用的Dockerfile、相关的shell脚本以及Python应用等源文件均已经在这里开放,做为一种快速部署Customer Gateway的方法,供各位读者参考。

本文假定读者从概念上理解AWS VPC、IPSec VPN以及动态路由协议BGP。如果希望了解更多如何与AWS VPC建立VPN连接的信息,读者可以参考 AWS VPC 网络管理员指南。

如何使用

我们从最基本的场景开始,假定您需要将本地网络与单个AWS VPC通过IPSec隧道互联。

图中Customer Gateway应为一台可以访问Internet且IP固定的 Linux服务器, 这台服务器将作为IPSec网关和BGP路由器,将内部网络与AWS VPC通过IPSec隧道和BGP动态路由协议连接起来。

在Customer Gateway上执行如下预备工作:

一、我们需要 预先安装和配置好docker引擎;

二、我们的脚本使用了Python和一些第三方库,所以需要安装Python 2.7或更新版本以及Python包管理工具,例如pip

三、通过pip安装如下软件包;

a. boto3 —— AWS SDK for Python,用于获取VPN连接的配置信息

b. xmltodict —— 便于python处理XML格式的数据

c. docker-py —— 用于连接docker engine并创建、运行容器

四、配置boto3连接AWS的 IAM凭证,需要注意使用的IAM用户需要拥有执行describe_vpn_connections API所需的权限。

$ cat  ~/.aws/credentials

[default]

aws_access_key_id = YOUR_KEY

aws_secret_access_key = YOUR_SECRET

建立连接

参照AWS VPC用户指南中关于“设置VPN连接”章节的指导,完成如下步骤:

步骤一、创建虚拟专用网关,附加到目标VPC并启用路由传播;

步骤二、创建客户网关,输入Customer Gateway的公网IP地址,选择动态路由,并输入65000作为本地网络的BGP ASN号;

步骤三、创建虚拟专用网关和客户网关之间的VPN连接,每个VPN连接包含两条相护冗余的VPN隧道;

步骤四、在Customer Gateway上执行peer.py 脚本,传入目标VPC所在的region名称和vpn连接id,该脚本将会调用AWS API下载指定的VPN连接的配置信息、然后连接Docker Engine创建cgw 容器并将关键参数作为环境变量传入容器;

步骤五、cgw容器会根据传入的环境变量完成自举并发起到AWS侧虚拟专用网关的2条动态路由VPN连接。

CGW容器的实现

正常的容器运行中的进程信息可见下图

可以看到容器中共有4个进程,其功能分别为:

一、cgw.sh 容器启动脚本,主要在容器开始运行时完成以下动作;

a. 根据传入的环境变量生成strongSwan、BIRD的配置文件

b.  配置virtual tunnel interface以便将两条ipsec隧道暴露给动态路由软件

c. 拉起strongSwan、BIRD

二、strongSwan守护进程,负责与虚拟专用网关协商和交换加密、解密密钥、调用Linux内核中IPSec相关的系统调用设定隧道;

三、BIRD守护进程;

a. 与虚拟专用网关的两个端点分别建立BGP邻居关系并以10秒的间隔持续检测对端是否健康

b. 与本地网络中其他路由器建立BGP邻居关系并将路由信息发布到本地网络和AWS VPC;实现本地网络与AWS VPC的互通

c. 当两条隧道中的一条由于某种原因发生故障,BIRD会检测到邻居状态的改变从而自动将流量切换到另外一条健康的隧道中去,从而实现了VPN连接的冗余

扩展性和可用性

一、如果需要与多个不同的VPC建立多条VPN连接,那么只需要重复前面建立连接的步骤在同一台服务器上创建多个cgw容器,分别建立与不同的虚拟专用网关的VPN连接即可。如下图所示

但是要做到不同VPC之间的流量互通,我们还需要在多个cgw容器之间建立iBGP邻居关系。传统的iBGP互联要求full mesh,这里我们为了简化部署和配置,可以在容器所在服务器上运行BIRD并将其配置为路由反射器,所有cgw容器都与路由反射器建立邻居关系并学习到其他容器、隧道的路由信息,从而实现多个VPN连接之间的流量互通。

二、如果需要保证高可用,需要在不同的VPN网关之间实现互为备份,那么可以通过运行两台物理服务器,各自建立与AWS VPC的VPN连接,通过动态路由协议来实现故障流量切换;

三、如果需要进一步增大吞吐量,超出单个服务器的可用带宽的情况下,我们可以将cgw容器分散到多个物理服务器上实现水平扩展;同样的,在服务器之间需要建立iBGP邻居关系并交换路由信息;

作者介绍:

丁成银

亚马逊AWS解决方案架构师,获得AWS解决方案架构师专业级认证和DevOps工程师专业级认证。负责基于AWS的云计算方案架构的咨询和设计,同时致力于AWS云服务在国内的应用和推广,在数字媒体、电信、互联网和游戏、企业混合IT等方面有着丰富的实践和设计经验。在加入AWS之前,历任数字媒体娱乐系统工程师、宽带业务架构师、云解决方案架构师,负责数字媒体娱乐系统、云计算解决方案等服务的咨询和架构设计工作。