Ein Reverse Proxy nimmt Anfragen entgegen und leitet sie an Backend-Server weiter. Nginx ist dafür besonders gut geeignet.

Warum Reverse Proxy?

  • SSL-Terminierung: HTTPS am Proxy, HTTP zum Backend
  • Load Balancing: Anfragen auf mehrere Server verteilen
  • Mehrere Apps: Verschiedene Anwendungen unter einer Domain
  • Caching: Statische Inhalte cachen
  • Sicherheit: Backend-Server verstecken

Grundlegende Konfiguration

Einfacher Reverse Proxy

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        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;
    }
}

Wichtige Proxy-Header

| Header | Beschreibung | |--------|--------------| | Host | Original-Hostname | | X-Real-IP | Client-IP-Adresse | | X-Forwarded-For | Proxy-Kette | | X-Forwarded-Proto | http oder https |

Mit SSL/TLS

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        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;
    }
}

Mehrere Anwendungen

Verschiedene Pfade

server {
    listen 443 ssl http2;
    server_name example.com;

    # Hauptanwendung
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }

    # API
    location /api/ {
        proxy_pass http://localhost:8080/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }

    # Admin-Panel
    location /admin/ {
        proxy_pass http://localhost:8000/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }
}

Verschiedene Subdomains

server {
    listen 443 ssl http2;
    server_name app.example.com;

    location / {
        proxy_pass http://localhost:3000;
    }
}

server {
    listen 443 ssl http2;
    server_name api.example.com;

    location / {
        proxy_pass http://localhost:8080;
    }
}

Load Balancing

Upstream-Definition

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
    }
}

Gewichtung

upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}

Backup-Server

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080 backup;
}

Methoden

upstream backend {
    # Round-Robin (Standard)
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

upstream backend_ip {
    ip_hash;  # Sticky Sessions
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

upstream backend_least {
    least_conn;  # Wenigste Verbindungen
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

WebSocket-Unterstützung

location /ws/ {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_read_timeout 86400;
}

Caching

Proxy-Cache aktivieren

http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

    server {
        location / {
            proxy_pass http://localhost:3000;
            proxy_cache my_cache;
            proxy_cache_valid 200 60m;
            proxy_cache_valid 404 1m;
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

Cache-Bypass

location / {
    proxy_pass http://localhost:3000;
    proxy_cache my_cache;
    proxy_cache_bypass $http_cache_control;
    proxy_no_cache $http_pragma $http_authorization;
}

Health Checks

Passive Health Checks

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}

Active Health Checks (Nginx Plus)

upstream backend {
    zone backend 64k;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    health_check interval=5s;
}

Timeouts konfigurieren

location / {
    proxy_pass http://localhost:3000;

    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;

    # Für langsame Uploads
    client_max_body_size 100m;
    client_body_timeout 120s;
}

Rate Limiting

http {
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            proxy_pass http://localhost:8080;
        }
    }
}

Sicherheitsheader

server {
    location / {
        proxy_pass http://localhost:3000;

        # Sicherheitsheader
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;

        # HSTS
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    }
}

Typische Setups

Node.js-Anwendung

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Docker-Container

upstream docker_app {
    server 127.0.0.1:8080;
}

server {
    listen 443 ssl http2;
    server_name docker.example.com;

    location / {
        proxy_pass http://docker_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Grafana

server {
    listen 443 ssl http2;
    server_name grafana.example.com;

    location / {
        proxy_pass http://localhost:3000;
        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;
    }

    location /api/live/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Debugging

Logs erweitern

log_format proxy '$remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent" '
                 'upstream: $upstream_addr '
                 'response_time: $upstream_response_time';

access_log /var/log/nginx/proxy_access.log proxy;

Fehler prüfen

nginx -t
tail -f /var/log/nginx/error.log

Fazit

Nginx als Reverse Proxy ist extrem vielseitig. SSL-Terminierung, Load Balancing und mehrere Anwendungen unter einer Domain sind nur einige Einsatzmöglichkeiten. Mit der richtigen Konfiguration wird Nginx zum zentralen Zugangspunkt Ihrer Infrastruktur.