A production-ready, cost-effective solution for routing traffic through a different IP using AWS Fargate and SOCKS5. Ideal for geo-testing websites, avoiding geolocation restrictions, and privacy-focused browsing.
Requirements: AWS account, Docker locally. Not tested on Windows.
Main point of difference: requires almost no user input other than starting and stopping the service. Transparently handles remote proxy IP address changes when used with a tool like foxyproxy. When starting a new proxy service fargate will create a new public IP address. the choices are to update your foxyproxy config on every start, pay for a fixed IP address, or use this application which handles it in the background. It even handles local and remote IP changes midstream.
This is not a VPN Which is to say using a tool like foxyproxy you can create per website proxying rules.
Key Stats:
- Cost: ~$1–3/month (100–200 hrs)
- Setup: ~5 minutes (automated)
- Startup: 30–60 seconds
- Idle shutdown: Configurable — remote stops after inactivity, auto-wakes on next request
- Persistent connections: WebSocket, SSE, HTTP/2
- Security: IP allowlist and/or username/password authentication
chmod +x setup.sh
./setup.sh # Automated deployment (asks about security, timeout)
./proxy-manage.sh start # Start proxy
curl -x http://localhost:8080 http://httpbin.org/ip # Test itSee QUICKSTART.md for step-by-step, or DEPLOYMENT.md for manual control.
Your Browser (localhost:8080)
↓
Local HTTP Proxy (Node.js) — async-proxy/proxy.js
─ Monitors orchestrator for endpoint updates
─ Tracks request activity (lastActivityAt) for idle detection
─ State machine: idle → waking → active
─ Triggers wake-up via POST /wake when idle traffic arrives
─ Routes traffic via SOCKS5 to Fargate task
↓
Local Orchestrator (Python) — proxy-orchestrator/orchestrator.py
─ Manages Fargate task lifecycle
─ Polls proxy.js health endpoint for activity data
─ Shuts down remote task after IDLE_TIMEOUT_MINUTES of inactivity
─ Enters idle_mode — does not restart the task
─ Receives POST /wake to start a new task on demand
─ Detects IP changes, manages security groups
─ Provides management API on port 5000
↓
AWS Fargate SOCKS5 Proxy (serjs/go-socks5-proxy) ── OFF when idle
─ Ephemeral task with public IP ── ON when in use
─ Optional username/password auth
─ Started on demand, stopped after idle timeout
↓
Internet (with your AWS region's IP)
Idle flow: No traffic for IDLE_TIMEOUT_MINUTES → orchestrator stops the Fargate task → proxy.js detects no endpoint → enters idle state → next browser request triggers POST /wake → orchestrator starts a new task → proxy.js picks up the IP and resumes routing.
Browser always connects to localhost:8080 — no reconfiguration needed between sessions.
./proxy-manage.sh start # Start (waits ~30–60s for Fargate init)
./proxy-manage.sh stop # Stop local proxy (Fargate auto-shuts down)
./proxy-manage.sh stop --remote # Stop local proxy + stop Fargate task immediately
./proxy-manage.sh status # Current status & IP
./proxy-manage.sh health # Connectivity test
./proxy-manage.sh logs # View logs
./proxy-manage.sh info # Cost/config summaryBrowser config: Set HTTP & HTTPS proxy to localhost:8080.
The proxy supports two complementary security layers, configured during setup.sh:
| Layer | When to use | How it works |
|---|---|---|
| IP Allowlist | Office/static IP | Security group restricts port 1080 to your IP only. Auto-detects IP changes. |
| Username/Password | Dynamic IP / extra protection | SOCKS5 authentication via PROXY_USER/PROXY_PASSWORD. Required when IP allowlist is off. |
- If IP allowlist is enabled: auth is optional (recommended for defense-in-depth)
- If IP allowlist is disabled: auth is mandatory —
setup.shenforces this
See SECURITY-IP-ALLOWLIST.md for details.
All configuration is stored in .env (generated by setup.sh). Key values:
| Variable | Default | Description |
|---|---|---|
IDLE_TIMEOUT_MINUTES |
60 | Remote proxy auto-shutdown after N min idle. Falls back to TASK_IDLE_TIMEOUT_MINUTES |
TASK_IDLE_TIMEOUT_MINUTES |
60 | Legacy — passed to CloudFormation for container-level timeout |
IP_ALLOWLIST_ENABLED |
false |
Restrict proxy to your public IP |
REQUIRE_AUTH |
false |
Require SOCKS5 username/password |
PROXY_USER |
— | SOCKS5 username |
PROXY_PASSWORD |
— | SOCKS5 password |
DUAL_IP_RETENTION_MINUTES |
180 | Keep old IP in SG when IP changes |
| Usage | Monthly Cost |
|---|---|
| 50 hrs | ~$0.60 |
| 100 hrs | ~$1.20 |
| 200 hrs | ~$2.40 |
Includes: Fargate compute (vCPU+memory), 1 GB data transfer, auto-shutdown Lambda, CloudWatch logs. Savings: Ephemeral by design — no minimum, pay only when running, auto-shutdown after idle timeout (default 60 min). Automatically wakes on next browser request.
| File | Purpose |
|---|---|
| QUICKSTART.md | 5-min quick start |
| README.md | Full documentation reference (this file) |
| DEPLOYMENT.md | Step-by-step deployment & troubleshooting |
| fargate-proxy-architecture.md | Architecture deep-dive |
| SECURITY-IP-ALLOWLIST.md | IP allowlist & auth security details |
setup.sh |
Automated deployment script |
proxy-manage.sh |
CLI management (start/stop/status/logs/info) |
fargate-infrastructure.yaml |
AWS CloudFormation template |
docker-compose.yml |
Docker Compose config for local services |
async-proxy/proxy.js |
Local Node.js HTTP → SOCKS5 proxy |
proxy-orchestrator/orchestrator.py |
Python orchestrator managing Fargate lifecycle |
proxy-orchestrator/entrypoint.sh |
Orchestrator container entrypoint |
async-proxy/Dockerfile |
Dockerfile for the local HTTP proxy |
proxy-orchestrator/Dockerfile |
Dockerfile for the orchestrator |
Legacy: ec2-proxy-setup.md (EC2-based alternative, different approach)
Do I need to update browser settings each time?
No — localhost:8080 is permanent.
Why is first startup slow?
Fargate initializes in ~30–60 seconds.
What if I forget to stop it?
Ephemeral by design — auto-shutdown after the configured idle timeout (default 60 min). The orchestrator monitors request activity through the local HTTP proxy and stops the remote Fargate task when no traffic has been seen for the timeout period. The next browser request automatically wakes it up (30-60s delay for Fargate initialization).
If you put your PC to sleep the local Docker containers stop — the remote proxy has already been shut down by the idle timeout at that point since no requests were flowing. If your local containers are still running (e.g. always-on device), the idle timeout still applies and the remote will shut down.
Can I use this remotely?
Designed for local use only. See DEPLOYMENT.md for options. For deploying as a shared network proxy on a local LAN, see the Network Proxy roadmap below.
How is security handled?
Two complementary layers: IP allowlist (security group restriction) and/or SOCKS5 username/password authentication. Encrypted end-to-end.
What IP/country will I get?
Depends on the AWS region you deploy to.
Can I customize the SOCKS5 proxy?
Yes — see serjs/go-socks5-proxy for config options.
| Symptom | Check |
|---|---|
| Proxy won't start | docker compose logs, aws sts get-caller-identity |
| Fargate task won't init | aws ecs list-tasks --cluster proxy-cluster, check CloudWatch logs & security groups |
| Can't connect | curl http://localhost:8080, verify browser proxy is localhost:8080, docker compose ps |
| Auth errors | Verify PROXY_USER/PROXY_PASSWORD match between .env and Fargate task definition |
See DEPLOYMENT.md for detailed troubleshooting.
The current design runs the proxy locally at localhost:8080, available only to the machine running Docker. A natural next step is to make it available to all devices on your local network — phones, tablets, laptops, TVs — so they all share the same Fargate SOCKS5 tunnel.
Deploy the local components (proxy.js + orchestrator) on a small always-on device (Raspberry Pi, old PC, thin client, etc.) on your network. The architecture stays the same:
Any Device on LAN (proxy → 192.168.1.100:8080)
↓
Local HTTP Proxy — running on the always-on box
↓
Local Orchestrator — running on the same box
↓
AWS Fargate SOCKS5 Proxy (ephemeral, auto-idle)
↓
Internet (with your AWS region's IP)
| Concern | Solution |
|---|---|
| Network binding | Change LISTEN_HOST from 0.0.0.0 to the LAN IP or keep 0.0.0.0 and open port 8080 on the device's firewall |
| Persistence | Use restart: always in docker-compose.yml so containers survive reboots |
| Remote access | SSH tunnel, Tailscale, or WireGuard if you want access from outside the LAN |
| IP allowlist | If enabled, the orchestrator already updates the security group — works for any LAN with a shared public IP (NAT). If each device has a different public IP, you may want to disable IP allowlisting and rely on SOCKS5 auth instead |
| Auth | SOCKS5 username/password (REQUIRE_AUTH=true) is recommended for LAN deployments since any device on the network can reach the proxy |
| Management UI | The orchestrator API on port 5000 could be extended with a simple dashboard for monitoring usage and idle status |
| Startup on boot | Add docker compose up -d to a systemd service or cron @reboot |
The idle timeout is what makes this practical for a shared device. Without it, the remote Fargate proxy would run 24/7 — costing ~$8-9/month. With it, the proxy shuts down when the household is asleep, at work, or away, and wakes automatically on the first browse of the day.
cat QUICKSTART.md # Read quick start (5 min)
chmod +x setup.sh #
./setup.sh # Run automated setup (5 min)
chmod +x proxy-manage.sh #
./proxy-manage.sh start # Start proxy
curl -x http://localhost:8080 http://httpbin.org/ip # TestYou'll have a proxy running with an IP from your chosen AWS region in ~15 minutes total.