从零搭建AWS网络(二): ELB与NAT Gateway


April 19, 2021

在上一篇文章中从零搭建AWS网络(一): VPC与Internet Gateway中,我们学习了如何从零开始搭建一套最简单的AWS网络并通过Internet Gateway来向公网提供服务。在文章的最后我留下了两个问题:

  • 没有详细配置Security Group等安全措施,安全性无法得到保障
  • 实例直接配置了公网ip地址,缺少安全性和可扩展性,占用宝贵的ip资源

在今天的文章里,我们就来通过添加ELB,NAT Gateway等设施来解决这些问题。

1. 网络分层

目前为止,我们只有一层可访问公网的子网Public Subnet,整个VPC的结构可以简化地如下表示:

public-arch

为了达到保护数据/主机安全的目的,我们需要将网络进行分层,把EC2主机从一个可以直接与公网通信的子网中拿出来,单独放入一个与外界隔绝的子网。如下图所示。

private-arch

我们可以去VPC -> Subnets -> Create Subnet 来新建一个子网,Subnet name填写private-subnet-1。CIDR block可以选择172.31.1.0/24, 这个子网的ip分配空间为172.31.1.0~172.31.1.255, 与我们在之前文章中配置的Public Subnet的172.31.0.0/24完全没有重合。Availability Zone这里就选择与另一个子网相同吧,因为在AWS中,跨AZ通信一般都是要额外收费的,这里我们先不考虑可用性。因为我们不想将这个子网直接与Internet Gateway相连。所以需要给他额外配置一个Route Table。

在VPC -> Route Tables -> Create route table 中创建一个新的路由表,选择我们之前创建的VPC。在在VPC -> Subnets里找到我们刚才创建的private-subnet-1并切换到Route Table选项卡,点击Edit route table association来将我们刚才创建的新路由表分配给这个子网。之后我们的EC2主机就可以在这个子网中部署了。

不过由于这个子网并没有网络访问的能力,部署在其中的EC2主机就算分配了公网IP,也不能从外部访问,更不能访问外网。而所有面对公网的能力都被保留在了Public Subnet中。此时Public Subnet可以被称为DMZ(Demilitarized Zone),也叫边界网络。

2. Bastion Host 堡垒机/跳板机

有过开发或者运维经验的同学对堡垒机/跳板机一词肯定不陌生。在传统数据中心的网络结构中,也会经常出现这个名词。不管是云原生应用还是传统数据中心,计算资源和数据库部署的网络一般都是与公网隔离以保障安全性的。通过在Public Subnet中部署一个公网可访问的Bastion Host,再经由这台跳板机,我们就可以登录到部署在私有子网中的EC2主机了。对于这台跳板机,我们还可以专门设置Security Group规则,仅允许你个人电脑的IP以及端口22(SSH)的inbound流量,来保证不被其他人攻击。此时的网络结构变为了下图所示。

bastion

AWS有一篇文章详细地描述了如何创建跳板机,以及一些安全操作,比如对SSH进行audit log,以及对跳板机的SSH秘钥进行管理和更新等。但一个基础的跳板机的创建其实极为简单,仅需要将跳板机部署到Public Subnet,然后将Private Subnet中主机的SSH秘钥上传至跳板机,并且把跳板机以及EC2主机之间的Security Group配置成允许22端口,就能通过跳板机对EC2主机进行SSH登录了。不过登上EC2后你会发现仍然无法访问外网,并且部署在EC2上的服务并不能从公网访问。

3. NAT Gateway

由于现在的EC2主机部署在了Private Subnet中,给这台机器配置一个公网IP是没有意义的。此时EC2主机的ENI仅分配有一个私网IP。而必须持有公网IP才能访问互联网,那怎么办呢?在上篇文章中介绍过Internet Gateway可以通过将子网中的ENI持有的私网IP与公网IP进行双向NAT转换,达成了EC2主机与公网的双向通信。那对于Private Subnet中的主机,访问外网就需要一个NAT Gateway将EC2的私网IP单方向NAT转换为一个公网IP。同时,为了获取一个公网的IP,这个NAT Gateway需要与Internet Gateway相连,也就是必须部署在Public Subnet中。部署了NAT Gateway后的网络结构如图:

nat-gateway

