In this tutorial, You will learn:
- Forward Proxy using Tinyproxy (simple, lightweight).
- Reverse Proxy using NGINX with two Python backends.
Update and install prerequisites:
sudo apt update
sudo apt install -y net-tools curl wget tcpdump jq
sudo apt install -y tinyproxy
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
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_proxyand 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.
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
sudo apt install -y nginx python3
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/
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
-
Backend1 via proxy:
curl -s http://localhost/service1/ | jq
-
Backend2 via proxy:
curl -s http://localhost/service2/ | jq
-
Default route:
curl -s http://localhost/ | jq
Expected: JSON output with "server": "<backend-host>".
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
-
Forward Proxy (Tinyproxy):
- Sits in front of clients.
- Clients must know about it (browser/
http_proxyvars). - 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.