AWS Lambda With Static Outgoing IP — A Complete No-VPC Tutorial

Yury Smykalov
3 min readMar 4, 2020

Sometimes, you need to have a static outgoing IP when making HTTP requests from AWS Lambda.

In our case, we were building a Skrill payment gateway integration for our InviteMember product (membership bot platform for paid Telegram channels and groups).

Here’re two common ways to solve that:

  • deploy your function in VPC and use a NAT gateway with static IP;
  • deploy your function normally, but use an HTTP proxy server with static IP.

We tried both.

Unfortunately, VPC didn’t work well — when you’re invoking a VPC-function from a normal function, it can result in a huge latency (up to a few minutes). In our case (payments processing) it wasn’t acceptable.

So we launched a simple proxy server with auth in EC2 and our function makes HTTP requests through it. Works like a charm!

Here’s how you can do the same.

Set up a proxy server instance in EC2

  1. Launch t3.nano instance (the cheapest one will work) with Amazon Linux 2 AMI.
  2. In your security group settings, allow inbound connections on port 22 and 9999 (first one for SSH, the second one for the proxy server itself).
  3. Allocate a new Elastic IP and associate it with the new instance.
  4. SSH to the instance and run the following commands to update packages and install tinyproxy 1.10 (yum repo has an outdated version at the moment so we’re installing it from source):
sudo yum -y update
sudo yum -y groupinstall “Development Tools”
wget https://github.com/tinyproxy/tinyproxy/releases/download/1.10.0/tinyproxy-1.10.0.tar.gz
tar zxvf tinyproxy-1.10.0.tar.gz
cd tinyproxy-1.10.0/
./configure && make && sudo make install

5. Create a new user tinyproxy:

sudo adduser tinyproxy

6. Edit the following lines of your tinyproxy.conf file (located by default in /usr/local/etc/tinyproxy/tinyproxy.conf):

User tinyproxy
Group tinyproxy
Port 9999
# default 8888 option didn't work for some reason on our instance
Allow 0.0.0.0/0
BasicAuth your_secure_user_name your_secure_password

7. Create /etc/systemd/system/my_tinyproxy.service file with the following contents:

[Unit]
Description=Tinyproxy Service
After=network.target
[Service]
Type=simple
User=tinyproxy
WorkingDirectory=/home/tinyproxy
ExecStart=/usr/local/bin/tinyproxy -d -c /usr/local/etc/tinyproxy/tinyproxy.conf
Restart=always
#on-failure # or always, on-abort, etc
[Install]
WantedBy=multi-user.target

8. Start tinyproxy:

sudo systemctl start my_tinyproxy.service

9. Make sure tinyproxy service is active (running):

sudo systemctl status my_tinyproxy.service

10. To avoid memory leaks, put the following line in root’s crontab file (sudo crontab -e):

0 2 * * * /bin/systemctl restart my_tinyproxy.service

11. Test your proxy server with curl (both commands should output your Elastic IP associated with proxy server instance):

# From the proxy server instance itself:
curl --proxy your_secure_user_name:your_secure_password@localhost:9999 https://api.ipify.org
# From your own machine:
curl --proxy your_secure_user_name:your_secure_password@your_elastic_ip:9999 https://api.ipify.org

If one of these will fail — check your “Allow” lines in tinyproxy.conf and security group inbound rules as well.

Use the proxy in your Lambda function

Our functions run on Node.js and we’re using axios library to make HTTP requests.

Unfortunately, axios internal proxy feature is a bit buggy (see issues on GitHub), so we’re using https-proxy-agent for the “proxy client” part:

const axios = require("axios");
const HttpsProxyAgent = require("https-proxy-agent");
const agent = new HttpsProxyAgent({
host: "your_elastic_ip",
port: 9999
auth: "your_secure_user_name:your_secure_password"
});
const response = await axios({
httpsAgent: agent,
...
});

That’s it!

Now your function has a static outgoing IP that you can whitelist where you need it.

--

--

Yury Smykalov

Founder of InviteMember, membership bot platform for paid Telegram channels and groups