← Semua pembelajaran / Astro Nol → Portal Berita
Fase 8 · Cloudflare: Cache, Edge & WAF

Menutup origin — WAF yang bisa dilewati bukan WAF

Ini kesalahan konfigurasi paling umum pada arsitektur Cloudflare di depan AWS, dan yang paling jarang diperiksa — karena situsnya bekerja sempurna meski salah.

Intisari

  • IP origin yang bisa dihubungi langsung = seluruh lapisan Cloudflare terlewati.
  • IP origin bocor lewat riwayat DNS, sertifikat, header email, dan halaman error — bukan rahasia.
  • Dua perbaikan: kunci security group ke rentang IP Cloudflare, atau Cloudflare Tunnel tanpa ALB publik.
  • Tunnel lebih rapat: tidak ada IP publik sama sekali, tidak ada inbound port yang terbuka.
  • SSL mode wajib Full (strict). Flexible mengirim plaintext ke origin dan bisa membuat loop redirect.

Serangannya sesederhana ini

# Cari IP origin — biasanya tidak sulit
dig +short portal-alb-123456.ap-southeast-3.elb.amazonaws.com

# Lalu lewati Cloudflare sepenuhnya
curl -H 'Host: portal.contoh.id' https://<ip-alb>/akun
Yang terlewatiAkibatnya
WAFPayload SQLi/XSS langsung ke aplikasi
Rate limitingCredential stuffing tanpa batas ke halaman login
Bot protectionScraping penuh isi berbayar
CacheSetiap permintaan memukul origin
DDoS protectionOrigin-mu terekspos langsung
cf-connecting-ipBisa dipalsukan — rate limit aplikasimu ikut jebol

Baris terakhir itu menghubungkan kembali ke Fase 1. Di sana kita memakai cf-connecting-ip untuk rate limiting karena "tidak bisa ditimpa klien". Itu benar hanya kalau satu-satunya jalan masuk adalah lewat Cloudflare. Kalau origin bisa dihubungi langsung, penyerang tinggal mengirim header itu sendiri dengan nilai apa pun — dan seluruh pembatas yang berbasis IP jadi tidak berarti.

IP origin bukan rahasia

Sumber kebocoranCatatan
Riwayat DNSArsip publik menyimpan record dari sebelum Cloudflare dipasang
Certificate TransparencySetiap sertifikat yang pernah diterbitkan tercatat publik
Header emailEmail dari servermu membawa IP-nya
Subdomain yang tidak di-proxystaging., mail., ftp. — abu-abu, bukan oranye
Halaman error & phpinfoSisa dari CI3
Pemindai internetMencocokkan sertifikat di seluruh ruang IPv4 secara berkala

Kesimpulannya: jangan bergantung pada kerahasiaan IP. Asumsikan sudah diketahui, lalu pastikan mengetahuinya tidak berguna.

Perbaikan 1: kunci security group

# Ambil rentang IP Cloudflare
curl -s https://www.cloudflare.com/ips-v4 -o /tmp/cf4.txt
curl -s https://www.cloudflare.com/ips-v6 -o /tmp/cf6.txt

# Terapkan ke security group ALB
SG=sg-0123456789abcdef0
while read -r cidr; do
  aws ec2 authorize-security-group-ingress \
    --group-id "$SG" --protocol tcp --port 443 --cidr "$cidr" \
    --description "Cloudflare" 2>/dev/null
done < /tmp/cf4.txt
KelebihanKekurangan
Perubahan kecil, mudah dipahamiRentang IP Cloudflare berubah sesekali
Tidak menambah komponenButuh otomatisasi pembaruan, atau situsmu mati suatu hari
ALB tetap seperti biasaBatas jumlah aturan per security group bisa tercapai
—Pelanggan Cloudflare lain juga berasal dari IP itu

Baris terakhir sering terlewat. Membatasi ke IP Cloudflare berarti "hanya lalu lintas yang melewati Cloudflare" — bukan "hanya lalu lintas yang melewati zona Cloudflare-ku". Siapa pun yang punya akun Cloudflare bisa mengarahkan zona miliknya ke IP origin-mu dan lolos filter itu. Tutupnya: verifikasi sertifikat klien (Authenticated Origin Pulls) atau header rahasia yang ditambahkan Cloudflare dan diperiksa origin-mu.

Cloudflare → Transform Rules → Modify Request Header:
  Set static:  X-Origin-Token = <nilai acak panjang dari Secrets Manager>
