Circuit Breaker
Circuit breaker melindungi kuota CPU Worker dari scanner agresif yang memicu honeypot
berkali-kali. Setelah ambang tertentu, IP tersebut menerima response 403 statis yang murah,
tanpa delay, watermark, atau komputasi payload.
Implementasinya ada di src/ratelimit.js dan memakai Workers KV.
Konstanta
Section titled “Konstanta”| Konstanta | Nilai | Arti |
|---|---|---|
STRIKE_TTL_SECONDS |
60 | TTL counter di KV |
STRIKE_THRESHOLD |
5 | Jumlah strike sebelum diblokir |
Kapan dicek
Section titled “Kapan dicek”Circuit breaker hanya dicek setelah request melewati scoring dan dianggap sebagai kandidat serangan. Request normal tidak melakukan panggilan KV sama sekali.
Urutannya:
- Scoring selesai dan
score >= threshold. - Cek
strike:<ip>di KV. - Jika
>= 5, kirim403dan catat eventcircuit_breaker_block. - Jika belum, lanjut ke honeypot dan
recordStrike()menambah counter.
Perhitungan strike
Section titled “Perhitungan strike”const strikes = await kv.get(`strike:${ip}`);return { isBlocked: Boolean(strikes) && parseInt(strikes, 10) >= STRIKE_THRESHOLD };const current = currentRaw ? parseInt(currentRaw, 10) : 0;await kv.put(key, String(current + 1), { expirationTtl: STRIKE_TTL_SECONDS });Karena pengecekan dilakukan sebelum penambahan, blokir mulai berlaku pada trigger keenam:
| Trigger ke- | Counter sebelum cek | Hasil | Counter setelah |
|---|---|---|---|
| 1 | 0 | Honeypot | 1 |
| 2 | 1 | Honeypot | 2 |
| 3 | 2 | Honeypot | 3 |
| 4 | 3 | Honeypot | 4 |
| 5 | 4 | Honeypot | 5 |
| 6 | 5 | 403 | 5 (tidak bertambah) |
| 7+ | 5 | 403 | 5 |
Response blokir
Section titled “Response blokir”HTTP/1.1 403 ForbiddenX-Bangk-Shield: honeypot-active-cbContent-Type: text/plain; charset=utf-8
Blocked by Circuit BreakerResponse ini sengaja sesederhana mungkin agar tidak membebani CPU.
Konfigurasi
Section titled “Konfigurasi”Circuit breaker aktif secara default. Untuk menonaktifkannya:
[vars]CIRCUIT_BREAKER_ENABLED = "false"Di src/index.js, nilai apa pun selain string "false" dianggap aktif:
const circuitBreakerEnabled = env.CIRCUIT_BREAKER_ENABLED !== 'false';Fail-open
Section titled “Fail-open”Jika KV tidak tersedia atau terjadi error:
checkCircuitBreaker()mengembalikan{ isBlocked: false }.recordStrike()menelan error tanpa melempar.
Artinya kegagalan KV tidak pernah memblokir trafik. Konsekuensinya, saat KV bermasalah, perlindungan circuit breaker juga tidak aktif.
Keterbatasan
Section titled “Keterbatasan”- Bukan atomic.
getlaluputbukan operasi atomik. Di bawah burst concurrent yang sangat tinggi, beberapa request bisa membaca nilai yang sama dan hitungan strike meleset. - Bukan rate limiter presisi. Tujuannya anti-abuse ringan, bukan pembatasan request per detik.
- Hanya satu level. PRD mendefinisikan level kedua berupa blokir known-attacker selama 24 jam; itu belum diimplementasikan.
- Counter per IP, bukan per kombinasi IP + vektor. Semua vektor berbagi counter yang sama.
cf-connecting-ipbisa absen di lingkungan non-Cloudflare. Saat itu semua klien memakai kuncistrike:Unknown IPdan saling memengaruhi.