Skip to content

Instantly share code, notes, and snippets.

@iam-veeramalla
Created September 23, 2025 14:57
Show Gist options
  • Select an option

  • Save iam-veeramalla/d263f75675376431c92cd579db5c15ad to your computer and use it in GitHub Desktop.

Select an option

Save iam-veeramalla/d263f75675376431c92cd579db5c15ad to your computer and use it in GitHub Desktop.
Forward and Reverse Proxy explained with Demos.

Forward Proxy vs Reverse Proxy

In this tutorial, You will learn:

  • Forward Proxy using Tinyproxy (simple, lightweight).
  • Reverse Proxy using NGINX with two Python backends.

0 — Prepare the Instance

Update and install prerequisites:

sudo apt update
sudo apt install -y net-tools curl wget tcpdump jq

1 — Forward Proxy with Tinyproxy

1.1 Install Tinyproxy

sudo apt install -y tinyproxy

1.2 Configure Tinyproxy (minimal safe config)

Backup original:

sudo cp /etc/tinyproxy/tinyproxy.conf /etc/tinyproxy/tinyproxy.conf.bak

Replace with this:

sudo tee /etc/tinyproxy/tinyproxy.conf > /dev/null <<'CONF'
# Tinyproxy minimal demo config
Port 8888
Listen 127.0.0.1
Allow 127.0.0.1

LogFile "/var/log/tinyproxy/tinyproxy.log"
PidFile "/run/tinyproxy/tinyproxy.pid"

MaxClients 100
Timeout 600
StatHost "tinyproxy-stats"
LogLevel Info
CONF

Restart:

    sudo systemctl daemon-reload
    sudo systemctl restart tinyproxy
    sudo systemctl enable tinyproxy
    sudo systemctl status tinyproxy --no-pager

1.3 Prove Traffic Goes Through Proxy

Set environment variables so all commands use the proxy:

export http_proxy="http://127.0.0.1:8888"
export https_proxy="http://127.0.0.1:8888"

Now run:

wget -O- http://example.com | head -n 5
curl -I https://www.wikipedia.org

At the same time, in another terminal, watch logs:

sudo tail -f /var/log/tinyproxy/tinyproxy.log
  • If proxy is used → entries appear in log.
  • If you unset http_proxy https_proxy and re-run → logs stay empty (direct connection).

Alternative proof with tcpdump:

sudo tcpdump -i any port 8888 -n

If proxy is used, you’ll see connections to 127.0.0.1.8888.


1.4 Cleanup (optional)

Stop Tinyproxy:

sudo systemctl stop tinyproxy

Remove if not needed:

sudo apt purge -y tinyproxy
sudo rm -rf /var/log/tinyproxy /run/tinyproxy
sudo apt autoremove -y

2 — Reverse Proxy with NGINX

2.1 Install NGINX + Python

sudo apt install -y nginx python3

2.2 Create Two Simple Backends

mkdir -p ~/proxy-labs && cd ~/proxy-labs
cat > backend_echo.py <<'PY'
#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import json, socket
class EchoHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        info = {"path": self.path,
                "client": self.client_address[0],
                "server": socket.gethostname()}
        body = json.dumps(info).encode()
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)
if __name__ == "__main__":
    import sys
    port = int(sys.argv[1]) if len(sys.argv) > 1 else 8001
    HTTPServer(("0.0.0.0", port), EchoHandler).serve_forever()
PY
chmod +x backend_echo.py

Start two backends:

nohup ./backend_echo.py 8001 > backend1.log 2>&1 &
nohup ./backend_echo.py 8002 > backend2.log 2>&1 &

Verify:

curl http://127.0.0.1:8001/
curl http://127.0.0.1:8002/

2.3 Configure NGINX

Backup default:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

Replace with:

sudo tee /etc/nginx/sites-available/default > /dev/null <<'NGINX'
server {
    listen 80;
    server_name _;

    # Route to backend1
    location /service1/ {
        proxy_pass http://127.0.0.1:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Route to backend2
    location /service2/ {
        proxy_pass http://127.0.0.1:8002/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Default route (load-balance demo)
    location / {
        proxy_pass http://127.0.0.1:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
NGINX

Reload:

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager

2.4 Test Reverse Proxy

Expected: JSON output with "server": "<backend-host>".


2.5 Cleanup

Kill backends:

pkill -f backend_echo.py || true

Restore NGINX config:

sudo mv /etc/nginx/sites-available/default.bak /etc/nginx/sites-available/default
sudo systemctl reload nginx

3 — Key Difference (Forward vs Reverse)

  • Forward Proxy (Tinyproxy):

    • Sits in front of clients.
    • Clients must know about it (browser/http_proxy vars).
    • Used for access control, anonymity, monitoring.
  • Reverse Proxy (NGINX):

    • Sits in front of servers.
    • Clients don’t know about it.
    • Used for load balancing, TLS termination, security.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment