wiretastix

Reverse Proxy Setup

How to configure a reverse proxy (Nginx, Caddy, Apache, Traefik) for Wiretastix with TLS.

Running Wiretastix behind a reverse proxy is the recommended production deployment pattern. A reverse proxy provides TLS termination, load balancing capabilities, enhanced security, and centralized certificate management.

Why Use a Reverse Proxy?

Essential Benefits

  1. TLS/HTTPS Termination

    • OIDC providers require HTTPS for authentication callbacks
    • Protects sensitive data in transit (credentials, API tokens)
    • Modern browsers require HTTPS for many features
    • Centralized certificate management
  2. Security

    • Hide internal service details
    • Additional firewall layer
    • Rate limiting and DDoS protection
    • Request filtering and validation
  3. Operational Flexibility

    • Easy certificate renewal (Let’s Encrypt)
    • Load balancing for high availability
    • Centralized logging and monitoring
    • Zero-downtime updates
  4. Additional Features

    • Custom headers and CORS handling
    • Compression (gzip, brotli)
    • Caching for static assets
    • URL rewriting and redirects

Architecture Overview

Client (Browser/CLI)
    ↓ HTTPS (443)
Reverse Proxy (Nginx/Caddy/Apache/Traefik)
    ↓ HTTP (8085) - internal network
Wiretastix Web UI
Client (WireGuard)
    ↓ UDP (51820) - direct
Wiretastix Daemon

Important: Only HTTP/HTTPS traffic goes through the proxy. WireGuard VPN traffic (UDP port 51820) goes directly to Wiretastix.

Prerequisites

Before configuring a reverse proxy:

  1. Domain Name: A domain pointing to your server (e.g., vpn.example.com)
  2. DNS Configuration: A record pointing to your server’s public IP
  3. Firewall: Ports 80 and 443 open for the reverse proxy
  4. Wiretastix Running: Daemon running and accessible on port 8085

Wiretastix Configuration

Configure Wiretastix to work behind a proxy:

Edit /etc/wiretastix/wiretastix.yaml:

webserver:
    # Bind to localhost only - proxy will forward
    binding: 127.0.0.1:8085
    
    # Base path (usually /)
    base: /
    
    # Disable ACME if proxy handles TLS
    acme-host: []
    
    # Assets and templates
    html-assets: /usr/lib/wiretastix/html
    html-templates: /usr/lib/wiretastix/templates

# API server - also localhost only
apiserver:
    binding: 127.0.0.1:8095
    base: /wiretastix/api/v1/

# OIDC redirect URL must match public URL
oidc:
    redirect-url: https://vpn.example.com/callback
    # ... other OIDC settings

Important: Set binding to 127.0.0.1 to prevent direct external access, forcing all traffic through the proxy.

Restart Wiretastix:

sudo systemctl restart wiretastix

Nginx is a high-performance reverse proxy, widely used and well-documented.

Installation

Debian/Ubuntu:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Rocky Linux/AlmaLinux:

sudo dnf install nginx certbot python3-certbot-nginx

Configuration

Create Nginx configuration file:

sudo nano /etc/nginx/sites-available/wiretastix

Add the following configuration:

# Upstream definition
upstream wiretastix_web {
    server 127.0.0.1:8085;
    keepalive 32;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name vpn.example.com;

    # Allow Let's Encrypt verification
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # Redirect everything else to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS server
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name vpn.example.com;

    # SSL certificates (will be configured by certbot)
    ssl_certificate /etc/letsencrypt/live/vpn.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/vpn.example.com/privkey.pem;

    # SSL configuration - modern and secure
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Logs
    access_log /var/log/nginx/wiretastix-access.log;
    error_log /var/log/nginx/wiretastix-error.log;

    # Proxy to Wiretastix
    location / {
        proxy_pass http://wiretastix_web;
        proxy_http_version 1.1;
        
        # Preserve original request information
        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;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # WebSocket support (if needed)
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # Buffering
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        proxy_busy_buffers_size 8k;
    }

    # Optional: Separate location for API if needed
    location /wiretastix/api/ {
        proxy_pass http://127.0.0.1:8095;
        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;
        
        # API might have larger payloads
        client_max_body_size 10M;
    }
}