// src/middleware/asal.ts
export const hanyaLewatCloudflare = defineMiddleware(async (ctx, next) => {
  const token = ctx.request.headers.get("x-origin-token");

  if (token !== env.ORIGIN_TOKEN) {
    return new Response("Forbidden", { status: 403 });
  }
  return next();
});

Perbaikan 2: Cloudflare Tunnel (lebih rapat)

Dengan ALB publik:
  Internet → ALB (IP publik) → ECS
             ↑ bisa dihubungi siapa saja

Dengan Tunnel:
  Internet → Cloudflare → terowongan keluar ← cloudflared (sidecar di ECS)
             tidak ada IP publik, tidak ada port masuk yang terbuka

cloudflared berjalan sebagai kontainer sidecar di task ECS yang sama dan membuka koneksi keluar ke Cloudflare. Tidak ada satu pun port masuk yang terbuka — bahkan tidak ada alamat untuk dituju.

{
  "family": "portal",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "web",
      "image": "…/portal:abc123",
      "portMappings": [{ "containerPort": 4321 }],
      "essential": true
    },
    {
      "name": "cloudflared",
      "image": "cloudflare/cloudflared:2026.8.0",
      "command": ["tunnel", "--no-autoupdate", "run"],
      "secrets": [
        { "name": "TUNNEL_TOKEN", "valueFrom": "arn:aws:secretsmanager:…:portal/tunnel:token::" }
      ],
      "essential": true,
      "dependsOn": [{ "containerName": "web", "condition": "START" }]
    }
  ]
}
KelebihanKekurangan
Tidak ada IP publik sama sekaliSatu kontainer lagi per task
Tidak ada biaya ALBHealth check & deployment butuh penyesuaian
Tidak ada rentang IP yang harus dipeliharaKetergantungan tambahan pada Cloudflare
Tidak perlu sertifikat di originMenelusuri masalah jaringan jadi kurang langsung

Yang mana untukmu? Kalau kamu sedang membangun dari awal, Tunnel lebih sederhana dan lebih aman — dan menghapus biaya ALB. Kalau kamu memigrasikan dari CI3 yang sudah di belakang ALB, kunci security group plus header rahasia lebih sedikit perubahan dan bisa dipasang minggu ini. Keduanya menutup lubangnya; yang penting adalah salah satunya benar-benar dipasang.

SSL mode: Full (strict), bukan yang lain

ModeCloudflare → originVerdict
OffHTTPTidak pernah
FlexibleHTTP polosTidak pernah — dan sumber loop redirect
FullHTTPS, sertifikat tidak diverifikasiRentan MITM di jalur Cloudflare→origin
Full (strict)HTTPS, sertifikat diverifikasiYang benar

Mode Flexible adalah penyebab klasik loop redirect tak berujung. Cloudflare menghubungi origin lewat HTTP; origin melihat HTTP dan mengalihkan ke HTTPS; Cloudflare menerima redirect itu dan meminta ulang lewat HTTP; dan seterusnya. Gejalanya "ERR_TOO_MANY_REDIRECTS" yang muncul untuk sebagian pembaca dan tidak untuk yang lain, tergantung cache.

Untuk ALB, pakai sertifikat ACM. Untuk origin lain, Cloudflare Origin CA gratis dan berlaku 15 tahun. Dengan Tunnel, ini tidak berlaku sama sekali — terowongannya sudah terenkripsi.

Verifikasi — lakukan ini, jangan diasumsikan

IP=<ip-origin-mu>

# 1. Harus TIMEOUT atau ditolak, bukan menjawab
curl -m 5 -H 'Host: portal.contoh.id' "https://$IP/" -k -sS -o /dev/null -w '%{http_code}\n'

# 2. Tanpa header rahasia, harus 403
curl -m 5 -H 'Host: portal.contoh.id' "https://$IP/berita/uji" -k -si | head -1

# 3. cf-connecting-ip palsu tidak boleh dipercaya
curl -sS https://portal.contoh.id/api/uji-ip -H 'CF-Connecting-IP: 1.2.3.4'

# 4. SSL mode
curl -sI http://portal.contoh.id/ | head -3    # harus 301 ke https, tanpa loop

Latihan: temukan IP origin-mu sendiri seperti penyerang akan melakukannya — periksa riwayat DNS domainmu dan log Certificate Transparency untuk domainmu. Lalu jalankan uji nomor 1: kalau origin-mu menjawab, kamu baru saja menemukan bahwa seluruh lapisan keamanan Cloudflare-mu opsional. Tutup dengan salah satu dari dua perbaikan, lalu jalankan ulang seluruh empat uji.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.