Mengekspos port 80 atau 443 langsung via Dynamic DNS atau port forwarding router membuka permukaan serangan terhadap automated scanner, credential stuffing, dan eksploitasi zero-day pada level web server. Pendekatan zero-maintenance membutuhkan isolasi total: tidak ada port inbound terbuka di firewall lokal, autentikasi terpusat di edge proxy, dan verifikasi identitas berlapis sebelum paket mencapai container aplikasi.

Arsitektur Zero Trust Tanpa Port Forwarding

Pola hands-off maintenance mengeliminasi rotasi dynamic IP manual, manajemen sertifikat Let's Encrypt yang rapuh di level host lokal, serta pembersihan log akses scanner. Arsitektur ini menggunakan outbound tunnel terenkripsi menuju Cloudflare Edge, yang menegakkan kebijakan Access Policy (IdP/OAuth + OTP) sebelum me-relay traffic ke reverse proxy internal.

Alur request:

  1. Klien meminta akses ke subdomain internal (misal: dashboard.internal.example.com).
  2. Cloudflare Access memvalidasi sesi via Identity Provider (Google Workspace, GitHub, atau OIDC) dan menerbitkan cookie/header JWT (Cf-Access-Jwt-Assertion).
  3. Daemon cloudflared lokal menerima paket melalui koneksi outbound tunnel (QUIC/HTTP/2) dan mem-forward ke Nginx reverse proxy.
  4. Nginx memvalidasi header Cloudflare dan melempar request ke upstream container internal.

Deployment Stack: Docker Compose

Konfigurasi di bawah menjalankan daemon tunnel bersama Nginx dan service target dalam isolated bridge network. Tidak ada binding port ke host (ports: tidak diekspos ke antarmuka eksternal).

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=eyJhIjoiY2...your_tunnel_token_here...
    networks:
      - internal_net

  nginx-proxy:
    image: nginx:alpine
    container_name: nginx-proxy
    restart: unless-stopped
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    networks:
      - internal_net

  target-service:
    image: containrrr/watchtower # Contoh workload homelab
    container_name: target-service
    restart: unless-stopped
    networks:
      - internal_net

networks:
  internal_net:
    driver: bridge

Konfigurasi Nginx: Header Validation dan Session Hardening

Meskipun tunnel berada di jaringan privat, proxy lokal tetap wajib memvalidasi bahwa lalu lintas benar-benar berasal dari edge Zero Trust resmi dan bukan dari spoofing internal. Tambahkan pengecekan header Cf-Access-Authenticated-User-Email dan drop request yang tidak memiliki token otentikasi valid.

events {}

http {
    server_tokens off;
    
    # Proteksi dasar buffer overflow
    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 8m;
    large_client_header_buffers 2 1k;

    # Session & Security Headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    server {
        listen 80;
        server_name dashboard.example.com;

        # Blokir request tanpa header identitas Zero Trust
        if ($http_cf_access_jwt_assertion = "") {
            return 403 "Forbidden: Missing Zero Trust Identity Context";
        }

        location / {
            proxy_pass http://target-service:8080;
            proxy_http_version 1.1;
            
            # Forward identity context ke upstream
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $http_cf_connecting_ip;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header Remote-User $http_cf_access_authenticated_user_email;

            # Hardening timeouts
            proxy_connect_timeout 5s;
            proxy_read_timeout 60s;
            proxy_send_timeout 60s;
        }
    }
}

Aturan Verifikasi Cloudflare Access Policy

Konfigurasikan access rules pada dashboard Cloudflare Zero Trust (Access > Applications) untuk memangkas brute-force sebelum menyentuh homelab:

  • Rule Type: Include
  • Criteria: Emails ending in @yourdomain.com atau email spesifik admin homelab.
  • Require MFA: Wajibkan FIDO2/WebAuthn pada Identity Provider (IdP).
  • Session Duration: Set ke 12 hours atau 24 hours untuk meminimalisasi re-autentikasi tanpa kompromi keamanan.

Alternatif Lebih Ringkas: Tailscale Serve / Tailscale Auth

Jika dependensi terhadap third-party edge seperti Cloudflare tidak diinginkan, alternatif lain adalah Tailscale Auth Proxy native tanpa ingress publik:

# Expose service internal via Tailscale tailnet langsung
tailscale serve --bg 8080

Tailscale Serve otomatis mengenkripsi koneksi end-to-end via WireGuard dan mengisolasi akses hanya pada node yang berada dalam Access Control List (ACL) tailnet Anda. Tidak diperlukan DNS publik atau sertifikat TLS manual.

Troubleshooting dan Verifikasi

Verifikasi header pipeline dari mesin klien yang terotentikasi:

curl -sv https://dashboard.example.com/ -H "cf-access-token: <JWT>"

Jika terjadi error 403 Forbidden dari Nginx, periksa log container untuk memastikan parameter tunneling tidak membuang header kustom:

docker logs nginx-proxy --tail 50

Pastikan token JWT diteruskan secara utuh pada directive proxy_pass. Untuk service yang membutuhkan WebSocket, tambahkan header Upgrade dan Connection "upgrade" pada blok location terkait.