Enable the site:

# Create symlink
sudo ln -s /etc/nginx/sites-available/wiretastix /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# If test passes, reload Nginx
sudo systemctl reload nginx

Obtain SSL Certificate

Using Let’s Encrypt with Certbot:

# Obtain certificate
sudo certbot --nginx -d vpn.example.com

# Follow prompts and choose options:
# - Enter email address
# - Agree to terms
# - Choose to redirect HTTP to HTTPS (recommended)

Certbot will automatically:

  • Obtain the certificate
  • Update Nginx configuration
  • Set up automatic renewal

Test automatic renewal:

sudo certbot renew --dry-run

Verify Configuration

Test the setup:

# Check Nginx is running
sudo systemctl status nginx

# Test HTTPS access
curl -I https://vpn.example.com

# Check certificate
echo | openssl s_client -connect vpn.example.com:443 -servername vpn.example.com 2>/dev/null | openssl x509 -noout -dates

Option 2: Caddy (Easiest)

Caddy provides automatic HTTPS with Let’s Encrypt built-in, making it the simplest option.

Installation

Debian/Ubuntu:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Or download binary:

curl -OL "https://github.com/caddyserver/caddy/releases/download/v2.7.5/caddy_2.7.5_linux_amd64.tar.gz"
tar xzf caddy_2.7.5_linux_amd64.tar.gz
sudo mv caddy /usr/local/bin/

Configuration

Create or edit /etc/caddy/Caddyfile:

# Wiretastix proxy with automatic HTTPS
vpn.example.com {
    # Automatic HTTPS (Let's Encrypt)
    # Caddy handles this automatically!
    
    # Reverse proxy to Wiretastix
    reverse_proxy localhost:8085 {
        # Preserve original request info
        header_up Host {host}
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        header_up X-Forwarded-Proto {scheme}
    }
    
    # Security headers
    header {
        # Enable HSTS
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        # Prevent clickjacking
        X-Frame-Options "SAMEORIGIN"
        # Prevent MIME sniffing
        X-Content-Type-Options "nosniff"
        # XSS protection
        X-XSS-Protection "1; mode=block"
    }
    
    # Logging
    log {
        output file /var/log/caddy/wiretastix-access.log
        format json
    }
}

# Optional: API endpoint on subdomain
api.vpn.example.com {
    reverse_proxy localhost:8095
}

Start Caddy:

# Test configuration
sudo caddy validate --config /etc/caddy/Caddyfile

# Start Caddy
sudo systemctl enable caddy
sudo systemctl start caddy

# Check status
sudo systemctl status caddy

That’s it! Caddy automatically:

  • Obtains Let’s Encrypt certificates
  • Configures HTTPS
  • Handles renewal
  • Redirects HTTP to HTTPS

Verify Configuration

# Check Caddy status
sudo systemctl status caddy

# View logs
sudo journalctl -u caddy -f

# Test HTTPS
curl -I https://vpn.example.com

Option 3: Apache (httpd)

Apache is a mature, feature-rich web server widely used in enterprise environments.

Installation

Debian/Ubuntu:

sudo apt update
sudo apt install apache2 certbot python3-certbot-apache
sudo a2enmod ssl proxy proxy_http headers rewrite

Rocky Linux/AlmaLinux:

sudo dnf install httpd mod_ssl certbot python3-certbot-apache

Configuration

Create Apache configuration:

sudo nano /etc/apache2/sites-available/wiretastix.conf
# Or on Rocky/Alma: /etc/httpd/conf.d/wiretastix.conf

Add configuration:

# Redirect HTTP to HTTPS
<VirtualHost *:80>
    ServerName vpn.example.com
    
    # Allow Let's Encrypt
    Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
    <Directory "/var/www/html/.well-known/acme-challenge/">
        Options None
        AllowOverride None
        Require all granted
    </Directory>
    
    # Redirect to HTTPS
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

