AWS GWLB对访问NLB流量做安全检测
B站视频:https://www.bilibili.com/video/BV1wt4y1K7kz/?spm_id_from=333.999.0.0
一、架构图
这个设计的核心在于路由表的设计,可以根据下面的架构图示,理解路由流量走向。(我发现公众号对图片压缩特别厉害,暂时没有找到上传原图的办法。如果你和我一样有强迫症,可以找我要高清图片)

实验环境一共有两个VPC,左边的是业务VPC,里面有两个APP模拟HTTP的业务,EC2放在私有子网里面,在不同的AZ。
有一个面向互联网的Network Load Balancer,向公网发布了这个HTTP的服务,这样互联网上的用户,就可以通过NLB访问后面的业务。我们要做的是把这个流量,引导到防火墙上去,做安全检测。这里使用Linux的iptables
来模拟防火墙。
另外,APP可以通过NAT GW上网,这个APP主动访问互联网的流量,也需要送到防火墙上去,做安全检测。所以,APP有两种流量都需要送到防火墙上去做安全检测,下面看一下APP的两种流量路径。
一、来自于互联网对NLB访问的流量路径。
-
首先,互联网上的用户,对NLB的公有DNS发起请求,这个DNS请求,会解析到NLB的两个公网IP地址,然后流量通过ISP路由,到达AWS的IGW上。 -
因为IGW关联了一个Ingress Route Table,发现去往NLB所在子网的路由指向GWLB endpoint1,和GWLB endpoint2,这里假设现在解析的主IP是Endpoint2所在的网段,这样路由会送到GWLB Endpoint2。 -
Endpoint2收到流量之后,会通过Private Link,把流量发送到GWLB上。 -
GWLB会通过GENEVE封装报文,把流量发送到防火墙。 -
防火墙做完安全检测之后,又会把流量送回给GWLB,然后通过Private Link,送到GWLB Endpoint2。 -
注意,到达GWLB Endpoint2之后,查询的是GWLB Endpoint2关联的Public Route Table,因为目的地址是NLB subnet2网段,所以匹配到local路由,将流量送给NLB。 -
流量到NLB之后,因为侦听组关联了APP实例,所以NLB将流量发送到实例的主接口,这里查询的是NLB所在子网的local路由。 -
最后,流量抵达了APP。以上就是来自互联网,对NLB发起的请求,流量经过防火墙之后,再抵达APP的过程。
继续看一下回包流程。
-
注意,对于来自NLB的流量,EC2并不查询所在子网的路由表,而是直接返回给NLB(这个点很有意思,有机会单独再聊NLB的行为)。 -
NLB收到报文之后,查询所在子网路由表,因为回包是互联网上的地址,所以会匹配到默认路由,将报文发送到GWLB Endpoint2。 -
接下来又是一样的流程,流量会经过Private Link到防火墙绕一圈再回来。 -
流量回到GWLB Endpoint2上之后,会匹配到默认路由,将流量通过IGW发送到互联网上。
以上就是完整的从互联网对NLB发起请求和回包的流程。
二、APP1主动访问互联网的流量路径
-
APP1对互联网地址发起请求,APP1查询子网关联的路由表,匹配到默认路由,流量送到NAT GW1。 -
NAT GW1收到流量后,查询路由表,默认路由把流量送给GWLB Endpoint1,发送时会对源IP地址做NAT转换。 -
流量到GWLB Endpoint1之后,通过Private Link把流量送到防火墙检测,然后再发回来。 -
GWLB Endpoint1收到流量之后,默认路由将流量送往IGW到达互联网,源地址是NAT GW1的公网IP地址。
继续看回包流程。
-
互联网上的主机收到报文以后,源地址是NAT GW1的公网IP地址,报文通过ISP路由,流量到达AWS的IGW。 -
到达IGW之后,会查询Ingress Route Table,去往NAT GW1网段的路由送到GWLB Endpoint1。 -
流量到GWLB Endpoint1之后,通过Private Link把流量送到防火墙检测,然后再发回来。 -
GWLB Endpoint1收到流量之后,匹配到local路由,将流量发送到NAT GW1。 -
NAT GW1收到报文之后,查询NAT转换表项,目的地址匹配到local路由表,将流量发送到APP1。
二、创建实验环境
通过CloudFormation创建实验环境,堆栈需要7分钟左右的时间创建完成。
上传堆栈文件。
编辑堆栈名称,修改实例密钥。
允许创建IAM资源。
Parameters:
EC2InstanceAmiId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
Environment:
Type: String
AllowedValues:
- dev
- prod
Default: dev
MyKeyPair:
Description: Amazon EC2 Key Pair
Type: AWS::EC2::KeyPair::KeyName
Default: Global_Tokyo_KeyPair
WebServerPort:
Description: Apache Http Server Port
Type: String
Default: 8443
AllowedValues:
- 8443
- 8888
- 8088
Resources:
BastionSsmRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
BastionSsmPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: PrivatelianceInstanceAccess
PolicyDocument:
Statement:
- Effect: Allow
Action:
- ssm:DescribeAssociation
- ssm:GetDeployablePatchSnapshotForInstance
- ssm:GetDocument
- ssm:DescribeDocument
- ssm:GetManifest
- ssm:GetParameter
- ssm:GetParameters
- ssm:ListAssociations
- ssm:ListInstanceAssociations
- ssm:PutInventory
- ssm:PutComplianceItems
- ssm:PutConfigurePackageResult
- ssm:UpdateAssociationStatus
- ssm:UpdateInstanceAssociationStatus
- ssm:UpdateInstanceInformation
Resource: "*"
- Effect: Allow
Action:
- ssmmessages:CreateControlChannel
- ssmmessages:CreateDataChannel
- ssmmessages:OpenControlChannel
- ssmmessages:OpenDataChannel
Resource: "*"
- Effect: Allow
Action:
- ec2messages:AcknowledgeMessage
- ec2messages:DeleteMessage
- ec2messages:FailMessage
- ec2messages:GetEndpoint
- ec2messages:GetMessages
- ec2messages:SendReply
Resource: "*"
Roles:
- !Ref BastionSsmRole
BastionSsmProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref BastionSsmRole
#=========================================SecVpc========================================#
# 创建SecVpc
SecVpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.100.10.0/16
EnableDnsSupport: 'true'
EnableDnsHostnames: 'true'
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc
# 创建IGW并且关联到VPC
SecVpcIGW:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpcIGW
SecVpcAttachIgw:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
VpcId: !Ref SecVpc
InternetGatewayId: !Ref SecVpcIGW
#---------------------------SecVpc创建6个子网-------------------------------------#
# SecVpc AZ1内创建公有子网
SecVpcAz1PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.10.0/24
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Public-Subnet
# SecVpc AZ2内创建公有子网
SecVpcAz2PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.20.0/24
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Public-Subnet
# SecVpc AZ1内创建私有子网
SecVpcAz1PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.30.0/24
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Private-Subnet
# SecVpc AZ2内创建私有子网
SecVpcAz2PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.40.0/24
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Private-Subnet
# SecVpc AZ1内创建TGW子网
SecVpcAz1TgwSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.50.0/24
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ1-TGW-Subnet
# SecVpc AZ2内创建TGW子网
SecVpcAz2TgwSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref SecVpc
CidrBlock: 10.100.60.0/24
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: ""
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ2-TGW-Subnet
#---------------------------SecVpc创建路由表-------------------------------------#
# 公有子网路由表及关联
SecVpcAz1PublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref SecVpc
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Public-RouteTable
SecVpcAz1PublicRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref SecVpcAz1PublicRouteTable
SubnetId: !Ref SecVpcAz1PublicSubnet
SecVpcAz2PublicRouteTable:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref SecVpc
Tags:
-