AWS 提供a guide 用于计算任何服务端点的 IP 地址以允许出口。这依赖于下载所有 AWS 端点的 IP 地址,然后过滤 AMAZON 列表中的 IP 地址,但从 EC2 列表中删除。
幸运的是,我们可以使用 aws_ip_ranges data source 在 Terraform 中直接获取这些 IP 地址,并且可以过滤 AMAZON 范围和 EC2 范围:
data "aws_region" "current" {}
data "aws_ip_ranges" "amazon" {
regions = [data.aws_region.current.name]
services = ["amazon"]
}
data "aws_ip_ranges" "ec2" {
regions = [data.aws_region.current.name]
services = ["ec2"]
}
以上示例将获取您正在运行的区域的 AMAZON 和 EC2 块(它们是 AMAZON 块的子集)的所有 IP 地址。
要从AMAZON 中删除EC2 块,我们需要使用setsubtract function:
locals {
aws_control_plane = setsubtract(data.aws_ip_ranges.amazon.cidr_blocks, data.aws_ip_ranges.ec2.cidr_blocks)
}
这应该只给我们希望允许我们的安全组出口的 IP 范围。
不幸的是,这可能超过 60 个 CIDR 范围,这相当于 60 多个规则。一个安全组是limited to a max of 60 ingress and 60 egress rules:
每个安全组可以有 60 个入站规则和 60 个出站规则
(总共制定了 120 条规则)。此配额单独执行
IPv4规则和IPv6规则;例如,一个安全组可以有 60
IPv4 流量的入站规则和 IPv6 流量的 60 个入站规则。
引用安全组或前缀列表 ID 的规则算作
IPv4 一条规则,IPv6 一条规则。
配额更改适用于入站和出站规则。这个配额
乘以每个网络接口的安全组配额
不能超过 1000。例如,如果您将此配额增加到 100,我们
减少每个网络的安全组数量的配额
10的接口。
但是,我们可以为每个接口设置多个安全组,这样我们就可以将这些范围分散到多个安全组并将多个安全组附加到实例:
为此,我们需要将我们拥有的范围列表拆分为 60 个块,然后循环遍历我们要创建的安全组资源。我们可以使用chunklist function:
locals {
aws_control_plane_chunked = chunklist(local.aws_control_plane, 60)
}
这将返回一个列表列表,每个列表最多包含 60 个 CIDR 块。
然后我们可以通过遍历这些列表来创建多个安全组:
resource "aws_security_group" "aws_only_egress" {
count = length(local.aws_control_plane_chunked)
name = "aws-only-egress-example-chunk-${count.index + 1}"
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = local.aws_control_plane_chunked[count.index]
}
}
最后我们需要将这些多个安全组附加到我们的实例:
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = aws_security_group.aws_only_egress.*.id
}