42

As per this document, if I need to access internet resources from my Lambda function with VPC access, I need to set up a NAT gateway.

So I followed this guide to set up a NAT gateway. However, at the stage when I need to edit the route tables of my subnet to add an entry with destination: 0.0.0.0/0 and target as my NAT gateway's id, I got an error that

An entry with this destination already exists

I checked and noticed that for that existing entry, the target was an internet gateway for my VPC. If I replace that entry with the NAT gateway id, I cannot access any of the EC2 instances in that VPC through SSH from the outside world. How can I achieve a solution where all the EC2 instances in this VPC:

  • Are accessible only via SSH and the rest of the traffic is blocked
  • Are able to completely access other EC2 instances in the same VPC
  • Lambda function having access to this VPC can access outside resources like SQS and Kinesis.
3
  • 4
    Here's a good tutorial I wrote: "How to setup AWS lambda function to talk to the internet and VPC" gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7 Commented Jun 14, 2016 at 23:19
  • Just checked about NAT gateway pricing and is it correct it currently costs $0.045 per hour? Commented Oct 24, 2019 at 6:56
  • 1
    I explain what is tripping most of us up in this answer: stackoverflow.com/a/63369754/2255753 Commented Aug 12, 2020 at 4:35

6 Answers 6

52

I found a good detailed tutorial on how to allow your lambda to connect to both VPC ressources and the internet here: https://gist.github.com/reggi/dc5f2620b7b4f515e68e46255ac042a7

A quick walk-through:

  • setup new subnets for your lambda (with CIDRs not overlapping your existing subnets). You need:
    • one subnet which will be pointing to an Internet Gateway (IGW) to be used by the NAT (let's call it A)
    • several pointing to the NAT to be used by your lambda (B, C and D)
  • add a NAT gateway: set the subnet to A
  • set your lambda VPC subnets to B, C and D
  • create 2 routes table:
    • one that points to your NAT with destination 0.0.0.0/0
    • one that points to your IGW (should already exists) with destination 0.0.0.0/0
  • update the subnet A to use the route table pointing to the IGW
  • update the subnets B, C and D to use the route table pointing to the NAT

Hope this helps.

Sign up to request clarification or add additional context in comments.

7 Comments

I added a detailed walk-through. Not as detailed as the linked tuto, but this is exactly what I did and it seems to answer the original question.
The linked article is quite useful but has some errors - for example it uses 'AWS services' to mean 'services only in your VPC', but in fact many AWS services are on the public Internet (such as default S3 setup)
The tutorial isn't perfect and leaves some details out, but is still a good starting point for beginners.
Additionally, for those who want to understand the VPC thing and how it relates to RDS/Lambda, here comes a very well written explanation, for beginners: edgarroman.github.io/zappa-django-guide/aws_network_primer
if I could give you 100 votes I would, OMG was so tough to get this answer, still confused what the heck is going on lol
|
38

You need both the IGW and the NAT gateway for this to work.

In the public subnets (ones you want to reach from outside) point the 0.0.0.0/0 traffic to the IGW gateway. The NAT gateway itself needs to sit in one of these public subnets.

In the private subnets that you want to NAT point 0.0.0.0/0 traffic to the NAT gateway elastic network interface.

If 0.0.0.0/0 is aleady bound to the gateway you need to remove that and add it pointing the NAT gateway.

See: http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-nat-gateway.html

6 Comments

And I need to select the private subnet in the Lambda function's configuration
With a NAT Gateway running ~$30/mo in the least expensive regions (and no NAT GW provided by the Free Tier), this kind of sucks from a hobbyist perspective.
yes and no. if you use the built-in one you're right, it sucks for a hobbyist. in that case you can try to leverage an EC2 instance that you can build to act as a NAT instance (what people did before the managed version was out there)
@Mircea you saved me. how many years of AWS / Networking experience do you have?
@nxmohamad thanks for the kind words. I've worked with AWS since the early days but if it matters I've learned most of these things the hard way :)
|
11

You need two different subnets. It sounds as if you only have one.

Lambda can only use private subnets inside VPC.

