Search code examples
amazon-web-servicesnetwork-programmingamazon-vpcaws-vpnaws-site-to-site

How do I access on-prem HTTP services from my Lambda function?


I've created a javascript lambda function that is triggered by an API gateway request. I've tested it from my frontend and it works fine (hosted outside AWS).

However, from my function I need to call an HTTP service from my on-prem network as an API call. I've tested the service through a local VPN connection in my machine and it works like a charm. Reading through the AWS documentation, I reached to the conclusion that I needed to configure my lambda to run inside a VPC and to connect that VPC to a site-to-site VPN.

I created the site-to-site VPN and the tunnels are up without issues. I created the client gateway for my on-prem network and also a Virtual Private Gateway for my AWS network. I checked the box to propagate to the routing table the on-prem IP prefixes I declared while creating the VPN. (I understand the IP prefixes are the on-prem IP endpoints I need to reach. For example let's say my services are hosted in 172.31.0.2 and 172.31.15.22, so I declared them as /32 since they're a single IP address and AWS asked me for a CIDR.)

I also created my VPC, associated it to the VPN and declared a subnet. The network admin gave me a CIDR range as routing option for our AWS services (let's say 172.31.50.160/29) so I declared the VPC CIDR as 172.21.0.0/16 and the subnet as 172.31.50.160/28. I also made sure lambda configurations specified my newly created VPC and subnet as well a security group.

While my frontend can still call the lambda without problems, I can't seem to reach the on-prem network. I always receive an ENOTFOUND error, so I assume this means the API call isn't going through the VPN tunnel, as the service is only reachable through the tunnel. So I'm guessing it's most likely a routing error. However, I'm not sure how to solve it.

My routing table shows the propagated IPs and the Virtual Private Gateway as their destination, as well as the 172.31.0.0/16 with the destination as Local. I imagine it could be a routing error, maybe I made a mistake setting that CIDR range as the VPC range.

I also tried adding cloudwatch logging to the VPC to check the traffic but nothing is logged, it always comes up empty. I made sure the IAM role I used for this had cloudwatch permissions, thinking that might be the issue, but even after that the logs are empty.

As you can see I have only very basic knowledge about networks, so any help is appreciated!

TL;DR

Goal: To allow my lambda function to access an on-prem service in a local machine.

Expected results: After connecting the lambda to a VPC that's associated to a running VPN, my lambda would be able to reach the local machine.

Actual results: The lambda is unable to locate the local machine (getaddrinfo ENOTFOUND error), seems as if the traffic is not going through the VPN tunnel.


Solution

  • Turns out that the same way that lambda cannot directly access the internet without a public NAT gateway and the right routing, lambda cannot access on-prem machines through the VPN without a private NAT gateway.

    So I created a private subnet in my VPC, using the CIDR range the on-prem network administrator gave me. Then I routed my requests to the on-prem machines to the private NAT gateway. The routing table for this private subnet directed my traffic flow to the Virtual Private Gateway and in this way I was able to reach the on-prem machines.

    Summary

    1. Create a private subnet in your VPC (do not associate it to lambda)
    2. Create a private NAT gateway and associate it with your new subnet
    3. On the route table that manages the subnets associated with lambda, route your requests to the on-prem machines to the private NAT gateway you created on step 2
    4. On the private NAT's routing table, route requests to your Virtual Private Gateway associated with your VPN

    And done, you should be able to send HTTP requests from your lambda to your on-prem servers.