Panduan Lengkap Firewall Rules di Cloudflare
Pendahuluan
Setiap aplikasi web yang terhubung ke internet pasti menghadapi ancaman: bot jahat, serangan brute-force, scraper agresif, hingga request berbahaya dari negara tertentu. Cloudflare Firewall Rules hadir sebagai lapisan pertahanan yang cerdas dan fleksibel — memungkinkan kamu mendefinisikan aturan keamanan sendiri berdasarkan berbagai atribut request.
Berbeda dengan firewall tradisional yang hanya melihat IP dan port, Cloudflare Firewall Rules dapat menginspeksi header HTTP, URI, user agent, negara asal, skor ancaman, bahkan konten body request. Jika kamu ingin membangun layanan dengan skala seperti Tokopedia atau Shopee yang menerima jutaan request per hari, kemampuan memfilter traffic secara presisi ini sangat krusial.
Artikel ini membahas Firewall Rules di level lanjutan — dari sintaks ekspresi, strategi prioritas aturan, hingga penerapan nyata yang sering dihadapi developer.
Konsep Inti dan Komponen Firewall Rules
Struktur Dasar Sebuah Rule
Setiap Firewall Rule terdiri dari tiga komponen utama:
- Expression — kondisi yang dievaluasi (siapa yang boleh/tidak boleh lewat)
- Action — tindakan yang diambil jika ekspresi bernilai
true - Priority — urutan evaluasi rule (angka lebih kecil = lebih prioritas)
Cloudflare mengevaluasi setiap incoming request terhadap semua rule yang aktif, lalu mengeksekusi action dari rule dengan prioritas tertinggi yang cocok.
Daftar Action yang Tersedia
| Action | Keterangan |
|---|---|
block | Langsung tolak request (HTTP 403) |
challenge | Tampilkan CAPTCHA interaktif |
js_challenge | Jalankan JS challenge (transparan untuk browser nyata) |
managed_challenge | Cloudflare tentukan sendiri jenis challenge |
allow | Izinkan request, lewati rule berikutnya |
log | Catat ke log tanpa memblokir (Cloudflare Enterprise) |
skip | Lewati WAF, Rate Limiting, atau rule lain tertentu |
Field Utama dalam Ekspresi
Cloudflare menggunakan bahasa ekspresi mirip dengan filter Wireshark:
# Field yang sering digunakan:
ip.src → Alamat IP sumber
ip.geoip.country → Kode negara (ISO 3166-1 alpha-2)
http.request.uri → Full URI termasuk query string
http.request.uri.path → Hanya path tanpa query
http.host → Hostname dari request
http.user_agent → User-Agent header
http.request.method → HTTP method (GET, POST, dll.)
cf.threat_score → Skor ancaman Cloudflare (0-100)
cf.bot_management.score → Skor bot (0-99, rendah = lebih bot-like)
Membangun Ekspresi dan Aturan Lanjutan
Sintaks Ekspresi Dasar
# Blokir semua request dari IP spesifik
ip.src eq 192.168.1.100
# Blokir request dengan threat score tinggi
cf.threat_score gt 30
# Izinkan hanya method GET dan POST
not (http.request.method in {"GET" "POST"})
# Blokir berdasarkan user agent (scraper)
http.user_agent contains "python-requests"
Operator yang Tersedia
eq → sama dengan
ne → tidak sama dengan
lt / gt → kurang dari / lebih dari
le / ge → kurang dari atau sama dengan / lebih dari atau sama dengan
contains → mengandung substring
matches → cocok dengan regex
in → ada dalam kumpulan nilai
Ekspresi Kompleks dengan Logika Boolean
# Blokir bot dengan threat score tinggi KECUALI dari IP whitelist
(cf.threat_score gt 50) and not (ip.src in {203.0.113.1 203.0.113.2})
# Lindungi endpoint login dari brute-force berdasarkan negara
(http.request.uri.path eq "/api/login") and
not (ip.geoip.country in {"ID" "SG" "MY"})
# Blokir scraper yang mencoba akses sitemap
(http.request.uri.path contains "/sitemap") and
(http.user_agent matches "(?i)(bot|crawler|spider|scraper)") and
not (cf.verified_bot_category ne "")
Menggunakan Fungsi Transformasi
# Case-insensitive matching untuk user agent
lower(http.user_agent) contains "scrapy"
# Cek panjang URI (antisipasi path traversal)
len(http.request.uri.path) gt 200
# Cek jumlah cookie
len(http.cookie) gt 4096
Strategi Penerapan dan Best Practices
Prinsip Urutan Prioritas
Cloudflare mengevaluasi rules dari prioritas terendah angkanya terlebih dahulu. Gunakan strategi ini:
Priority 1 → Whitelist (allow) untuk IP internal / monitoring tools
Priority 5 → Allowlist bot resmi (Googlebot, dll.)
Priority 10 → Blokir threat score tinggi
Priority 20 → Challenge negara tertentu di endpoint sensitif
Priority 50 → Rate limiting custom
Priority 100 → Aturan umum (catch-all)
Strategi Tiered Defense
Jangan langsung block — gunakan pendekatan bertahap:
# Tier 1: Blokir ancaman nyata
(cf.threat_score gt 70) → block
# Tier 2: Challenge yang mencurigakan
(cf.threat_score gt 30) or
(not cf.bot_management.verified_bot and cf.bot_management.score lt 30) → managed_challenge
# Tier 3: Log saja untuk monitoring
(http.user_agent contains "curl") and
(http.request.uri.path contains "/api/") → log
Lindungi Endpoint Kritis
Untuk aplikasi yang memiliki panel admin atau API sensitif — bayangkan seperti membangun dashboard internal ala sistem manajemen Gojek — isolasi akses dengan ketat:
# Hanya izinkan akses admin dari IP kantor
(http.request.uri.path wildcard "/admin/*") and
not (ip.src in {203.0.113.10 203.0.113.11 203.0.113.12}) → block
# Proteksi API key endpoint
(http.request.uri.path eq "/api/v1/keys") and
not (http.request.method eq "GET") and
(cf.threat_score gt 10) → challenge
Integrasi dengan Variabel Dinamis
Untuk pengelolaan sekumpulan IP yang berubah, manfaatkan IP Lists di Cloudflare:
# Buat IP List bernama "trusted_ips" di dashboard, lalu referensikan:
ip.src in $trusted_ips → allow
# Gabungkan dengan kondisi lain
(http.request.uri.path contains "/webhook") and
not (ip.src in $github_hooks_ips) → block
Pola manajemen IP List ini mirip dengan konsep Secrets vs Variables di GitHub Actions — data sensitif dikelola terpusat, bukan hardcoded di setiap aturan.
Contoh Kasus Nyata
Kasus 1: Melindungi API dari Abuse
# Blokir request tanpa header Authorization ke endpoint API
(http.request.uri.path wildcard "/api/v2/*") and
not (http.request.headers["authorization"][*] ne "") → block
# Challenge request dengan rate tinggi dari satu ASN
(ip.geoip.asnum eq 12345) and
(http.request.uri.path contains "/api/") → js_challenge
Kasus 2: Geo-Restriction untuk Konten Berbayar
# Konten premium hanya untuk Indonesia, Singapura, Malaysia
(http.request.uri.path wildcard "/premium/*") and
not (ip.geoip.country in {"ID" "SG" "MY"}) → block
Kasus 3: Mitigasi SQL Injection via URI
# Deteksi pola SQL injection sederhana di query string
(http.request.uri.query matches "(?i)(union.*select|drop.*table|insert.*into|'.*or.*'.*=.*')") → block
Kasus 4: Proteksi Upload Endpoint
# Batasi upload hanya dari user yang terautentikasi (ada cookie sesi)
(http.request.uri.path eq "/upload") and
(http.request.method eq "POST") and
not (http.cookie contains "session_id=") → challenge
Pendekatan sistematis dalam menyusun rules ini mirip dengan cara kerja Memahami Komponen Dasar GitHub Actions: Workflow, Job, dan Step — setiap aturan dieksekusi secara berurutan dengan logika yang terstruktur.
Troubleshooting: Error yang Sering Muncul
Rule Aktif tapi Traffic Tidak Terblokir
Penyebab: Rule memiliki prioritas lebih rendah dari rule allow yang sudah ada, atau traffic berasal dari Cloudflare Verified Bot yang di-skip secara default.
Solusi:
# Cek dengan Cloudflare Firewall Events Log:
# Dashboard → Security → Events → Filter by Rule ID
# Pastikan tidak ada rule "allow" dengan prioritas lebih tinggi:
# Urutkan rules berdasarkan priority, cek rule dengan angka < rule kamu
# Untuk override verified bot, tambahkan kondisi eksplisit:
(cf.bot_management.score lt 10) and
(http.request.uri.path eq "/api/scrape-target") → block
Error “Expression Too Long” saat Menyimpan Rule
Penyebab: Cloudflare membatasi panjang ekspresi. Plan Free/Pro memiliki batas karakter yang lebih ketat dibanding Business/Enterprise.
Solusi:
# SEBELUM: Ekspresi panjang dengan banyak IP individual
ip.src in {1.2.3.4 5.6.7.8 9.10.11.12 ... (100 IP)} → block
# SESUDAH: Gunakan IP Lists
# 1. Buat IP List di My Profile → Configurations → Lists
# 2. Upload IP via API:
curl -X POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/rules/lists/{list_id}/items" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
--data '[{"ip": "1.2.3.4"}, {"ip": "5.6.7.8"}]'
# 3. Referensikan di rule:
ip.src in $nama_list → block
False Positive: User Legitimate Kena Block
Penyebab: Ekspresi terlalu agresif, atau cf.threat_score terlalu rendah threshold-nya sehingga menangkap user asli dari ISP tertentu.
Solusi:
# Ganti action "block" ke "managed_challenge" dulu untuk observasi
(cf.threat_score gt 20) → managed_challenge
# Tambahkan pengecualian untuk ISP/ASN yang sering false positive
(cf.threat_score gt 20) and
not (ip.geoip.asnum in {4761 17974 7713}) → managed_challenge
# ASN 4761 = Indosat, 17974 = Telkomsel, 7713 = Telkom Indonesia
# Monitor di Security Events selama 24-48 jam sebelum aktifkan block
Rule Skip Tidak Berfungsi untuk WAF Managed Rules
Penyebab: Action skip memerlukan konfigurasi eksplisit komponen mana yang di-skip. Tanpa opsi yang tepat, WAF managed rules tetap berjalan.
Solusi:
# Di Expression Editor, tambahkan rule Skip dengan konfigurasi:
# Action: Skip
# Skip: WAF Managed Rules (centang opsi ini secara eksplisit)
# Contoh: Skip WAF untuk traffic dari payment gateway
(ip.src in $payment_gateway_ips) → skip [waf managed rules]
# Via API:
{
"action": "skip",
"action_parameters": {
"ruleset": "current",
"phases": ["http_request_firewall_managed"]
},
"expression": "ip.src in $payment_gateway_ips"
}
Pertanyaan yang Sering Diajukan
Apa perbedaan Firewall Rules dengan WAF Managed Rules di Cloudflare?
Firewall Rules (kini disebut Custom Rules) adalah aturan yang kamu tulis sendiri berdasarkan logika bisnis spesifik aplikasimu. WAF Managed Rules adalah kumpulan aturan siap pakai yang dikelola Cloudflare untuk menangkal ancaman umum seperti OWASP Top 10. Keduanya bisa aktif bersamaan, dan kamu bisa menggunakan action skip untuk menonaktifkan WAF Managed Rules pada request tertentu yang trusted.
Bagaimana cara menguji Firewall Rule sebelum mengaktifkannya di production?
Gunakan action log terlebih dahulu (tersedia di plan Enterprise) atau manfaatkan fitur Simulate di Expression Editor. Untuk plan non-Enterprise, ubah action ke js_challenge selama beberapa jam sambil memantau Firewall Events — JS Challenge tidak memblokir browser asli tetapi memberi sinyal apakah rule menangkap traffic yang tepat.
Berapa jumlah maksimum Firewall Rules yang bisa dibuat?
Batas rule bergantung pada plan: Free (5 rules), Pro (20 rules), Business (100 rules), Enterprise (1000+ rules). Untuk memaksimalkan kuota, gunakan operator in dengan multiple value dalam satu rule daripada membuat rule terpisah untuk setiap kondisi.
Apakah Firewall Rules memengaruhi performa website?
Dampaknya sangat minimal karena evaluasi dilakukan di edge network Cloudflare sebelum request menyentuh server aslimu. Namun, ekspresi dengan regex kompleks atau banyak kondisi bersarang bisa sedikit menambah latensi evaluasi. Gunakan kondisi sederhana di prioritas awal untuk early exit pada traffic yang jelas aman.
Apa itu cf.threat_score dan bagaimana cara kerjanya?
cf.threat_score adalah skor 0-100 yang dihitung Cloudflare berdasarkan reputasi IP, data historis serangan, dan threat intelligence dari seluruh jaringan Cloudflare. Skor 0 berarti IP bersih, skor 100 berarti sangat berbahaya. Umumnya, threshold di atas 30 sudah cukup untuk challenge, dan di atas 50 untuk block — namun kamu perlu menyesuaikan berdasarkan false positive rate di sitemu.
Kesimpulan
Cloudflare Firewall Rules adalah alat yang sangat powerful untuk melindungi aplikasi web dari berbagai ancaman. Kunci keberhasilan implementasinya terletak pada pemahaman sintaks ekspresi, strategi prioritas yang tepat, dan pendekatan bertahap (log → challenge → block) agar tidak memblokir user legitimate.
Mulai dari rule sederhana seperti memblokir IP dengan threat score tinggi, lalu tingkatkan kompleksitasnya sesuai kebutuhan spesifik aplikasimu. Pantau Firewall Events secara rutin, dan jangan ragu bereksperimen dengan ekspresi baru di environment staging terlebih dahulu.
Selamat belajar dan terus bereksperimen! Keamanan aplikasi adalah perjalanan berkelanjutan — semakin sering kamu menyempurnakan rules-mu, semakin tangguh pertahanan aplikasimu. Jika ada pertanyaan lebih lanjut, jangan ragu untuk eksplorasi artikel-artikel lainnya di KamusNgoding.