Definition of a private subnet: the default route is a NAT instance (which most be on a different, public subnet) or a NAT Gateway, and no machines in the subnet have a public IP address. Machines with public IP addresses are allowed on a private subnet, but for the most part, they will not work properly, because this is technically a misconfiguration.

Definition of a public subnet: the default route is the igw-xxxxxxxx Internet Gateway object, and machines have public IP addresses assigned. Machines without public IP addresses are allowed on a public subnet, but they will not be able to access the Internet, because this is a misconfiguration.

It sounds like you are trying to change your existing subnet from public to private by changing the default route. As expected, this breaks other things.

See also Why do we need private subnet in VPC?

7 Comments

a private subnet does not have to have a nat instance or gateway as a default route. you can have machines without a public IP in a public subnet. The only real difference between the private and the public subnets is the route to the igw.
I will edit to address the igw inclusion/exclusion as the defining attribute more clearly, and add authoritative citations.
There are a lot of EC2 instances on this account and there are 4 subnets. I want to make sure that I do not mess up anything while making the change. Should I add a new subnet. I am not sure how should I configure my Lambda to work with this strategy
If you already have a subnet where the default route points to a NAT instance or NAT Gateway, you should be able to use that subnet with Lambda. If not, you will need to create a new subnet, if you want to be certain nothing will break, and then arrange for NAT for machines (including Lambda interfaces) in that subnet (NAT Gateway is easiest and typically has best performance; NAT Instance is a little more involved but documented, lower performance (though you may not notice, depending on traffic), and cheaper).
@Michael-sqlbot I would like to question your second statement. Lambda can run in public subnets. However, since the ENIs created for Lambda does not respect the subnet "auto-assign public IP" setting it does not get a public IP and cannot access outside resources so given OPs question it doesn't help. That said, I have deployed Lambdas in public subnets that can access ElastiCache clusters in the same public subnets.
|
3

Hey guys I developed a step by step tutorial with explicit screenshots about it:

Part I

  1. Create a lambda function in AWS
  2. Create an API Gateway to redirect all the requests to your AWS Lambda Function https://medium.com/@shontauro/how-can-i-turn-my-restful-api-into-a-serverless-application-and-deploy-it-to-aws-lambda-step-by-ec7ce38e18be

Part II

  1. Configure a VPC for your lambda function
  2. Grant internet access to the lambda function in a safety way
  3. Deploy the Node.js Restful API into your Lambda Function https://medium.com/@shontauro/how-can-i-turn-my-restful-api-into-a-serverless-application-and-deploy-it-to-aws-lambda-step-by-8ff6cc97780f

Comments

1

For using your Lambda inside of your VPC and internet access:

I believe, most of you already have IGW ,that you're working with inside of your VPC and working with internet,so no need create a new one.

Steps worked for me:

  1. Create a new subnets (recommended 2 or more) under your main VPC. Give it new CIDR with a mask ,you think it'll be count of network interfaces use in your Lambda.(I did X.X.X.X/28 , because for us it's enough)

  2. Create NAT Gateway , add to it Elastic IP or create new EIP and add it to your main Subnet under your VPC. (remember it'll work if you already have Internet Gateway)

  3. Create Route table and add 0.0.0.0/0 route to Target - Nat Gateway ID (nat-xxxxxxxxxxxxxxxxx)that we've created (step 2)

  4. Create new Security Groups (ALL to ALL) for your lambda to work with internet. I believe it's secure to add 0.0.0.0/0 to lambda for internet.

  5. Open lambda - choose your VPC, add SG that's you're working with and add new created from the step 4 to work with internet. press Save and Test.

1 Comment

> choose your VPC, add SG that's you're working with. Do you add the groups that are associated to the NAT, to the lambda or the SGs that are associated to the internet gateway? or both?
-2

You actually don't need to create Internet and NAT gateways anymore:https://aws.amazon.com/blogs/security/how-to-connect-to-aws-secrets-manager-service-within-a-virtual-private-cloud/

1 Comment

This is only for AWS Secret Manager. If your Lambda still needs to access ElasticSearch, RDS or other services that sit on top of a VPC, you still need to configure it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.