VPC 中的 AWS Lambda 在 NAT 后面没有互联网访问权限
AWS Lambda in VPC doesn't have internet access behind NAT
我的问题是我 运行 在具有 IGW 的 VPC 内的 NAT 后面的 Lambda 函数无法访问互联网上的任何内容。
我想做的是创建一个 VPC,它具有:
- 互联网网关;
- 2 个私有子网(
PrivateA
和 PrivateB
)分别位于可用性区域 A
和 B
;
- 1 public 个子网 (
PublicA
) 在可用区 A
PublicA
子网中的 NAT 网关
PrivateA
和 PrivateB
有一条路由 table 将 0.0.0.0/0
路由到 NAT 网关。
PublicA
有一条路由 table 将 0.0.0.0/0
路由到互联网网关。
- 私有子网以及 public 子网具有允许所有入口和出口流量的访问控制列表。
那部分作品。
接下来,我想在 VPC 中创建一个 Lambda 函数。我将其放入 PrivateA
和 PrivateB
并为其分配一个允许所有出口和入口流量的安全组。
下面是一个重现问题的独立示例(整个模板)。我已经阅读了 Internet 上所有可能的文档和文章,所以如果有人能指出正确的方向,我将不胜感激。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Vpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": true,
"EnableDnsHostnames": true,
"InstanceTenancy": "default"
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway"
},
"VpcGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": { "Ref": "Vpc" },
"InternetGatewayId": { "Ref": "InternetGateway" }
}
},
"ElasticIP":{
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatGateway": {
"Type": "AWS::EC2::NatGateway",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "ElasticIP", "AllocationId" ] },
"SubnetId": { "Ref": "SubnetAPublic" }
}
},
"SubnetAPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.0.0/19",
"MapPublicIpOnLaunch": true,
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetAPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.64.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetBPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.96.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePublic": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePrivate": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTableAssociationAPublic": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPublic" },
"RouteTableId": { "Ref": "RouteTablePublic" }
}
},
"RouteTableAssociationAPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTableAssociationBPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTablePrivateInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePrivate" },
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway" }
}
},
"RouteTablePublicInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePublic" },
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "InternetGateway" }
}
},
"NetworkAclPublic": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"NetworkAclPrivate": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetNetworkAclAssociationAPublic": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPublic" },
"NetworkAclId": { "Ref": "NetworkAclPublic" }
}
},
"SubnetNetworkAclAssociationAPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"SubnetNetworkAclAssociationBPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"NetworkAclEntryInPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryOutPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryInPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/16"
}
},
"NetworkAclEntryOutPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"LambdasSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Lambdas security group",
"SecurityGroupEgress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"SecurityGroupIngress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"VpcId": { "Ref": "Vpc" }
}
},
"LambdaFunctionExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
}
},
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.lambda_handler",
"Runtime": "python2.7",
"Role": {
"Fn::GetAtt": ["LambdaFunctionExecutionRole", "Arn"]
},
"Code": {
"ZipFile": {
"Fn::Join": ["\n", [
"import urllib2",
"def lambda_handler(event, context):",
"\tresponse = urllib2.urlopen('http://python.org/')",
"\treturn response.read()"
]]
}
},
"VpcConfig": {
"SecurityGroupIds": [
{ "Fn::GetAtt": [ "LambdasSecurityGroup", "GroupId"] }
],
"SubnetIds": [
{ "Ref": "SubnetAPrivate" },
{ "Ref": "SubnetBPrivate" }
]
}
}
}
}
}
连接失败的原因在于 "NetworkAclEntryInPrivateAllowVpc" 和 "NetworkAclEntryOutPrivateAllowVpc" 的 ACL 配置。
如果您打开从“0.0.0.0/16”到“0.0.0.0/0”的 CIDR 块,Lambda 可以访问互联网。
我不太了解 NAT,但 NAT 流量似乎被该 ACL 规则阻止了。
我的问题是我 运行 在具有 IGW 的 VPC 内的 NAT 后面的 Lambda 函数无法访问互联网上的任何内容。
我想做的是创建一个 VPC,它具有:
- 互联网网关;
- 2 个私有子网(
PrivateA
和PrivateB
)分别位于可用性区域A
和B
; - 1 public 个子网 (
PublicA
) 在可用区A
PublicA
子网中的 NAT 网关PrivateA
和PrivateB
有一条路由 table 将0.0.0.0/0
路由到 NAT 网关。PublicA
有一条路由 table 将0.0.0.0/0
路由到互联网网关。- 私有子网以及 public 子网具有允许所有入口和出口流量的访问控制列表。
那部分作品。
接下来,我想在 VPC 中创建一个 Lambda 函数。我将其放入 PrivateA
和 PrivateB
并为其分配一个允许所有出口和入口流量的安全组。
下面是一个重现问题的独立示例(整个模板)。我已经阅读了 Internet 上所有可能的文档和文章,所以如果有人能指出正确的方向,我将不胜感激。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Vpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": true,
"EnableDnsHostnames": true,
"InstanceTenancy": "default"
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway"
},
"VpcGatewayAttachment": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": { "Ref": "Vpc" },
"InternetGatewayId": { "Ref": "InternetGateway" }
}
},
"ElasticIP":{
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatGateway": {
"Type": "AWS::EC2::NatGateway",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"AllocationId": { "Fn::GetAtt": [ "ElasticIP", "AllocationId" ] },
"SubnetId": { "Ref": "SubnetAPublic" }
}
},
"SubnetAPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.0.0/19",
"MapPublicIpOnLaunch": true,
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetAPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.64.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetBPrivate": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": { "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ] },
"CidrBlock": "10.0.96.0/19",
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePublic": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTablePrivate": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"RouteTableAssociationAPublic": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPublic" },
"RouteTableId": { "Ref": "RouteTablePublic" }
}
},
"RouteTableAssociationAPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetAPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTableAssociationBPrivate": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"RouteTableId": { "Ref": "RouteTablePrivate" }
}
},
"RouteTablePrivateInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePrivate" },
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NatGateway" }
}
},
"RouteTablePublicInternetRoute": {
"Type": "AWS::EC2::Route",
"DependsOn": [ "VpcGatewayAttachment" ],
"Properties": {
"RouteTableId": { "Ref": "RouteTablePublic" },
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "InternetGateway" }
}
},
"NetworkAclPublic": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"NetworkAclPrivate": {
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "Vpc" }
}
},
"SubnetNetworkAclAssociationAPublic": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPublic" },
"NetworkAclId": { "Ref": "NetworkAclPublic" }
}
},
"SubnetNetworkAclAssociationAPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties":{
"SubnetId": { "Ref": "SubnetAPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"SubnetNetworkAclAssociationBPrivate": {
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "SubnetBPrivate" },
"NetworkAclId": { "Ref": "NetworkAclPrivate" }
}
},
"NetworkAclEntryInPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryOutPublicAllowAll": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPublic" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"NetworkAclEntryInPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": false,
"CidrBlock": "0.0.0.0/16"
}
},
"NetworkAclEntryOutPrivateAllowVpc": {
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"NetworkAclId": { "Ref": "NetworkAclPrivate" },
"RuleNumber": 99,
"Protocol": -1,
"RuleAction": "allow",
"Egress": true,
"CidrBlock": "0.0.0.0/0"
}
},
"LambdasSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Lambdas security group",
"SecurityGroupEgress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"SecurityGroupIngress": [
{ "CidrIp": "0.0.0.0/0", "IpProtocol": "-1" }
],
"VpcId": { "Ref": "Vpc" }
}
},
"LambdaFunctionExecutionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
]
}
},
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Handler": "index.lambda_handler",
"Runtime": "python2.7",
"Role": {
"Fn::GetAtt": ["LambdaFunctionExecutionRole", "Arn"]
},
"Code": {
"ZipFile": {
"Fn::Join": ["\n", [
"import urllib2",
"def lambda_handler(event, context):",
"\tresponse = urllib2.urlopen('http://python.org/')",
"\treturn response.read()"
]]
}
},
"VpcConfig": {
"SecurityGroupIds": [
{ "Fn::GetAtt": [ "LambdasSecurityGroup", "GroupId"] }
],
"SubnetIds": [
{ "Ref": "SubnetAPrivate" },
{ "Ref": "SubnetBPrivate" }
]
}
}
}
}
}
连接失败的原因在于 "NetworkAclEntryInPrivateAllowVpc" 和 "NetworkAclEntryOutPrivateAllowVpc" 的 ACL 配置。
如果您打开从“0.0.0.0/16”到“0.0.0.0/0”的 CIDR 块,Lambda 可以访问互联网。
我不太了解 NAT,但 NAT 流量似乎被该 ACL 规则阻止了。