How to Use a Single EC2 Instance as Both a Reverse Proxy and NAT Gateway in AWS
Introduction
AWS charges for outbound IPv4 traffic and NAT Gateway usage, making cost management a priority for cloud users. This guide explains how to configure a single EC2 instance to function as both a Reverse Proxy (for inbound traffic) and a NAT Gateway (for outbound IPv4 traffic) to help optimize costs.
Why This Setup?
- Saves Money: Avoids AWS NAT Gateway costs ($32/month + $0.045/GB).
- IPv6-First Strategy: Reduces reliance on IPv4 by leveraging AWS Egress-Only Gateway for IPv6.
- Simplified Infrastructure: Eliminates the need for separate NAT and Load Balancer instances.
Step 1: Launch an EC2 Instance
Recommended Instance Type:
t4g.nano
(~$4/month) for minimal traffic.t3a.micro
(~$6/month) for moderate traffic.
Network Configuration:
- Assign a public IPv4 & IPv6 (enable auto-assign in the AWS console).
- Place the instance in a public subnet.
- Ensure private instances use this instance as their default route.
Step 2: Configure the Instance as a NAT Gateway
Enable IP Forwarding:
Edit the sysctl settings:
echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
sysctl -p
Set Up IPTables NAT Rules:
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Persist the rules:
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
Step 3: Configure Nginx Proxy Manager as a Reverse Proxy
Install Docker & Docker Compose:
sudo apt update && sudo apt install docker docker-compose -y
Deploy Nginx Proxy Manager (NPM):
Create a directory for NPM:
mkdir -p ~/nginx-proxy-manager && cd ~/nginx-proxy-manager
Create a docker-compose.yml
file:
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- "80:80"
- "81:81"
- "443:443"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt"
Start Nginx Proxy Manager:
docker-compose up -d
Configure Reverse Proxy via NPM Dashboard:
- Access the dashboard at
http://your-server-ip:81
- Set up an admin account.
- Add a Proxy Host:
- Domain Name: yourdomain.com
- Forward Hostname/IP: Private instance IP
- Forward Port: 80 (or app-specific port)
- Enable SSL (Let’s Encrypt) if required.
Step 4: Route Private Subnet Traffic via NAT Instance
Modify Route Table:
- Go to VPC → Route Tables in AWS.
- Select the private subnet route table.
- Add a new route:
- Destination:
0.0.0.0/0
- Target: NAT Instance ID
Step 5: Handling IPv6 Traffic Efficiently
- Outbound IPv6 Traffic: Use an Egress-Only Internet Gateway (free, but bandwidth is chargeable).
- Inbound IPv6 Traffic: Ensure Nginx Proxy Manager supports IPv6 in its configurations.
Conclusion
With this setup, your single EC2 instance efficiently handles both inbound and outbound traffic while avoiding the high cost of AWS NAT Gateway and Application Load Balancer. This solution is best suited for low-to-moderate traffic workloads and aligns well with an IPv6-first strategy to reduce costs further.