AWS安全组引用配置异常:EC2间Flask服务访问超时排查
问题:EC2实例间通过安全组引用访问Flask应用超时的原因分析
我搭建了以下最小可复现的Terraform环境:
terraform { required_providers { aws = { source = "hashicorp/aws" version = "5.21.0" } } } provider "aws" { region = "eu-central-1" } data "aws_ami" "amazon_linux" { most_recent = true owners = ["amazon"] filter { name = "image-id" values = ["ami-0a23a9827c6dab833"] } } resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" } resource "aws_subnet" "public" { cidr_block = "10.0.1.0/24" vpc_id = aws_vpc.main.id availability_zone = "eu-central-1a" } resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id } resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id } } resource "aws_route_table_association" "public" { subnet_id = aws_subnet.public.id route_table_id = aws_route_table.public.id } resource "aws_security_group" "inbound" { name = "ingress-ec2" description = "For the EC2 that has the inbound traffic" vpc_id = aws_vpc.main.id } resource "aws_security_group" "outbound" { name = "egress-ec2" description = "For the EC2 that has the outbound traffic" vpc_id = aws_vpc.main.id } resource "aws_vpc_security_group_ingress_rule" "main" { security_group_id = aws_security_group.inbound.id from_port = 5000 to_port = 5000 ip_protocol = "tcp" referenced_security_group_id = aws_security_group.outbound.id } resource "aws_vpc_security_group_egress_rule" "main" { security_group_id = aws_security_group.outbound.id from_port = 5000 to_port = 5000 ip_protocol = "tcp" referenced_security_group_id = aws_security_group.inbound.id } resource "aws_vpc_security_group_ingress_rule" "ssh_inbound" { security_group_id = aws_security_group.inbound.id from_port = 22 to_port = 22 ip_protocol = "tcp" cidr_ipv4 = "0.0.0.0/0" } resource "aws_vpc_security_group_ingress_rule" "ssh_outbound" { security_group_id = aws_security_group.outbound.id from_port = 22 to_port = 22 ip_protocol = "tcp" cidr_ipv4 = "0.0.0.0/0" } resource "aws_vpc_security_group_egress_rule" "internet_inbound" { security_group_id = aws_security_group.inbound.id ip_protocol = -1 cidr_ipv4 = "0.0.0.0/0" } resource "aws_vpc_security_group_egress_rule" "internet_outbound" { security_group_id = aws_security_group.outbound.id ip_protocol = -1 cidr_ipv4 = "0.0.0.0/0" } resource "aws_key_pair" "inbound" { key_name = "ingress-ec2" public_key = file(var.public_ssh_key) } resource "aws_instance" "inbound" { ami = data.aws_ami.amazon_linux.id instance_type = "t2.micro" key_name = aws_key_pair.inbound.id subnet_id = aws_subnet.public.id security_groups = [aws_security_group.inbound.id] associate_public_ip_address = true } resource "aws_key_pair" "outbound" { key_name = "egress-ec2" public_key = file(var.public_ssh_key) } resource "aws_instance" "outbound" { ami = data.aws_ami.amazon_linux.id instance_type = "t2.micro" key_name = aws_key_pair.outbound.id subnet_id = aws_subnet.public.id security_groups = [aws_security_group.outbound.id] associate_public_ip_address = true } variable "public_ssh_key" { type = string default = "~/.ssh/test_key.pub" } output "ingress-ec2" { value = aws_instance.inbound.public_ip } output "egress-ec2" { value = aws_instance.outbound.public_ip }
在inbound EC2实例上启动简单Flask应用后,从outbound EC2实例访问该应用出现超时错误。将inbound安全组的5000端口入站规则从引用outbound安全组改为允许0.0.0.0/0后,访问恢复正常,确认是安全组配置导致的拦截。
原因分析
核心问题在于安全组引用规则匹配的是实例的私有IP,而非公网IP:
- 当你从
outbound实例访问inbound实例的公网IP时,数据包会通过互联网传输,此时数据包的源IP是outbound实例的公网IP,而非它的私有IP。 - 你配置的
aws_vpc_security_group_ingress_rule.main规则,是允许关联到outbound安全组的实例的私有IP发起的5000端口流量,公网IP不在这个规则的匹配范围内,所以被inbound安全组拦截。 - 当改为
cidr_ipv4 = "0.0.0.0/0"时,规则允许所有公网IP的流量,自然就能正常访问。
解决方案
如果想保留安全组引用的安全特性,不需要开放全公网访问,可以:
- 在
outbound实例上使用inbound实例的私有IP访问Flask应用,此时数据包在VPC内部传输,源IP是outbound的私有IP,符合安全组引用规则,能正常通过。 - 若必须使用公网IP访问,可在
inbound安全组的入站规则中添加outbound实例的公网IP作为允许的CIDR,或者保持0.0.0.0/0(不推荐生产环境使用)。
内容的提问来源于stack exchange,提问作者Kilian Calefice
相关产品推荐
相关产品推荐

