Theodo logo

Why my Lambda cannot access Internet anymore from its AWS VPC?

January 20, 2020Charles de la Roche Saint André10 min read

In this post, I try to be as clear as possible to explain how to give Internet Access to your AWS resources if they are in an AWS VPC.

For the most curious and those who like to understand things in depth, I explain at each step the AWS concepts in the grey part.

How did I get there?

Recently, I developed an application with a React frontend, a NestJS backend and I set up a deployment with an AWS Lambda function for the backend and an AWS S3 bucket for the static frontend. My app was quite simple and mostly used a PostgreSQL database, an external API and the Google authentication.

All was working really fine in production until I decided to switch my RDS database to private mode for security reasons and then lost its access. Indeed, by default, a RDS database is in an AWS VPC and you can't access it, except if you are in the same VPC or if your RDS is public.

Thus, to retrieve access to my database, I was forced to move my AWS lambda function in the same VPC. Then came a new problem. When you move an AWS instance in a VPC, you lose the Internet access and therefore cannot anymore reach your instance from Internet and your instance cannot reach the Internet anymore.

1 - Create a VPC

A VPC (Virtual Private Cloud) is a virtual network in the cloud in which you can launch AWS resources. You have complete control over your virtual networking environment, including selection of your own private IP address range, creation of subnets and configuration of route tables and network gateways.

You have all interest in using VPC because it helps in aspects of cloud computing like privacy, security and preventing loss of proprietary data. Moreover, some instances like AWS relational databases, need to be in a VPC and the only way to access them is to be in the same VPC.

If you don't already have a VPC (virtual private cloud), you need to create one.

To do that, go to the Services tab, select VPC, click on Your VPCs on the left menu and then on Create VPC:

  • Choose the name of your VPC, for example my-wonderful-vpc
  • In the CIDR (class inter-domain routing) block input, choose a range of IPs addresses for your VPC, for example 172.30.0.0/16

create-vpc-image.png

For your information, 172.30.0.0/16 is what we called a network mask, it means all the IP addresses starting from 173.30.0.0 to 172.30.255.255.

infra-step-1-image.png

2 - Create private and public subnets in your VPC

A subnet is simply a range of IP addresses in the VPC. A subnet can be thought of as dividing a large network into smaller networks. This is done because the maintenance of smaller networks is easier and it also provides security to the network from other networks.

To host your lambda, you need to create a private subnet inside your VPC.

Click on Subnets on the left menu in the VPC service and then on the button Create subnet:

  • Choose the name of your subnet, for example my-wonderful-vpc-private-subnet
  • Choose the VPC you created during the previous step (my-wonderful-vpc)
  • In the CIDR block input, choose a subrange IPs addresses of your VPC IPs addresses, for example 172.30.1.0/24 (from 173.30.1.0 to 172.30.1.25)

create-subnet-image.png

Repeat these previous steps to create the public subnet by choosing another name (for example my-wonderfull-vpc-public subnet) and another subrange of IPs (for example 172.30.2.0/24).

You will configure your subnets as public and private in the 4th step.

infra-step-2-image.png

3 - Create an Internet Gateway and a NAT Gateway in the VPC

An Internet Gateway is a logical connection between an AWS VPC and the Internet. It's not a physical device. Only one can be associated with each VPC. If a VPC doesn't have an Internet Gateway, then the resources cannot be accessed from the Internet. Conversely, resources within your VPC need an Internet Gateway to access the Internet.

A Network Address Translation (NAT) enable instances in a private subnet to connect to the Internet, but prevent the Internet from initiating a connection with those instances. To do that, NAT maps all the private IP addresses assigned to the instances in the subnet to one public IPv4 address called the Elastic IP address.

To access Internet, you will need to attach an Internet Gateway to your VPC.

Select Internet Gateways on the left menu and then click on the button Create internet gateway:

  • Choose the name of your Internet Gateway, for example my-wonderful-vpc-igw

create-internet-gateway-image.png

You will then need to attach your Internet Gateway to your VPC. Come back to the Internet Gateways tab, select your Internet Gateway (my-wonderful-vpc-igw), click on Action, select Attach to VPC and select your VPC (my-wonderful-vpc).

You will also need to create a NAT Gateway. Click on NAT Gateways on the left menu and then on the button Create NAT gateway :

  • Choose the subnet you want to be public (my-vonderful-vpc-public-subnet)
  • Choose one of your Elastic IPs. If you don't have one, click on Create New EIP

create-nat-gateway-image.png

Your infra should look like this now:

infra-step-3-image.png

4 - Associate the right route tables to the subnets

