【带图操作指南】处理CIDR重叠:使用AWS PrivateLink整合VPC互联网流量(无需NLB)

处理CIDR重叠:使用AWS PrivateLink整合VPC互联网流量(无需NLB)
  • 即使在 CIDR 重叠且无法使用 Transit Gateway 的 VPC 环境中,也可以通过本文介绍的方法来汇总互联网通信(HTTP 和 HTTPS)。
  • 本文将详细解说如何利用 PrivateLink 整理并汇总 VPC 之间的通信,从而减少 NAT 网关的实用方法。
  • 如果您因 CIDR 重叠问题而在互联网通信汇总方面遇到困难,请一定参考本篇文章!

本篇文章的背景是由于向员工分配了 AWS 用户账户,导致多个 VPC 和 NAT 网关泛滥的情况。
虽然这与本文主题无直接关联,但如果您对此感兴趣,请参阅以下文章。

2024/12/04 更新
AWS announces access to VPC resources over AWS PrivateLink
通过 AWS PrivateLink,现在可以在不使用 NLB 的情况下访问 VPC 内资源。
详情请参阅以上官方文章。
我们公司原本使用 NLB,但借此机会转变为无需 NLB 的方法。

背景

我们为每个项目都建立了独立的 VPC。
我们要求使用 NAT 网关作为连接互联网的方法,但随着 VPC 数量的增加,成本已成为瓶颈。
因此,我们考虑用中转网关连接多个 VPC,并合并 NAT 网关作为互联网出口,如下图所示;

使用NAT网关进行集中出IPv4口
https://docs.aws.amazon.com/zh_cn/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/using-nat-gateway-for-centralized-egress.html

但是,我们发现在我们的环境中,Transit Gateway 无法在 VPC 之间进行连接。

原因

虽然这是我们的失误,但我们只为每个项目支付了 IAM 用户,并没有任何特定的 IP 地址带安排。
因此,许多 VPC 的 CIDR 重叠,我们无法将每个 VPC 连接到转接网关。
(或者更准确地说,它们可以连接,但转接网关路由表中指定的返回路由在多个 VPC 中重复)。

我是否可以连接到具有相同 CIDR 的 Amazon VPC?
AWS Transit Gateway 不支持具有相同 CIDR 的 Amazon VPC 之间的路由。如果您连接一个具有 CIDR 的新 Amazon VPC,与某个已连接的 Amazon VPC 相同,则 AWS Transit Gateway 不会将新的 Amazon VPC 路由传播到 AWS Transit Gateway 路由表。

https://aws.amazon.com/cn/transit-gateway/faqs/?nc1=h_ls

我想过使用私有 NAT 网关来转换为非重叠 IP 地址,如下图所示。
但是,这种方法最终会在每个 VPC 中使用一个私有 NAT 网关,无法实现节约成本的目标。

实现重叠网络之间的通信
https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/nat-gateway-scenarios.html#private-nat-overlapping-networks

方法

幸运的是,NAT 网关在每个项目中的主要用途都是通过 HTTP/HTTPS 进行互联网通信。
因此,我们使用 AWS PrivateLink 和代理服务器通过 NAT 网关聚合互联网出口,作为满足这一要求的配置。
有了 AWS PrivateLink,即使 VPC 之间的 IP 地址范围重叠,也能进行通信。
配置如下

在这个构成图中,通信源 VPC 仅显示了 4 个,但实际上存在更多的 VPC。
另外,通过将 NAT 网关或代理实例部署在区域内的每个可用区 (AZ),可以实现更高可用性的操作。

2024/12/04 更新
这里保留了曾经需要 NLB 时的配置图以供参考。
以前,PrivateLink 的流量由 NLB 接收并路由到目标。
而在最新更新中,PrivateLink 的流量似乎由资源网关 (Resource Gateway) 接收,并可路由到资源配置 (Resource Configuration) 中指定的资源。

使用 NLB 之前的配置图

管理员方面的步骤

首先,我们从创建 VPC 开始。

