Trigger AWS Lambda with TCP Traffic + Static IP Address
Published: 2024-03-27 14:46:58

In this post, I will walk you through how to trigger AWS Lambda with TCP traffic. By the end of the post, we would have created a setup similar to the diagram below:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqw5s4j9ugutzn3i8prq.png)

## First question is WHY?

In my case, it is because the client application that I was working with can only send requests via TCP. I needed to supply a stable IP address and a port number. They couldn't really update the client to HTTP because it was a legacy system.

Given a choice though, it is best to just use HTTP traffic so you can connect with Lambda via API Gateway. Using this approach comes with advantages:
- You can use API Gateway's routing capabilities to route traffic to small Lambda functions
- The setup is more durable because API Gateway is a managed service. As you'd see later, we would have to create a TCP server to route traffic to Lambda + APIGW. And that can be a single point of failure.

## FACT: Lambda cannot be directly triggered with TCP traffic.

When sending TCP requests, you need the IP address and the port number of the target. Because Lambda functions are only spawned when they are triggered by an event, they are only given an ephemeral IP address and port number. Sending TCP requests to Lambda directly implies you are made aware of the IP address and port number of each invocation of Lambda. And so far, AWS has no feature that makes this possible.

If you are looking to deploy an application in Lambda to receive and process TCP traffic _directly_, this post unfortunately cannot help you. At this time of writing, this is not technically feasible yet. I suggest you just use ECS, EC2 or EKS to do this.

But if you are looking to find a way for a TCP client to communicate with Lambda by converting TCP traffic to HTTP, then this post is for you!

## Now on the solution

**(1)** Following the diagram above, we first provision an EC2 instance. To follow with the examples here, I suggest you choose a Linux instance (i.e Ubuntu or Amazon Linux 2).

**(2)** Install Python 3

**(3)** Create a Python virtual environment and install the requests package.

```sh
python3 -m venv venv
source venv/bin/activate

pip install requests
pip freeze > requirements.txt
```

**(4)** Create a file called `tcp_server.py` and copy paste the contents of this [GitHub Snippet](https://gist.github.com/jamby1100/916b201e2a8739818ab3442a07d74631) to the file.

(5) Set the environment variables and run the TCP server.

```sh
export TCP_IP_ADDRESS_BIND=0.0.0.0 
export TCP_PORT_NUMBER=8108
export TCP_SERVER_TIMEOUT=20
export APIGW_BASE_URL="<YOUR APIGW ROUTE>"

chmod +x tcp_server.py
python tcp_server.py
```

You should see this in your terminal:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c743rw78e4q0buc9z6y2.png)

(6) To test your setup, create another Python script by copying the contents of [this second Github Gist](https://gist.github.com/jamby1100/faf10bbd148e500f9fb20c4f7274cd24) to a file called `tcp_client.py`. This gist sends a TCP request to the TCP web server we have started.

(7) Next, execute these commands to ping the TCP server. 

```sh
export TCP_SERVER_IP_ADDRESS=0.0.0.0 
export TCP_PORT_NUMBER=8108

python tcp_client.py
```

In the screencap below, we see that we have received a response from our TCP web server. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3dxhud0anp6xousol39n.png)

## What's next?

This solution is a POC that demonstrates that we can receive TCP traffic and route it to Lambda. The next step is to run this script inside an EC2 instance and expose the port and IP address of the EC2 instance.

For low-traffic conditions, this setup is okay. But with increased traffic, we have to start thinking about how this would all scale automatically when there is an increased load. For this, we recommend that the TCP server is hosted in a Docker container, orchestrated by either ECS, EKS, or a custom Kubernetes cluster.

The full repo is found [here](https://github.com/jamby1100/lambda-tcp-web-server)

Photo by <a href="https://unsplash.com/@tvick?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Taylor Vick</a> on <a href="https://unsplash.com/photos/cable-network-M5tzZtFCOfs?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>