Proxy Headers #
Header HTTP adalah mekanisme komunikasi metadata antara client, proxy, dan backend. Ketika Caddy berperan sebagai reverse proxy, ia bisa menambah, mengubah, atau menghapus header baik pada request yang diteruskan ke backend maupun pada response yang dikembalikan ke client. Konfigurasi header yang tepat sangat penting untuk beberapa hal: mendapatkan IP client yang benar di backend, CORS yang berfungsi dengan baik, dan security headers yang konsisten.
Dua Arah: header_up dan header_down
#
Client ──request──► Caddy ──[header_up modifikasi]──► Backend
│
Client ◄──response── Caddy ◄──[header_down modifikasi]── Backend
example.com {
reverse_proxy backend:3000 {
# header_up: modifikasi header REQUEST yang diteruskan ke backend
header_up X-Custom "value"
# header_down: modifikasi header RESPONSE dari backend ke client
header_down X-Backend-Version "v2"
}
}
Header Forwarding Standar #
Ini adalah set header standar yang harus diteruskan ke backend agar aplikasi bisa mengetahui informasi tentang request asli:
example.com {
reverse_proxy backend:3000 {
# IP client asli
# Tanpa ini, backend hanya melihat IP Caddy (127.0.0.1)
header_up X-Real-IP {remote_host}
# Daftar IP yang telah melewati proxy (bisa multiple proxy)
# Format: "client-ip, proxy1-ip, proxy2-ip"
header_up X-Forwarded-For {remote_host}
# Protokol asli yang digunakan client (http atau https)
# Backend bisa cek ini untuk redirect logic
header_up X-Forwarded-Proto {scheme}
# Host header yang diminta client
# Berguna jika backend perlu tahu domain yang diminta
header_up X-Forwarded-Host {host}
# Port yang digunakan (80, 443, atau custom)
header_up X-Forwarded-Port {server_port}
# Host untuk upstream (termasuk port jika non-standar)
# Ini yang backend lihat sebagai "Host" header
header_up Host {upstream_hostport}
}
}
Perlu dicatat: Caddy secara default sudah menambahkanX-Forwarded-For,X-Forwarded-Proto, danX-Forwarded-Hostsecara otomatis. Kamu hanya perlu menambahkan secara eksplisit jika ingin mengubah nilai atau menambahkan header tambahan sepertiX-Real-IP.
Placeholder yang Tersedia untuk Header Values #
Placeholder Nilai
─────────────────────────────────────────────────────────────────────
{remote_host} IP address client (tanpa port)
{remote_port} Port client
{remote_ip} IP address client (sama dengan remote_host)
{scheme} http atau https
{host} Hostname dari request (tanpa port)
{hostport} Hostname + port jika non-standar
{upstream_hostport} Hostname + port upstream target
{server_port} Port server yang menerima request
{method} HTTP method (GET, POST, dll.)
{uri} URI lengkap termasuk query string
{path} Path tanpa query string
{query} Query string (tanpa ?)
{header.NAMA_HEADER} Nilai header request tertentu
{http.request.uuid} UUID unik untuk setiap request
{time.now.unix} Unix timestamp saat ini
{env.NAMA_ENV} Nilai environment variable
Trusted Proxies dan X-Forwarded-For yang Benar #
Ini adalah salah satu konfigurasi yang paling sering disalahpahami. X-Forwarded-For adalah header yang bisa di-spoof oleh client — client bisa mengirim header ini dengan nilai IP palsu.
Tanpa trusted_proxies:
Attacker (203.0.113.1) mengirim:
X-Forwarded-For: 1.2.3.4 ← IP palsu yang attacker kirim
Backend menerima:
X-Forwarded-For: 1.2.3.4, 203.0.113.1 ← Caddy menambahkan IP attacker
Tapi jika backend hanya baca X-Forwarded-For[0] = 1.2.3.4
→ IP palsu berhasil!
Dengan trusted_proxies:
Caddy hanya percaya X-Forwarded-For dari IP yang ada di trusted list
IP dari client langsung selalu ditambahkan ke akhir
{
servers {
# IP yang dipercaya untuk header forwarding
# Sesuaikan dengan IP load balancer / proxy di depan Caddy
trusted_proxies static 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
# Cloudflare (contoh, cek dokumentasi Cloudflare untuk IP terbaru)
# trusted_proxies static 103.21.244.0/22 103.22.200.0/22 ...
}
}
example.com {
reverse_proxy backend:3000 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Menghapus Header #
example.com {
reverse_proxy backend:3000 {
# Hapus header dengan prefix '-'
# Hapus header sensitif dari request sebelum ke backend
header_up -X-Internal-Secret
header_up -Authorization # Jika auth ditangani di Caddy, tidak perlu ke backend
# Hapus header dari response sebelum ke client
header_down -X-Powered-By # Sembunyikan teknologi stack
header_down -Server
header_down -X-Runtime
header_down -X-Debug-Info
}
}
Menambahkan Header ke Response (header_down) #
example.com {
reverse_proxy backend:3000 {
# Security headers — tambahkan di proxy level
# agar konsisten untuk semua response termasuk error dari backend
header_down Strict-Transport-Security "max-age=31536000; includeSubDomains"
header_down X-Frame-Options "SAMEORIGIN"
header_down X-Content-Type-Options "nosniff"
header_down Referrer-Policy "strict-origin-when-cross-origin"
# Versi API yang digunakan
header_down X-API-Version "v2.1.0"
# Hapus header informatif
header_down -Server
header_down -X-Powered-By
}
}
CORS via Proxy Header #
Untuk mengaktifkan CORS dari sisi proxy (tanpa perlu mengubah kode backend):
api.example.com {
@preflight method OPTIONS
# Handle CORS preflight request
handle @preflight {
header Access-Control-Allow-Origin "https://app.example.com"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH, OPTIONS"
header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With"
header Access-Control-Allow-Credentials "true"
header Access-Control-Max-Age "86400"
respond "" 204
}
# Tambahkan CORS header ke semua response
reverse_proxy backend:8080 {
header_down Access-Control-Allow-Origin "https://app.example.com"
header_down Access-Control-Allow-Credentials "true"
header_down Access-Control-Expose-Headers "X-Total-Count, X-Page"
}
}
Request ID Tracking #
Untuk distributed tracing dan korelasi log:
example.com {
# Tambahkan request ID unik ke setiap request
# Backend bisa log ID ini, memudahkan tracing masalah
header X-Request-ID {http.request.uuid}
reverse_proxy backend:3000 {
# Teruskan ke backend
header_up X-Request-ID {http.request.uuid}
# Return ke client juga (untuk debugging dari sisi client)
header_down X-Request-ID {http.request.uuid}
}
log {
format json
# Log otomatis menyertakan request UUID
}
}
Rate Limit Headers #
Memberi informasi rate limit ke client via header response:
api.example.com {
# Jika menggunakan plugin rate_limit, tambahkan info ke header
reverse_proxy backend:8080 {
# Pass-through rate limit headers dari backend
# (jika backend mengelola rate limit sendiri)
header_down X-RateLimit-Limit ""
header_down X-RateLimit-Remaining ""
header_down X-RateLimit-Reset ""
}
}
Header untuk Autentikasi ke Backend #
internal-api.example.com {
# Verifikasi JWT di level Caddy (dengan plugin)
# Kemudian teruskan user info ke backend via header
reverse_proxy backend:8080 {
# Teruskan user ID yang sudah di-extract dari JWT
header_up X-User-ID {http.auth.user.id}
header_up X-User-Email {http.auth.user.email}
header_up X-User-Role {http.auth.user.role}
# Hapus Authorization header agar backend tidak perlu validasi ulang
# (karena Caddy sudah validasi di atas)
header_up -Authorization
}
}
Debugging Header #
# Lihat header yang dikirim Caddy ke backend
# Aktifkan debug log sementara di Caddyfile:
# {
# debug
# }
# Atau tangkap request di backend
# Untuk Node.js/Express sementara, tambahkan:
# app.use((req, res, next) => { console.log(req.headers); next(); });
# Atau gunakan httpbin untuk melihat header
# reverse_proxy httpbin.org {
# header_up Host "httpbin.org"
# }
# Akses /get atau /headers untuk melihat apa yang diterima
# Lihat header response dari Caddy
curl -I https://example.com/
# Atau lebih detail:
curl -sv https://example.com/ 2>&1 | grep "^[<>]"
Anti-Pattern yang Harus Dihindari #
# ANTI-PATTERN 1: Meneruskan header Authorization tanpa pemikiran
example.com {
reverse_proxy backend:3000 {
# Ini OK jika backend perlu validasi auth sendiri
# Tapi jika Caddy sudah handle auth, hapus header ini
# agar backend tidak di-bypass
header_up Authorization {header.Authorization}
}
}
# ANTI-PATTERN 2: Mempercaya X-Forwarded-For dari client tanpa trusted_proxies
# → Attacker bisa spoof IP address
# BENAR: Set trusted_proxies di global options untuk menentukan
# proxy mana yang boleh di-trust untuk X-Forwarded-For
Ringkasan #
header_upuntuk modifikasi header request ke backend,header_downuntuk modifikasi header response ke client.- Selalu teruskan
X-Real-IP,X-Forwarded-For, danX-Forwarded-Protoagar backend bisa mengetahui informasi client asli.- Konfigurasi
trusted_proxiesdi global options untuk mencegah IP spoofing viaX-Forwarded-For— hanya percaya header dari proxy yang kamu kontrol.- Hapus header informatif dari response (
-Server,-X-Powered-By) untuk menyembunyikan teknologi stack dari publik.- Tambahkan
X-Request-ID {http.request.uuid}untuk distributed tracing dan korelasi log antara Caddy dan backend.- Gunakan
header_downdi reverse_proxy untuk menambahkan security headers secara konsisten ke semua response, termasuk error dari backend.
← Sebelumnya: Konfigurasi Reverse Proxy Berikutnya: Transport →