创建 VPC

  1. 从以下 URL 创建 VPC、子网等
    https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#CreateVpc:createMode=vpcWithResources
  2. 使用以下设置创建。 (除下划线项目外,其余均为默认设置)。
    • 要创建的资源:VPC 等
      • 这将同时创建子网等。
    • 自动生成名称标签: ☑️ 自动生成 “Proxy”。
      • 这将自动命名 VPC 和子网。 以后可以更改。
    • IPv4 CIDR 块:10.0.0.0/16
      • VPC 的私有 IP 地址范围。 以后不能更改。
      • 在连接互联网时,它与公共 IP 地址无关。
    • 可用区(AZ)数量:2
      • 这表示子网所在的 AWS 数据中心的数量。
    • 公有子网的数量:2
      • 这是可以连接到互联网的子网数量。
    • 私有子网的数量:2
      • 不能连接互联网的子网数量。
    • NAT 网关 ($): 在 1 个可用区中
      • 如果使用 NAT 网关,此设置将决定是否将其放置在所有 AZ 中。
      • 每次在一个 AZ 中创建一个 NAT 网关,因为每个 NAT 网关的数量都有成本。
      • ($)符号表示需要付费)。
    • VPC 终端节点:S3 网关
      • 这似乎允许从 VPC 直接访问 S3。
      • 附加本身是免费的,而且似乎有助于减少费用,所以我还是保留它。
图片

准备代理服务器

由于已经熟悉这个过程,我将通过 AWS CLI 命令进行操作。

  1. 使用以下 AWS CLI 命令,创建一个实例配置文件,以通过 Session Manager 连接到 EC2 实例。
# Create IAM role
aws iam create-role \
    --role-name SSMRole \
    --assume-role-policy-document '{
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "ec2.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }'

# Attach IAM policy for SSM
aws iam attach-role-policy \
    --role-name SSMRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

# Create instance profile
aws iam create-instance-profile \
    --instance-profile-name SSMRole

# Add IAM role to instance profile
aws iam add-role-to-instance-profile \
    --instance-profile-name SSMRole \
    --role-name SSMRole
  1. 使用以下 AWS CLI 命令,创建一个代理实例(Proxy Instance)的安全组,其中包含允许来自 Resource Gateway 的流量的规则。
    ※ 出站规则默认已创建,因此无需配置。
SourceProtocolPort
10.0.0.0/16 (VPC CIDR)AllAll
Inbound Rule
DestinationProtocolPort
0.0.0.0/0AllAll
Outbound Rule
# Get VPC ID
VPC_ID=$(aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=Proxy-vpc" \
    --query "Vpcs[].VpcId" \
    --output text)

# Create a security group for proxy instance
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
    --group-name Proxy-sg \
    --description "Security group for proxy instance" \
    --vpc-id $VPC_ID \
    --query 'GroupId' \
    --output text)

# Add an inbound rule to allow all traffic from VPC
aws ec2 authorize-security-group-ingress \
    --group-id $SECURITY_GROUP_ID \
    --protocol -1 \
    --cidr 10.0.0.0/16
  1. 使用以下 AWS CLI 命令,在一个私有子网中启动具有此安全组的 EC2 实例。
# Get Amazon Linux 2 AMI ID
AMI_ID=$(aws ec2 describe-images \
    --owners amazon \
    --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" \
    --query 'sort_by(Images, &CreationDate)[-1].ImageId' \
    --output text)

# Get Subnet ID for running proxy instance
SUBNET_ID=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=Proxy-subnet-private1-*" \
    --query "Subnets[].SubnetId" \
    --output text)

# Run EC2 instance for proxy
aws ec2 run-instances \
    --image-id $AMI_ID \
    --count 1 \
    --instance-type t2.micro \
    --iam-instance-profile Name=SSMRole \
    --security-group-ids $SECURITY_GROUP_ID \
    --subnet-id $SUBNET_ID \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ProxyInstance}]'
  1. 使用以下 AWS CLI 命令,通过 Session Manager 连接到 EC2 实例。
