Reverse Proxies & Ingress Guide

In production environments, Django Hurricane typically operates behind an edge reverse proxy, CDN, or Kubernetes Ingress Controller (such as Nginx, Traefik, AWS ALB, or Cloudflare).

This guide covers configuring proxy headers, resolving real client IPs for the Rate Limiter, and optimizing Fast-404 defense shields.


Client IP Resolution & Trusted Headers

Hurricane's Token-Bucket Rate Limiter tracks request frequency per client IP address. When operating behind a reverse proxy, the direct socket connection (REMOTE_ADDR) belongs to the proxy rather than the end user.

To prevent all users from sharing a single proxy rate-limit bucket, configure RATE_LIMIT_PROXY_HEADER to match your infrastructure provider:

Infrastructure ProviderRecommended Proxy HeaderHurricane Setting
Standard Reverse Proxy (Nginx, Traefik)X-Forwarded-For (first IP)RATE_LIMIT_PROXY_HEADER = "X-Forwarded-For"
CloudflareCF-Connecting-IPRATE_LIMIT_PROXY_HEADER = "CF-Connecting-IP"
Nginx (Direct)X-Real-IPRATE_LIMIT_PROXY_HEADER = "X-Real-IP"
AWS Application Load Balancer (ALB)X-Forwarded-ForRATE_LIMIT_PROXY_HEADER = "X-Forwarded-For"
Google Cloud Load Balancer (GCLB)X-Forwarded-ForRATE_LIMIT_PROXY_HEADER = "X-Forwarded-For"

Configuration Example

In your settings.py:

settings.py
# Cloudflare example:
RATE_LIMIT_PROXY_HEADER = "CF-Connecting-IP"

# Or via environment variable:
# HURRICANE_RATE_LIMIT_PROXY_HEADER="CF-Connecting-IP"

Hurricane automatically normalizes header formats—whether you specify "CF-Connecting-IP" or "HTTP_CF_CONNECTING_IP", it correctly locates the value in WSGI/ASGI request headers.


Production Nginx Configuration

Below is an optimal Nginx configuration proxying traffic to Hurricane on port 8000 while maintaining real client headers and supporting WebSockets:

nginx.conf
upstream hurricane_upstream {
    server 127.0.0.1:8000;
    keepalive 32;
}

server {
    listen 80;
    server_name example.com;

    client_max_body_size 50M;

    location / {
        proxy_pass http://hurricane_upstream;
        proxy_http_version 1.1;

        # WebSocket support
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Real Client IP and Host headers
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeouts and buffer sizes
        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}

Kubernetes Ingress Configuration

When deploying inside Kubernetes with ingress-nginx, ensure snippet or annotation settings pass real client IPs:

ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: django-app-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "60"
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: django-app-service
            port:
              number: 80

Tuning Fast-404 Behind Reverse Proxies

Hurricane's Fast-404 Security Shield blocks scanner probes and malicious paths before they reach Django. Choose the optimal strategy based on your routing architecture:

1. auto Strategy (Default)

Inspects Django's root urls.py. If a root catch-all pattern is detected (e.g. Wagtail, CMS, or dynamic routing), it operates in Signature-only mode to avoid dropping legitimate dynamic pages. Otherwise, it operates in high-performance Prefix mode.

2. prefix Strategy

Ideal for dedicated APIs, microservices, and applications with explicit URL prefixes. Any path that does not match a known Django URL prefix is dropped immediately with an instant 404.

settings.py
FAST_404 = "prefix"
FAST_404_EXTRA_PREFIXES = ["api", "auth", "v1", "v2"]

3. signature Strategy

Strictly checks incoming paths against known malicious exploit patterns (.php, .env, /wp-admin/, phpmyadmin, etc.). Legitimate non-matching paths continue to Django. Recommended when running CMS or dynamic multi-tenant routes.

settings.py
FAST_404 = "signature"