A route table contains a set of rules called routes which determine where traffic has to be directed. You can create as many route tables in a VPC as you want. Route tables act at the subnet level, not the VPC level. A route table can be associated to one or severals subnets. By default, all route tables in a VPC have a local route for communication within the VPC. You can add custom routes in a route table by creating a new route defining which traffic (IP destination) must go where (target).

Remarks:
  • Even if you don't create any route table, all VPC come with a default main route table and all the subnets of the VPC are associated to this main route table until you associate them to a custom route table.
  • If a subnet is associated to a route table redirecting all traffic to an internet gateway, it is called a public subnet.

We will create two custom route tables, one for each subnet.

In the VPC service, click on Route Tables in the left menu and then on the button Create route table:

  • Choose the name for your route tables, for example my-wonderful-vpc-public-route-table and my-wonderful-vpc-private-route-table
  • Choose the VPC created in step 1 (my-wonderful-vpc)

create-route-table-image.png

Now that the two routes tables, we are going to configure them. Let's start with the public one.

Go back to the Route Tables section and select the created route table my-wonderful-vpc-public-route-table:

  • Click on the tab Routes of the selected route table
  • Click on the button Edit routes
  • Add a new route with for destination 0.0.0.0/0 and for target your internet gateway ID igw-.... created in step 3 and click on Save Routes

configure-public-route-table-routes-image.png

  • Then, click on the tab Subnet Associations of the selected route table
  • Click on the button Edit subnet associations
  • Add your public subnet my-wonderful-vpc-public-subnet created in step 2 and click on Save

configure-public-route-table-subnet-association-image.png

By doing that, you have redirected all outgoing traffic of the public subnet to the internet gateway, what makes this subnet a public subnet.

Now, let's configure the private route table. Go back to the Route Tables tab and select the route table my-wonderful-vpc-private-route-table:

  • Click on the tab Routes of the selected route table
  • Click on the button Edit routes
  • Add a new route with for destination 0.0.0.0/0 and for target your NAT gateway ID nat-.... created in step 3 and click on Save Routes
  • Click on the tab Subnet Associations of the selected route table
  • Click on the button Edit subnet associations
  • Add your private subnet my-wonderful-vpc-private-subnet created in step 2 and click on Save

By doing that, you have redirected all traffic of the private subnet to the NAT gateway.

infra-step-4-image.png

5 - Create the lambda function and configure it

The hardest part is already done!

If you don't already have a lambda, go to the Lambda service, and then click on the button Create function:

  • Choose a name for your Lambda, for example my-wonderful-lambda
  • Select the Node.js runtime
  • In the section Permissions, select the choice create a new role with basic lambda permissions

configure-lambda-permissions-image.png

Once your lambda is created, click on it in the Lambda service and it will open the configuration page. Go down to the section Network and there, you must select 3 things:

  • your VPC created in step 1 (my-wonderful-vpc)
  • your private subnet created in step 2 (my-wonderful-vpc-private-subnet)
  • the default security group of your VPC, called by default your-vpc-name-default-security-group

configure-lambda-vpc-image.png



🔥🔥 Congrats, that's all, your AWS lambda function has access to Internet! 🔥🔥

infra-step-5-image.png



The end of this post is for people who wonders what is this mysterious default security group that I mentioned in the last step.

Bonus: Add more security with the security groups

A security group acts as a virtual firewall for your instance to control inbound and outbound traffic. You can create as many security groups in a VPC as you want. Security groups act at the instance level, not the subnet level. A security group can be associated to one or severals instances. By default, all security groups in a VPC allow all inbound and outbound traffic. You can add custom rules in a security group that control the inbound and outbound traffic.

Remark:
  • even if you don't create security groups, all VPC come with a default security group and all the instances of the VPC are associated to this default security group until you associate them to a custom security group

A good practice is to associate with each of your instance a security group with the strict minimum authorized traffic.

For example, if you have a RDS database (AWS relational database service), you will only need to accept inbound traffic from your lambda (or your other backend instance).

To do that, in the VPC service, click on Security Groups and then on the button Create security group.

Once created, go back to the Security Group tab, select your security group, go the Inbound Rules tab, and select Edit rules to add an inbound rule that allows only incoming traffic from the security group of your lambda instance to reach the RDS instance:

configure-security-group-inbound-rules-image.png

Then, go to the Outbound Rules tab, click on Edit rules to add an outbound rule that allows all traffic to leave the instance:

configure-security-group-outbound-rules-image.png

To finish, you just have to associate this security group to your RDS in its configuration page.

🔥 Congrats, that's all you have to do to protect your database from the outside.

I hope you have enjoyed and have learned new things in this post. Feel free to leave comments to help me improve it.

Charles de la Roche Saint André

Charles de la Roche Saint André

Web Developer at Theodo