03. Cloudflare Tunnel

03. Cloudflare Tunnel Setup

Cloudflare Tunnel (cloudflared) memungkinkan server menjalankan aplikasi di balik firewall tanpa membuka port publik. Traffic diteruskan melalui tunnel terenkripsi yang diinisiasi oleh server (outbound connection).

3.1 Prasyarat

  • Akses ke dashboard Cloudflare One (https://one.dash.cloudflare.com)
  • Domain yang sudah dikonfigure di Cloudflare
  • Token tunnel dari dashboard
  • Sudah melakukan baseline security setup (bagian 01)

3.2 Instalasi Cloudflared

Step 1: Setup Repository dan Install Paket

# Create directory untuk keyrings
sudo mkdir -p --mode=0755 /usr/share/keyrings

# Add Cloudflare GPG key
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

# Add this repo to apt
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list

# Install cloudflared
sudo apt-get update && sudo apt-get install -y cloudflared

3.3 Enroll Service Tunnel

Step 1: Dapatkan Token dari Dashboard

  1. Login ke https://one.dash.cloudflare.com
  2. Navigasi ke AccessTunnels (atau NetworkTunnels)
  3. Klik Create a tunnel atau Add tunnel
  4. Pilih Cloudflared sebagai connector type
  5. Cloudflare akan menampilkan token unik untuk server Anda

Step 2: Install Tunnel Service

Jalankan command service install dengan token dari dashboard:

# Command dari dashboard (contoh format):
sudo cloudflared service install <TUNNEL_TOKEN_HERE>

# Contoh dengan token nyata (format):
# sudo cloudflared service install <YOUR_CLOUDFLARE_TUNNEL_TOKEN>

Catatan:

  • Token adalah credentials unik per tunnel dan server
  • Jangan share token ke repository publik
  • Service secara otomatis restart jika crashed

Step 3: Verifikasi Installation dan Service Status

# Cek apakah service sudah jalan
sudo systemctl status cloudflared

# Lihat logs real-time
sudo journalctl -u cloudflared -f

# Verifikasi tunnel terhubung ke dashboard
curl -s http://127.0.0.1:9090/ready

Expected output pada /ready: 200 OK berarti tunnel aktif dan terhubung.

Step 4: Verifikasi di Dashboard

  1. Login ke https://one.dash.cloudflare.com
  2. Navigasi ke AccessTunnels
  3. Lihat tunnel server Anda dengan status Connected (biasanya terlihat dalam 30 detik)

3.4 Konfigurasi Tunnel Routes

Setelah tunnel terhubung, configure routing untuk aplikasi backend.

Step 1: Tentukan Service Backend

Tunnel perlu tahu aplikasi mana yang akan di-proxy. Contoh routing:

Hostname Backend Port
app.<YOUR_DOMAIN> 127.0.0.1 5000 (Node.js)
api.<YOUR_DOMAIN> 127.0.0.1 5001 (Python/Gunicorn)
admin.<YOUR_DOMAIN> 127.0.0.1 3000 (Go)

Step 2: Configure via Dashboard atau config.yaml

  1. Di dashboard Tunnel, klik Configure
  2. Tab Public Hostname
  3. Add a public hostname:
    • Subdomain: app atau full domain
    • Domain: <YOUR_DOMAIN>
    • Type: HTTP atau HTTPS
    • URL: http://127.0.0.1:5000 (atau service backend)
  4. Save hostname
  5. Tunnel secara otomatis akan route traffic ke backend

Opsi B: Via config.yaml (Advanced)

Edit atau buat config di ~/.cloudflared/config.yaml (run sebagai user yang menjalankan service):

tunnel: <TUNNEL_ID>
credentials-file: /home/<app-user>/.cloudflared/<TUNNEL_ID>.json

ingress:
  # Route 1: API
  - hostname: api.<YOUR_DOMAIN>
    service: http://127.0.0.1:5001
    
  # Route 2: Web App
  - hostname: app.<YOUR_DOMAIN>
    service: http://127.0.0.1:5000
    
  # Route 3: Admin
  - hostname: admin.<YOUR_DOMAIN>
    service: http://127.0.0.1:3000
    
  # Catch-all (optional, untuk debugging)
  - service: http_status:404

Catatan: Setelah edit config.yaml, restart service: sudo systemctl restart cloudflared

3.5 Integrasi dengan Backend Services

Pastikan Backend Listening Lokal

Semua aplikasi backend HARUS listen pada 127.0.0.1 (localhost), bukan 0.0.0.0:

Node.js (Express)

app.listen(5000, '127.0.0.1', () => {
  console.log('Server listening on 127.0.0.1:5000');
});

Python (Gunicorn)

gunicorn -w 4 -b 127.0.0.1:5001 app:app

Go

http.ListenAndServe("127.0.0.1:5002", router)

Service Systemd Hardening

Pastikan backend services sudah ter-setup dengan systemd sandboxing (lihat 04_role_web_app.md).

3.6 SSL/TLS & Security Headers

Tunnel-level SSL

Cloudflare secara otomatis menangani SSL/TLS antara client dan Cloudflare edge. Untuk backend communication:

# Untuk backend yang tidak ada cert, gunakan http://
# Tunnel akan re-encrypt traffic ke client

# Untuk backend dengan self-signed cert, option di dashboard:
# Opsi "No TLS Verify" jika testing, tapi jangan di production!

Add Security Headers (via Cloudflare Rule)

  1. Dashboard Cloudflare
  2. RulesTransform Rules atau Page Rules
  3. Create rule untuk add security headers:
    • Host: <YOUR_DOMAIN>
    • Header: Strict-Transport-Security: max-age=31536000
    • Header: X-Content-Type-Options: nosniff

Alternatif: Configure di backend application (Node.js/Python) langsung.

3.7 Monitoring & Logging

Real-time Service Logs

# Tail logs cloudflared service
sudo journalctl -u cloudflared -f

# Filter untuk error saja
sudo journalctl -u cloudflared | grep -i error

# Persisten logs (jika available)
sudo tail -f /var/log/cloudflared.log

Monitor Tunnel Status

# Check tunnel connection health
curl http://127.0.0.1:9090/ready

# Metrics (jika enabled)
curl http://127.0.0.1:9090/metrics

Dashboard Monitoring

  1. Di https://one.dash.cloudflare.comAccessTunnels
  2. Lihat tunnel status dan last activity
  3. Cek logs untuk akses/errors

3.8 Troubleshooting

Issue Solusi
Tunnel tidak terkoneksi ke dashboard Cek token valid, pastikan sudo systemctl status cloudflared running, lihat logs: sudo journalctl -u cloudflared
Backend unreachable (502 Bad Gateway) Verifikasi backend service jalan dengan netstat -tlnp | grep 5000, pastikan listening di 127.0.0.1
Tunnel connects tapi traffic tidak ter-route Di dashboard, check route sudah di-configure dengan benar, restart: sudo systemctl restart cloudflared
SSL certificate error Jika backend punya cert, ensure hostname match, atau disable “TLS Verify” hanya untuk testing
High latency/slow response Cek network latency, monitor backend performance, check Cloudflare region terdekat
Tunnel ngk start after reboot Pastikan service enabled: sudo systemctl enable cloudflared, check token credentials masih valid
Credentials file not found Service install harusnya auto-create credentials, jika tidak ada, re-run: sudo cloudflared service install <TOKEN>

3.9 Advanced Configuration

Multiple Backends

Jika punya multiple services di port berbeda:

ingress:
  - hostname: app1.<YOUR_DOMAIN>
    service: http://127.0.0.1:5000
    
  - hostname: app2.<YOUR_DOMAIN>
    service: http://127.0.0.1:5001
    
  - service: http_status:404

Request Path Routing

ingress:
  - hostname: api.<YOUR_DOMAIN>
    path: /v1/*
    service: http://127.0.0.1:5001
    
  - hostname: api.<YOUR_DOMAIN>
    path: /v2/*
    service: http://127.0.0.1:5002

WebSocket Support

Tunnel mendukung WebSocket out-of-the-box. Pastikan backend support WebSocket upgrade:

ingress:
  - hostname: realtime.<YOUR_DOMAIN>
    service: ws://127.0.0.1:8080

SSH Access Through Tunnel

Jika perlu SSH remote ke server melalui tunnel:

# Install cloudflared local proxy (di client machine)
cloudflared access ssh --hostname ssh.<YOUR_DOMAIN>

# Connect
ssh username@127.0.0.1 -p 2222

3.10 Best Practices

  • Keep token secure: Jangan commit ke git, store di .env atau vault
  • Monitor connectivity: Set up alerts di dashboard untuk tunnel disconnects
  • Regular updates: Jalankan sudo apt update && sudo apt upgrade -y cloudflared berkala
  • Backup config: Simpan copy config.yaml di safe location
  • Test failover: Simulate tunnel disconnect untuk ensure graceful degradation
  • Use Firewall Rules: Di Cloudflare, tambahkan rules untuk restrict access ke tunnel (IP whitelist, country blocks, etc.)
  • Enable logging: Check dashboard logs untuk audit trail akses
  • Prevent DNS leak: Verifikasi DNS bukan leak traffic outside tunnel side tunnel