Allowing AWS Lambda reaching Internet via NAT and VPC

Dev environment

  1. Serverless framework
  2. Nodejs 12.x LTS

Github repo: https://github.com/ookangzheng/aws-lambda-with-nat-vpc-example

handler.js

// handler.js
// node12.x version

module.exports.hello = async event => {
  
  const fetch = require('node-fetch')
  const os = require( 'os' );

  let networkInterfaces = os.networkInterfaces( ); 
  console.log( networkInterfaces );
  console.log('Fetch start')
  let a = await fetch('http://www.e-try.com/black.htm')
  console.log(`${JSON.stringify(a) + a.status } log out RESPONSE `)
  console.log('Fetch end')
  return {}
};

Serverless configuration

// serverless.yml
 
service: testlambdanatvpc
provider:
  name: aws
  runtime: nodejs12.x
  stage: dev 
  region: us-east-2
  vpc:
      securityGroupIds:
        - "Fn::GetAtt": ServerlessSecurityGroup.GroupId
      subnetIds:
        - Ref: ServerlessPublicSubnetA


functions:
  hello:
    handler: handler.hello
  
resources:
  Resources:
    ServerlessVPC:
      Type: AWS::EC2::VPC
      Properties:
        CidrBlock: "10.0.0.0/16"
    ElasticIpLambda:
      Type: AWS::EC2::EIP
      Properties:
        Domain: vpc
    InternetGatewayLambda:
      Type: AWS::EC2::InternetGateway
    VPCGatewayAttachmentLambda:
      Type: AWS::EC2::VPCGatewayAttachment
      Properties:
        VpcId:
          Ref: ServerlessVPC
        InternetGatewayId:
          Ref: InternetGatewayLambda
    NatGatewayLambda:
      Type: AWS::EC2::NatGateway
      Properties:
        AllocationId:
          Fn::GetAtt:
            - ElasticIpLambda
            - AllocationId
        SubnetId:
          Ref: ServerlessPublicSubnetA
    ServerlessPrivateSubnetA:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::Subnet
      Properties:
        VpcId:
          Ref: ServerlessVPC
        AvailabilityZone: ${self:provider.region}a
        CidrBlock: "10.0.3.0/24"
    ServerlessPublicSubnetA:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::Subnet
      Properties:
        VpcId:
          Ref: ServerlessVPC
        AvailabilityZone: ${self:provider.region}a
        CidrBlock: "10.0.2.0/24"
    DefaultPrivateRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId:
          Ref: ServerlessVPC
    DefaultPublicRouteTable:
      Type: AWS::EC2::RouteTable
      Properties:
        VpcId:
          Ref: ServerlessVPC
    DefaultPublicRoute:
      Type: AWS::EC2::Route
      Properties:
        RouteTableId:
          Ref: DefaultPublicRouteTable
        DestinationCidrBlock: 0.0.0.0/0
        GatewayId:
          Ref: InternetGatewayLambda
    DefaultPrivateRoute:
      Type: AWS::EC2::Route
      Properties:
        RouteTableId:
          Ref: DefaultPrivateRouteTable
        DestinationCidrBlock: 0.0.0.0/0
        NatGatewayId:
          Ref: NatGatewayLambda
    SubnetRouteTableAssociationLambdaPrivateA:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId:
          Ref: ServerlessPrivateSubnetA
        RouteTableId:
          Ref: DefaultPrivateRouteTable
    SubnetRouteTableAssociationLambdaPublicA:
      Type: AWS::EC2::SubnetRouteTableAssociation
      Properties:
        SubnetId:
          Ref: ServerlessPublicSubnetA
        RouteTableId:
          Ref: DefaultPublicRouteTable
    ServerlessSecurityGroup:
      DependsOn: ServerlessVPC
      Type: AWS::EC2::SecurityGroup
      Properties:
        GroupDescription: SecurityGroup for Serverless Functions
        VpcId:
          Ref: ServerlessVPC

Source

  1. https://aws.amazon.com/premiumsupport/knowledge-center/internet-access-lambda-function/
  2. https://serverless.com/framework/docs/providers/aws/guide/functions/