# Get EC2 instance ID
EC2_ID=$(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=ProxyInstance" \
    --query "Reservations[].Instances[].InstanceId" \
    --output text)

# Start connect by Session Manager
aws ssm start-session --target $EC2_ID
  1. 执行以下命令来设置代理服务器。
    此处仅进行了最低限度的配置,您可以根据实际用例进行自定义。
## Bellow command is at Session Manager.
# Ready for operating proxy
sh-4.2$ sudo yum -y install squid
sh-4.2$ sudo systemctl start squid
sh-4.2$ sudo systemctl enable squid
sh-4.2$ sudo lsof -i:3128
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
squid   3551 squid   11u  IPv6  33657      0t0  TCP *:squid (LISTEN)

创建 Resource Gateway

完成 Resource Gateway 的创建后,会在指定的子网中创建 ENI。
通过 PrivateLink 的流量可以视为从该 ENI 流出。

  1. 使用以下 AWS CLI 命令,创建一个包含允许 Resource Gateway 流量规则的安全组。
    ※ 出站规则默认已创建,因此无需配置。
SourceProtocolPort
0.0.0.0/0AllAll
Inbound Rule
DestinationProtocolPort
0.0.0.0/0AllAll
Outbound Rule
# Get VPC ID
VPC_ID=$(aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=Proxy-vpc" \
    --query "Vpcs[].VpcId" \
    --output text)

# Create a security group for resource gateway
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
    --group-name ResourceGateway-sg \
    --description "Security group for resource gateway" \
    --vpc-id $VPC_ID \
    --query 'GroupId' \
    --output text)

# Add an inbound rule to allow all traffic
aws ec2 authorize-security-group-ingress \
    --group-id $SECURITY_GROUP_ID \
    --protocol -1 \
    --cidr 0.0.0.0/0
  1. 从以下 URL 创建 Resource Gateway:
    https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#CreateResourceGateway
  2. 按以下配置进行创建:
    • Resource gateway name: proxy-rgw
    • IP address type: IPv4
    • VPC: Proxy-vpc
    • ☑️ us-east-1a: Proxy-subnet-private1-us-east-1a
    • ☑️ us-east-1c: Proxy-subnet-private2-us-east-1c
      • 在这些子网中会创建 ENI。
    • Security groups:ResourceGateway-sg
      • 这是分配给创建的 ENI 的安全组。
      • 必须允许从 PrivateLink 到资源的流量。
图片

创建 Resource Configuration

此处指定通过 PrivateLink 的流量的路由目标。
特定端口号的流量通过指定的 Resource Gateway 后,将路由到指定的资源。

  1. 通过以下 URL 创建 Resource Configuration:
    https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#CreateResourceConfig:
  2. 按照以下配置进行创建:
    • Name:Proxy-conf
    • Configuration type:◉ Resource
    • Type:Single
    • Protocol:TCP
    • Resource gateway:proxy-rgw
    • Resource type:◉ DNS resource
    • Domain name:proxy.awsexample.com
      • 指定了一个可解析为 Proxy Instance IP 地址的域名。
      • 稍后会提到,我原以为在这里指定域名可以启用私有 DNS,但看起来并不是这种情况。
      • 也可以直接指定 IP 地址。
    • IP address type:IPv4
    • Port ranges
      • Lower bound:1
      • Upper bound:65535
    • Allow association with shareable service networks:◉ Allow
      • 这可能是指是否允许在 Amazon VPC Lattice 的“服务网络”中关联该配置。
        此次不使用“服务网络”,因此保留默认设置。
图片

稍后会提到,与使用 NLB 的 VPC 终端节点服务不同,没有找到任何验证域名所有权的项目,且上述配置未设置 VPC 终端节点的私有 DNS 名称。
此外,虽然可以使用域名来指定路由目标资源,但前提是该域名必须指向资源的私有 IP 地址。
目前可能没有方法将公共使用的域名用作私有 DNS 名称。

用户方面的步骤

在每个项目中,我们在 VPC 上创建了 VPC 终端节点,并配置了代理 (Proxy)。

创建 VPC 终端节点

  1. 通过以下 URL 创建 VPC 终端节点:
    https://us-east-1.console.aws.amazon.com/vpcconsole/home?region=us-east-1#CreateVpcEndpoint:
  2. 按照以下设置进行配置:
    • Name tag - optional:Proxy-vpce
    • Type:Resources - New
    • Resource configurations:proxy-conf
    • VPC:<项目 VPC>
    • DNS name:☑️ Enable DNS name
    • Subnets
      • ☑️ us-east-1a:<项目子网 AZ-a>
      • ☑️ us-east-1c:<项目子网 AZ-c>
    • Security groups:<安全组 ID>
      • 需要允许来自通信源的流量的规则。
      • 我们公司建议允许来自 VPC CIDR 的所有通信。
图片

Proxy 配置

查看已创建的 VPC 终端节点时,私有 DNS 名称似乎已启用,但未显示域名。
是否可以启用尚不明确,因此我们决定暂时让各项目检查私有 IP 地址并进行设置。

  1. 您可以通过以下 URL 使用 VPC 终端节点 ID 来确认私有 IP 地址:
    https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#NIC:description=:VPC%20Endpoint%20Interface;v=3;$case=tags:false%5C,client:false;$regex=tags:false%5C,client:false
  2. 请为每个通信源服务器配置 Proxy。

目前,这种配置运行良好。
不过,分配唯一的域名将简化流程,因此能够使用私有 DNS 名称将非常有帮助。
如果有解决方法,请通过“联系我们”告知我们。

此外,未来可能会出现 Proxy 无法支持的通信情况。
为了应对这种情况,我计划为各项目规定 IP 地址的使用范围。

タイトルとURLをコピーしました