# HTTPS VirtualHost
<VirtualHost *:443>
    ServerName vpn.example.com
    
    # SSL Configuration (will be set by certbot)
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/vpn.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/vpn.example.com/privkey.pem
    
    # Modern SSL configuration
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder off
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    
    # Logs
    ErrorLog ${APACHE_LOG_DIR}/wiretastix-error.log
    CustomLog ${APACHE_LOG_DIR}/wiretastix-access.log combined
    
    # Proxy configuration
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8085/
    ProxyPassReverse / http://127.0.0.1:8085/
    
    # Pass headers
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"
</VirtualHost>

Enable and start:

# Debian/Ubuntu
sudo a2ensite wiretastix
sudo apache2ctl configtest
sudo systemctl reload apache2

# Rocky/Alma
sudo httpd -t
sudo systemctl reload httpd

Obtain SSL Certificate

# Debian/Ubuntu
sudo certbot --apache -d vpn.example.com

# Rocky/Alma
sudo certbot --apache -d vpn.example.com

Option 4: Traefik (Docker-Native)

Traefik is ideal for Docker deployments with automatic service discovery.

Docker Compose Configuration

Create or modify docker-compose.yml:

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    command:
      # API and dashboard
      - "--api.dashboard=true"
      - "--api.insecure=false"
      
      # Docker provider
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      
      # Entrypoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      
      # HTTPS redirect
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      
      # Let's Encrypt
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      
      # Logging
      - "--log.level=INFO"
      - "--accesslog=true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt
    labels:
      # Dashboard access (optional)
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.vpn.example.com`)"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.service=api@internal"

  wiretastix:
    image: wiretastix:latest
    container_name: wiretastix-daemon
    restart: unless-stopped
    network_mode: host
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    volumes:
      - ./config/wiretastix.yaml:/etc/wiretastix/wiretastix.yaml:ro
      - ./config/nftables.conf:/etc/nftables.conf:ro
      - ./data:/data
      - /lib/modules:/lib/modules:ro
    labels:
      # Enable Traefik
      - "traefik.enable=true"
      
      # HTTP router
      - "traefik.http.routers.wiretastix.rule=Host(`vpn.example.com`)"
      - "traefik.http.routers.wiretastix.entrypoints=websecure"
      - "traefik.http.routers.wiretastix.tls.certresolver=letsencrypt"
      
      # Service
      - "traefik.http.services.wiretastix.loadbalancer.server.port=8085"

  postgres:
    image: postgres:16-alpine
    # ... postgres config ...

Create letsencrypt directory:

mkdir -p letsencrypt
chmod 600 letsencrypt

Start services:

docker compose up -d

Traefik automatically:

  • Discovers Wiretastix service
  • Obtains Let’s Encrypt certificate
  • Routes traffic to Wiretastix
  • Handles HTTPS and redirects

Advanced Configurations

Rate Limiting (Nginx)

Protect against brute force attacks:

# Add to http block
http {
    # Define rate limit zone
    limit_req_zone $binary_remote_addr zone=wiretastix_login:10m rate=5r/m;
    
    # ... rest of http config
}

# In server block
server {
    # ... other config
    
    # Apply rate limit to login/auth endpoints
    location /callback {
        limit_req zone=wiretastix_login burst=3 nodelay;
        proxy_pass http://wiretastix_web;
        # ... other proxy settings
    }
}

IP Whitelisting (Nginx)

Restrict API access to specific IPs:

# In server block
location /wiretastix/api/ {
    # Allow specific IPs
    allow 10.0.0.0/8;
    allow 192.168.1.0/24;
    deny all;
    
    proxy_pass http://127.0.0.1:8095;
    # ... other proxy settings
}

Custom Headers (Caddy)

Add custom headers for security or debugging:

vpn.example.com {
    reverse_proxy localhost:8085
    
    header {
        # Custom header
        X-Proxy-By "Caddy"
        
        # CORS (if needed)
        Access-Control-Allow-Origin "https://example.com"
        
        # CSP
        Content-Security-Policy "default-src 'self'"
    }
}

Load Balancing (Nginx)

For high availability setups:

upstream wiretastix_cluster {
    least_conn;
    server 127.0.0.1:8085 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8086 max_fails=3 fail_timeout=30s backup;
    keepalive 32;
}

server {
    # ... SSL config
    
    location / {
        proxy_pass http://wiretastix_cluster;
        # ... proxy settings
    }
}

Testing the Setup

Verify HTTPS

# Test HTTPS access
curl -I https://vpn.example.com

# Check certificate
echo | openssl s_client -connect vpn.example.com:443 -servername vpn.example.com 2>/dev/null | openssl x509 -noout -text

# Test SSL Labs (optional)
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=vpn.example.com

Verify Headers

# Check security headers are present
curl -I https://vpn.example.com | grep -E "(Strict-Transport-Security|X-Frame-Options|X-Content-Type)"

Test OIDC Flow

  1. Open browser to https://vpn.example.com
  2. Should redirect to OIDC provider
  3. After authentication, should return to Wiretastix
  4. Check browser console for any errors

Verify Internal Access Blocked

# This should fail (timeout or connection refused)
curl http://your-server-ip:8085

# Only accessible via proxy
curl https://vpn.example.com  # This should work

Troubleshooting

502 Bad Gateway

Cause: Proxy can’t reach Wiretastix

Solutions:

  1. Check Wiretastix is running: systemctl status wiretastix
  2. Verify binding: Wiretastix should listen on 127.0.0.1:8085
  3. Check firewall doesn’t block localhost communication
  4. Review proxy logs for connection errors

SSL Certificate Errors

Cause: Certificate issues

Solutions:

  1. Check certificate files exist and are readable
  2. Verify domain DNS points to your server
  3. Ensure ports 80 and 443 are accessible from internet
  4. For Let’s Encrypt, check rate limits
  5. Review certbot logs: sudo journalctl -u certbot -f

OIDC Callback Fails

Cause: Redirect URL mismatch

Solutions:

  1. Ensure oidc.redirect-url in Wiretastix matches public URL
  2. Must be https://vpn.example.com/callback, not http:// or IP
  3. Update OIDC provider with correct callback URL
  4. Check proxy forwards Host header correctly

Headers Not Passed

Cause: Missing proxy headers

Solutions:

  1. Verify proxy_set_header (Nginx) or equivalent in config
  2. Especially important: X-Forwarded-Proto and Host
  3. Check Wiretastix logs for received headers
  4. Test with curl: curl -H "X-Forwarded-Proto: https" http://localhost:8085

Security Best Practices

  1. Always use HTTPS: Never expose Wiretastix over HTTP in production
  2. Keep certificates updated: Enable automatic renewal (certbot, Caddy)
  3. Use strong ciphers: Disable old protocols (SSLv3, TLSv1.0, TLSv1.1)
  4. Enable HSTS: Force browsers to always use HTTPS
  5. Implement rate limiting: Protect against brute force
  6. Monitor logs: Watch for suspicious access patterns
  7. Restrict API access: Use IP whitelisting if possible
  8. Regular updates: Keep proxy software updated
  9. Secure proxy server: Harden the proxy OS and configuration
  10. Backup certificates: Include in backup procedures

Performance Optimization

Enable Compression (Nginx)

# In http block
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;

HTTP/2 and HTTP/3

# Nginx
listen 443 ssl http2;
listen 443 quic reuseport;  # HTTP/3

# Caddy (automatic HTTP/2, HTTP/3)
vpn.example.com {
    # HTTP/2 and HTTP/3 enabled by default
}

Connection Pooling

upstream wiretastix_web {
    server 127.0.0.1:8085;
    keepalive 32;  # Maintain 32 keepalive connections
    keepalive_requests 100;
    keepalive_timeout 60s;
}

Monitoring

Nginx Status

# Add to server block
location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    deny all;
}

Access: curl http://localhost/nginx_status

Log Analysis

# Nginx access log
sudo tail -f /var/log/nginx/wiretastix-access.log

# Caddy logs
sudo journalctl -u caddy -f

# Apache logs
sudo tail -f /var/log/apache2/wiretastix-access.log

Additional Resources