众所周知,Network Load Balancer (NLB)拥有低延迟高性能的特性,并且和Classic Load Balancer(CLB)以及Application Load Balancer(ALB)不同,NLB的IP并不会变化(不会变化意味着既不会变得不同—即纵向扩展,也不会不会变多或者变少—即横向扩展)。

但是同样的,在NLB的安全配置上也带来了一些问题。在大部分场景的配置中,NLB可以透明的传递客户端地址IP到后端,它本身除了NACL以外,是无法添加安全组的,如果你想实现更精细的配置,则需要在后端实例的安全组上做对应的配置;我们在安全组的配置中习惯采用组间引用的方式构成安全组规则,然而在NLB后面的安全组并不能实现这种规则,这就导致了我们不得不使用IP段来做为约束条件。

现在我们假设以下场景,Instance通过NLB访问Target

Image

其VPC子网情况如下

Image

在规划IP分配时,已经考虑了同一角色(层)可以使用一个IP段来指定,并且该IP段没有非同一层的IP,所以以上IP可以合并成下表

Subnet
IP Range
Public Subnet
10.0.0.0/24
InternalLB Subnet
10.0.1.0/26
Private Subnet
10.0.2.0/24

其安全组情况如下

Image

名为Public Instance的安全组允许来自互联网的SSH访问。

Image

名为Target Instance的安全组允许来自Public Instance的SSH访问,这是典型的组间引用构建安全组规则,只有当Network Interface挂载Public Instance安全组配置时,才会被认为是Target Instance这个安全组规则的源来放行。同时第一条规则放行了来自LB的健康检查(若NLB则可以在创建后固定为NLB的固定IP,这样更加安全)。

然后我们分别创建三个实例。

Image

我们此时可以尝试登录Public Instance

$ ssh ec2-user@161.189.42.250
The authenticity of host '161.189.42.250 (161.189.42.250)' can't be established.
ECDSA key fingerprint is SHA256:a6UAA2N/nAKv1ae5eAf8qyX8LD6MI/0L/1ggojiv544.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '161.189.42.250' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-0-0-68 ~]$

由于正确的安全组配置,我们也可以通过这台机器登录Target 1和Target 2

[ec2-user@ip-10-0-0-68 ~]$ ssh ec2-user@10.0.2.23
The authenticity of host '10.0.2.23 (10.0.2.23)' can't be established.
ECDSA key fingerprint is SHA256:g1LJXHhFzs3oG1chbIgGQrcxOSzkTcGCz97xUqleEN8.
ECDSA key fingerprint is MD5:f1:59:1e:bb:0f:2f:24:a2:6d:18:e6:97:d4:4b:c7:1b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.2.23' (ECDSA) to the list of known hosts.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
[ec2-user@ip-10-0-0-68 ~]$

当然由于我们没有使用ssh-agent传递私钥,导致这里登录失败,但是可以确认的是由Public Instance到Target Instance的22端口请求是正确被放行的。

然后我们来创建Target Group

Image

之后创建Internal NLB

Image

在确认Target已经通过健康检查的情况下,我们使用SSH直接访问NLB的域名

[ec2-user@ip-10-0-0-68 ~]$ ssh Demo-831c7168ce5b9392.elb.cn-northwest-1.amazonaws.com.cn

它没有响应,此时虽然设置了安全组的组间引用,但是依然不能通过NLB的域名来访问后端,这时我们就要对Target Instance的安全组做修改。

Image

我们首先删除了之前的健康检查放行规则,并且将其细化成为对NLB的两个静态IP的放行规则,然后我们添加了针对于Public Subnet的IP段放行规则。这时我们再尝试一次。

[ec2-user@ip-10-0-0-68 ~]$ ssh Demo-831c7168ce5b9392.elb.cn-northwest-1.amazonaws.com.cn
The authenticity of host 'demo-831c7168ce5b9392.elb.cn-northwest-1.amazonaws.com.cn (10.0.1.50)' can't be established.
ECDSA key fingerprint is SHA256:RzgAqW6JLU0ux3/VGB6E3UCaOtIG6gMBnLSBk5l4o9M.
ECDSA key fingerprint is MD5:d6:51:16:d4:dd:df:f4:e7:db:45:f4:c9:7e:d1:9e:89.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'demo-831c7168ce5b9392.elb.cn-northwest-1.amazonaws.com.cn,10.0.1.50' (ECDSA) to the list of known hosts.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
[ec2-user@ip-10-0-0-68 ~]$

可以确认流量已经正确被放行了。
但是这就带来了我们之前所说的问题,若Public Subnet中的实例有很多,则处于管理的方便我们往往放行的是整个Public Subnet的IP段,不能做到精细化处理,所以我们考虑引入PrivateLink,创建VPC Interface Endpoint来为这个结构引入安全组。即结构如下

Image

我们以NLB创建Endpoint服务

Image

我们先创建Endpoint创建过程中需要使用的安全组

Image

可以看到这个安全组使用了组间引用放行22端口。

然后我们创建Endpoint,注意选择关联刚创建的安全组,等待Endpoint变为可用。

Image

然后我们再对Target Instance安全组做修改

Image

可以看到,原来粗糙的IP段放行被一个组间引用替换。

结合两个安全组的修改,实现了更精细的安全组规则构成,我们尝试使用VPC Endpoint的域名来访问

[ec2-user@ip-10-0-0-68 ~]$ ssh vpce-0827a8a49ccd94735-fmsw2dd7.vpce-svc-05c034b8103b29060.cn-northwest-1.vpce.amazonaws.com.cn
The authenticity of host 'vpce-0827a8a49ccd94735-fmsw2dd7.vpce-svc-05c034b8103b29060.cn-northwest-1.vpce.amazonaws.com.cn (10.0.0.110)' can't be established.
ECDSA key fingerprint is SHA256:g1LJXHhFzs3oG1chbIgGQrcxOSzkTcGCz97xUqleEN8.
ECDSA key fingerprint is MD5:f1:59:1e:bb:0f:2f:24:a2:6d:18:e6:97:d4:4b:c7:1b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'vpce-0827a8a49ccd94735-fmsw2dd7.vpce-svc-05c034b8103b29060.cn-northwest-1.vpce.amazonaws.com.cn,10.0.0.110' (ECDSA) to the list of known hosts.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
[ec2-user@ip-10-0-0-68 ~]$

可以看到22端口是正常被放行的。

虽然增加了架构的复杂度,但是我们为对内部NLB的访问增加了更精细化的安全组配置,这在一些场景下是非常适合的。以下几点需要注意:

  1. 它会影响性能,所以只在需要内部负载均衡,且负载不高的情况下可用,具体可见https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#load-balancer-performance
  2. 同样适用于面向互联网的NLB的内部请求
  3. PrivateLink会产生额外的费用,具体也可以参考https://aws.amazon.com/privatelink/pricing/