VPC 中的 Lambda 函数无法访问互联网
Lambda Function in VPC has no Internet Access
我的 Lambda 函数可以访问 VPC 中的其他资源,但是一旦它尝试向 Internet 发出请求,它就会超时。我有以下内容:
- 两个私有子网
- 将 0.0.0.0/0 路由到 Internet 网关的路由 Table。
- 几个 ACL 规则和一个 Lambda 安全组
任何帮助都会有所帮助。这是我的 CF 模板:
AWSTemplateFormatVersion: 2010-09-09
Description: VPC Stack
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: 'us-east-1b'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: 'us-east-1e'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Route:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
SubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allowAWSTemplateFormatVersion: 2010-09-09
Description: VPC Stack
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: 'us-east-1b'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: 'us-east-1e'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Route:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
SubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundSSHNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '22'
To: '22'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '103'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '0'
To: '65535'
SubnetNetworkAclAssociation1:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet1
NetworkAclId: !Ref NetworkAcl
SubnetNetworkAclAssociation2:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet2
NetworkAclId: !Ref NetworkAcl
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: Access to Lambda functions
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub "Portal-VpcId"
Subnet1:
Description: Subnet ID 1
Value: !Ref Subnet1
Export:
Name: !Sub "Portal-SubnetID1"
Subnet2:
Description: Subnet ID 2
Value: !Ref Subnet2
Export:
Name: !Sub "Portal-SubnetID2"
LambdaSecurityGroup:
Description: Access to Lambda functions
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "LambdaSecurityGroup"
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '103'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '0'
To: '65535'
SubnetNetworkAclAssociation1:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet1
NetworkAclId: !Ref NetworkAcl
SubnetNetworkAclAssociation2:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet2
NetworkAclId: !Ref NetworkAcl
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: Access to Lambda functions
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub "Portal-VpcId"
Subnet1:
Description: Subnet ID 1
Value: !Ref Subnet1
Export:
Name: !Sub "Portal-SubnetID1"
Subnet2:
Description: Subnet ID 2
Value: !Ref Subnet2
Export:
Name: !Sub "Portal-SubnetID2"
LambdaSecurityGroup:
Description: Access to Lambda functions
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "LambdaSecurityGroup"
CF 模板 2:
Lambda:
Type: "AWS::Lambda::Function"
Properties:
Handler: "index.handler"
Environment:
Variables:
Environment: !Ref Environment
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: "nodejs6.10"
VpcConfig:
SecurityGroupIds:
- !ImportValue "LambdaSecurityGroup"
SubnetIds:
- !ImportValue "Portal-SubnetID1"
- !ImportValue "Portal-SubnetID2"
Code:
S3Bucket: !Ref BaseS3Bucket
S3Key:
!Join
- ''
- - !Ref TemplatePath
- '/'
- !Ref Environment
- '/Quick-Links/build-output.zip'
如果您希望 Lambda 与互联网通信,您需要通过 NAT 实例进行路由。
向您现有的 VPC 子网再添加两个子网和一个 NAT 网关。然后,在您的新子网中设置路由 table 以通过 NAT 路由互联网。
当您在 VPC 中执行 Lambda 函数时,Lambda 函数将仅接收私有 IP 地址。它不会收到 public IP 地址。
为了让任何 AWS 服务器通过互联网网关访问 public 互联网,它必须:
- 有一个 public IP 地址,并且
- 在 public 子网中(即直接访问互联网网关的子网)
由于您的 Lambda 函数没有那个 public IP 地址,它无法访问互联网,即使它位于 public 子网中。
要解决此问题,您必须在私有子网中执行 Lambda 函数。这是一个子网:
- 无法直接访问 Internet 网关,并且
- 通过 NAT 实例或 NAT 网关引导所有外向连接
我的 Lambda 函数可以访问 VPC 中的其他资源,但是一旦它尝试向 Internet 发出请求,它就会超时。我有以下内容:
- 两个私有子网
- 将 0.0.0.0/0 路由到 Internet 网关的路由 Table。
- 几个 ACL 规则和一个 Lambda 安全组
任何帮助都会有所帮助。这是我的 CF 模板:
AWSTemplateFormatVersion: 2010-09-09
Description: VPC Stack
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: 'us-east-1b'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: 'us-east-1e'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Route:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
SubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allowAWSTemplateFormatVersion: 2010-09-09
Description: VPC Stack
Resources:
VPC:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.3.0/24
AvailabilityZone: 'us-east-1b'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: 'us-east-1e'
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InternetGateway:
Type: 'AWS::EC2::InternetGateway'
Properties:
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
AttachGateway:
Type: 'AWS::EC2::VPCGatewayAttachment'
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTable:
Type: 'AWS::EC2::RouteTable'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
Route:
Type: 'AWS::EC2::Route'
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
SubnetRouteTableAssociation1:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet1
RouteTableId: !Ref RouteTable
SubnetRouteTableAssociation2:
Type: 'AWS::EC2::SubnetRouteTableAssociation'
Properties:
SubnetId: !Ref Subnet2
RouteTableId: !Ref RouteTable
NetworkAcl:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref VPC
Tags:
- Key: Application
Value: !Ref 'AWS::StackId'
InboundHTTPNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '100'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundSSHNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '101'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '22'
To: '22'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '103'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '0'
To: '65535'
SubnetNetworkAclAssociation1:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet1
NetworkAclId: !Ref NetworkAcl
SubnetNetworkAclAssociation2:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet2
NetworkAclId: !Ref NetworkAcl
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: Access to Lambda functions
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub "Portal-VpcId"
Subnet1:
Description: Subnet ID 1
Value: !Ref Subnet1
Export:
Name: !Sub "Portal-SubnetID1"
Subnet2:
Description: Subnet ID 2
Value: !Ref Subnet2
Export:
Name: !Sub "Portal-SubnetID2"
LambdaSecurityGroup:
Description: Access to Lambda functions
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "LambdaSecurityGroup"
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '80'
To: '80'
InboundResponsePortsNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '102'
Protocol: '6'
RuleAction: allow
Egress: 'false'
CidrBlock: 0.0.0.0/0
PortRange:
From: '1024'
To: '65535'
OutBoundNetworkAclEntry:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref NetworkAcl
RuleNumber: '103'
Protocol: '6'
RuleAction: allow
Egress: 'true'
CidrBlock: 0.0.0.0/0
PortRange:
From: '0'
To: '65535'
SubnetNetworkAclAssociation1:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet1
NetworkAclId: !Ref NetworkAcl
SubnetNetworkAclAssociation2:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
SubnetId: !Ref Subnet2
NetworkAclId: !Ref NetworkAcl
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: Access to Lambda functions
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
Outputs:
VpcId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub "Portal-VpcId"
Subnet1:
Description: Subnet ID 1
Value: !Ref Subnet1
Export:
Name: !Sub "Portal-SubnetID1"
Subnet2:
Description: Subnet ID 2
Value: !Ref Subnet2
Export:
Name: !Sub "Portal-SubnetID2"
LambdaSecurityGroup:
Description: Access to Lambda functions
Value: !Ref LambdaSecurityGroup
Export:
Name: !Sub "LambdaSecurityGroup"
CF 模板 2:
Lambda:
Type: "AWS::Lambda::Function"
Properties:
Handler: "index.handler"
Environment:
Variables:
Environment: !Ref Environment
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: "nodejs6.10"
VpcConfig:
SecurityGroupIds:
- !ImportValue "LambdaSecurityGroup"
SubnetIds:
- !ImportValue "Portal-SubnetID1"
- !ImportValue "Portal-SubnetID2"
Code:
S3Bucket: !Ref BaseS3Bucket
S3Key:
!Join
- ''
- - !Ref TemplatePath
- '/'
- !Ref Environment
- '/Quick-Links/build-output.zip'
如果您希望 Lambda 与互联网通信,您需要通过 NAT 实例进行路由。
向您现有的 VPC 子网再添加两个子网和一个 NAT 网关。然后,在您的新子网中设置路由 table 以通过 NAT 路由互联网。
当您在 VPC 中执行 Lambda 函数时,Lambda 函数将仅接收私有 IP 地址。它不会收到 public IP 地址。
为了让任何 AWS 服务器通过互联网网关访问 public 互联网,它必须:
- 有一个 public IP 地址,并且
- 在 public 子网中(即直接访问互联网网关的子网)
由于您的 Lambda 函数没有那个 public IP 地址,它无法访问互联网,即使它位于 public 子网中。
要解决此问题,您必须在私有子网中执行 Lambda 函数。这是一个子网:
- 无法直接访问 Internet 网关,并且
- 通过 NAT 实例或 NAT 网关引导所有外向连接