部署NAT Gateway分为两步:

  • 在VPC -> NAT gateways -> Create NAT gateway中新建一个NAT Gateway,只要选择部署到Public Subnet,并分配一个新的Elastic IP即可
  • 在VPC -> Route tables里找到分配给Private Subnet的Route table, 点击Edit Routes编辑路由表。点击Add route,第一列填入0.0.0.0/0代表匹配所有其他ip。第二列选择NAT Gateway并选中刚才我们创建好的。

部署完毕NAT Gateway后我们的EC2主机就可以访问外网了。我们可以通过跳板机登录上机器后执行curl ip.sb,返回的IP地址即我们访问公网使用的IP。这个IP应该与我们分配给NAT GatewayElastic IP保持一致。你可以尝试多部署几台EC2主机在Private Subnet中如下图所示

nat-gateway-explained

你会发现所有主机的公网IP都与NAT Gateway一致,也就是说NAT Gateway将Private Subnet中的私网IP多对一地映射成了自己的Elastic IP,节省了IP资源。这里NAT Gateway会对outbound流量的网络回包进行处理,送达至对应的私网ip,保证从EC2发出的网络请求响应能顺利送回。但如果直接从公网访问NAT Gateway的IP地址,并不能触达私网中的EC2主机。也就是说NAT Gateway是一个从内网到公网的“单行道”。

4. Elastic Load Balancer

那如何才能安全地对外暴露EC2提供的服务呢?那就需要使用Elastic Load Balancer。顾名思义这是AWS提供的负载均衡器,总共分为三种:Application Load Balancer(ALB), Network Load Balancer(NLB), 和Classic Load Balancer(CLB)。其中ALB是针对7层(HTTP, HTTPS等等)的,NLB是针对4层(TCP, TLS, UDP等等)的,而CLB可以同时提供4层和7层服务,但已经是不被AWS推荐的过期产品,对比较新的功能的支持是有限的。ELB和Nginx, HAProxy等负载均衡器所提供的功能非常接近,但它是完全由AWS部署运维的,你只需要新建一个ELB并且配置规则即可,不需要考虑它是如何被部署的。 首先,我们去EC2 -> Load Balancers -> Create Load Balancer创建ELB

  • 首先我们选择ALB
  • Configure Load Balancer:

    • Listeners: 选择默认的HTTP和80端口
    • Availability Zones: 选择我们的VPC以及Public Subnet。如果所选的Subnet没有与Internet Gateway相连,这里会给出警告。在当前的版本AWS为了可用性会强制要求ALB部署在两个或者以上的可用区中,可以自行在一个新的可用区新建一个Public Subnet。
  • Configure Security Settings: 由于我们选择的是HTTP而不是HTTPS,所以这一步可以略过。如果要暴露HTTPS服务,可以在这一步选择HTTP证书,ALB可以帮你做HTTPS证书卸载,并且支持SNI。
  • Configure Security Groups: 选择Create a new security group。默认会为你准备好允许80端口TCP的规则。
  • Configure Routing: 使用默认配置即可,新建一个target group。
  • Register Targets: 手动选择在Private Subnet中创建的EC2主机

此时我们有了一个指向EC2主机的ALB,对EC2主机,编辑Security Group允许从ALB的Security Group来的所有流量,并且登录到主机上开启一个监听0.0.0.0:80的HTTP服务,等待ALB的Health Check健康后就能通过访问ALB提供的DNS域名访问到EC2上部署的HTTP服务了。通过在Target Group中部署多台EC2,也可以达到负载均衡的目的,配合Auto Scaling groups更是可以做到弹性伸缩。部署好ELB后的网络结构如图:

elb

5. 总结

至此,我们已经搭建了一个出具规模的二层网络,将内部可信流量与外部不可信流量区分开,并且通过NAT GatewayELB为计算资源的弹性伸缩做好了铺垫。从图中我们可以看到,不管是跳板机ELB还是NAT Gateway,所有的流量都是单向的,并且有自己的目的。我们可以通过配置不通的安全策略来控制每一条路径的安全性,使得整个网络结构安全可控。

在接下来的文章中我们会介绍:

  • 如何安全快速地在VPC中访问AWS提供的诸如S3之类的服务?
  • 如何在AWS中访问数据库?

本作品采用知识共享署名4.0署名-非商业性使用-禁止演绎(BY-NC-ND)国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,但不得对本创作进行修改,亦不得依据本创作进行再创作,不得将本创作运用于商业用途。