Lab: Reverse Proxy, Load Balancing & API Gateway Features with Nginx

1. Goal of This Lab

You will configure Nginx to:

  • Act as a reverse proxy
  • Load balance across two backend servers
  • Apply API gateway features:
    • Rate limiting
    • User-agent filtering
    • HTTP method restrictions
    • Security headers

Every step must be documented in your protocol.


2. Prerequisites

  • Ubuntu Server VM
  • Nginx installed
  • Python 3 installed (for backend servers)
  • Host machine configured with hosts entries like:
    <VM_IP> loadbalance.local
    

3. Step 1 – Create Backend Servers

3.1 Backend 1

mkdir -p ~/backend1
cd ~/backend1
cat > server.py << 'EOF'
from http.server import BaseHTTPRequestHandler, HTTPServer
 
class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"backend":"1"}')
 
HTTPServer(("0.0.0.0", 8001), Handler).serve_forever()
EOF
python3 server.py

3.2 Backend 2

mkdir -p ~/backend2
cd ~/backend2
cat > server.py << 'EOF'
from http.server import BaseHTTPRequestHandler, HTTPServer
 
class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "application/json")
        self.end_headers()
        self.wfile.write(b'{"backend":"2"}')
 
HTTPServer(("0.0.0.0", 8002), Handler).serve_forever()
EOF
python3 server.py

4. Step 2 – Configure Nginx Load Balancer

sudo nano /etc/nginx/sites-available/loadbalance.local

Insert:

upstream backend_pool {
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
}
 
server {
    listen 80;
    server_name loadbalance.local;
 
    location / {
        proxy_pass http://backend_pool;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Enable:

sudo ln -s /etc/nginx/sites-available/loadbalance.local /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Test:

curl http://loadbalance.local/

Repeated calls should alternate between backend 1 and 2.


5. Step 3 – Add Rate Limiting

Add to Nginx config:

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s;
 
server {
    ...
    location / {
        limit_req zone=mylimit burst=3;
        proxy_pass http://backend_pool;
    }
}

Test with:

for i in {1..10}; do curl -I http://loadbalance.local/; done

Some requests should return 503.


6. Step 4 – Security Filtering

6.1 Block Bad User-Agents

Add inside server block:

if ($http_user_agent ~* "bot|crawler|curl") {
    return 403;
}

Test:

curl -A "Googlebot" http://loadbalance.local/

Should return 403.


6.2 Allow Only Certain HTTP Methods

if ($request_method !~ ^(GET|POST)$ ) {
    return 405;
}

Test:

curl -X DELETE http://loadbalance.local/

Should return 405 Method Not Allowed.


6.3 Add Security Headers

add_header X-Frame-Options "DENY";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";

Verify using:

curl -I http://loadbalance.local/

7. Step 5 – Documentation

Your protocol must include:

  • Backend server creation
  • Nginx reverse proxy configuration
  • Test outputs (curl results)
  • Load balancing verification
  • Rate limit behavior
  • Security filtering tests
  • Explanations for each step

8. Optional Extensions