For our Serverless project running on AWS infrastructure we needed an outbound Lambda API call to a SaaS platform which demands a whitelist of the source IP addresses. Which is pretty hard since AWS has a whole range. Luckily there is a trick to target your Lambda function in a VPC which can be configured to use a elastic IP for outbound communication.
High Level Design

Steps to configure the VPC / Network
Step 1 – create/use a VPC
Our AWS Network configuration always start with an AWS VPC (Virtual Private Cloud). You can use an existing VPC and configure your subnets there, or create a new one. Network configuration on AWS can look simple with the GUI wizard, but the setup of your VPC had major impact on all your resources so for real production a thing to remember. In the example I use CIDR block 10.0.0.0/16 which gives me (way to much) options.
Step 2 – create a public and 1-n private subnets
We will need 1 public subnet to attach to a NAT Gateway and route our traffic to the Internet. The example can work with 1 private subnet which hosts your Lambda function. However for availability purposes you would want to have multiple private subnets in different availability zones for your lambda to run. In the example I use CIDR block 10.0.11.0/24 for the public subnet and 10.0.21.0/24, 10.0.22.0/24 and 10.0.23.0/24 for the 3 private subnets on each eu-west-1 availability zone.
Step 3 – Configure the Internet Gateway and the public subnet configuration
We need an Internet Gateway for our VPC, attach to our public subnet and a public route table configuration which targets all (0.0.0.0/0) outbound traffic from the public subnet.
Step 4 – Configure the NAT Gateway and the private subnet configuration
We need a NAT Gateway which uses an elastic IP address. By adding a private route table which we attach to our private subnet(s) we make sure that all functions in the VPC will use our elastic IP for outbound communication. At lease, if we make sure the private route table contains a (0.0.0.0/0) target to the NAT Gateway
Configure your Lambda function
Make sure your Lambda function(s) use the configured VPC by selecting it in the VPC pulldown and then select all the private subnet(s).

Notes:
- Make sure your Lambda runs with the IAM AWSLambdaVPCAccessExecutionRole

CloudFormation source code
Template can be found in my aws-cloudformation Git repository as well:
Resources:
######################
## VPC basics
######################
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: t10-fn-vpc-dev
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: t10-fn-internetgateway-dev
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId:
Ref: InternetGateway
VpcId:
Ref: VPC
######################
## Subnet Public
######################
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: eu-west-2a
CidrBlock: 10.0.11.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: t10-fn-public-subnet-az1-dev
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: t10-fn-public-rt-dev
PublicRouteTableRoute1:
Type: AWS::EC2::Route
DependsOn: InternetGateway
Properties:
RouteTableId:
Ref: PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId:
Ref: InternetGateway
PublicRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: PublicSubnet1
RouteTableId:
Ref: PublicRouteTable
PublicElasticIP:
Type: AWS::EC2::EIP
Properties:
Domain:
Ref: VPC
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId:
Fn::GetAtt: PublicElasticIP.AllocationId
SubnetId:
Ref: PublicSubnet1
Tags:
- Key: Name
Value: t10-fn-natgateway-dev
######################
## Subnet Private
######################
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: eu-west-2a
CidrBlock: 10.0.21.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: t10-fn-private-subnet-az1-dev
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: eu-west-2b
CidrBlock: 10.0.22.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: t10-fn-private-subnet-az2-dev
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId:
Ref: VPC
AvailabilityZone: eu-west-2c
CidrBlock: 10.0.23.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: t10-fn-private-subnet-az3-dev
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: t10-fn-private-rt-dev
PrivateRouteTableRoute1:
Type: AWS::EC2::Route
DependsOn: NatGateway
Properties:
RouteTableId:
Ref: PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId:
Ref: NatGateway
PrivateRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: PrivateSubnet1
RouteTableId:
Ref: PrivateRouteTable
PrivateRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: PrivateSubnet2
RouteTableId:
Ref: PrivateRouteTable
PrivateRouteTableAssociation3:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId:
Ref: PrivateSubnet3
RouteTableId:
Ref: PrivateRouteTable
######################
## Security NACL
######################
NetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: t10-fn-nacl-dev
NetworkAclEntryfn100:
Type: AWS::EC2::NetworkAclEntry
Properties:
CidrBlock: 0.0.0.0/0
Egress: 'false'
NetworkAclId:
Ref: NetworkAcl
Protocol: "-1"
RuleAction: allow
RuleNumber: "100"
NetworkAclEntryOutbound100:
Type: AWS::EC2::NetworkAclEntry
Properties:
CidrBlock: 0.0.0.0/0
Egress: 'true'
NetworkAclId:
Ref: NetworkAcl
Protocol: "-1"
RuleAction: allow
RuleNumber: "100"
PrivateSubnetNetworkAclAssociation1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId:
Ref: PrivateSubnet1
NetworkAclId:
Ref: NetworkAcl
PrivateSubnetNetworkAclAssociation2:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId:
Ref: PrivateSubnet2
NetworkAclId:
Ref: NetworkAcl
PrivateSubnetNetworkAclAssociation3:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId:
Ref: PrivateSubnet3
NetworkAclId:
Ref: NetworkAcl
######################
## Security Group(s)
######################
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: t10-fn-lambda-sg
GroupDescription: t10-fn-lambda-sg
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
VpcId:
Ref: VPC
Tags:
- Key: Name
Value: t10-fn-lambda-sg-dev
######################
## OUTPUT
######################
#Outputs:
# VPC:
# Description: A reference to the created VPC
# Value:
# Ref: VPC
# Export:
# Name: t10-fn-vpc-id$
References