VPC 中的 Lambda 函数无法访问互联网

Lambda Function in VPC has no Internet Access

我的 Lambda 函数可以访问 VPC 中的其他资源,但是一旦它尝试向 Internet 发出请求,它就会超时。我有以下内容:

任何帮助都会有所帮助。这是我的 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 互联网,它必须:

  1. 有一个 public IP 地址,并且
  2. 在 public 子网中(即直接访问互联网网关的子网)

由于您的 Lambda 函数没有那个 public IP 地址,它无法访问互联网,即使它位于 public 子网中。

要解决此问题,您必须在私有子网中执行 Lambda 函数。这是一个子网:

  1. 无法直接访问 Internet 网关,并且
  2. 通过 NAT 实例或 NAT 网关引导所有外向连接