VPC 中的 AWS Lambda 在 NAT 后面没有互联网访问权限

AWS Lambda in VPC doesn't have internet access behind NAT

我的问题是我 运行 在具有 IGW 的 VPC 内的 NAT 后面的 Lambda 函数无法访问互联网上的任何内容。

我想做的是创建一个 VPC,它具有:

那部分作品。

接下来,我想在 VPC 中创建一个 Lambda 函数。我将其放入 PrivateAPrivateB 并为其分配一个允许所有出口和入口流量的安全组。

下面是一个重现问题的独立示例(整个模板)。我已经阅读了 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 规则阻止了。