CodeIgniter 4 Shieldv1.2.x
Konfigurasi
Konsep yang perlu Anda pahami dulu
Section titled “Konsep yang perlu Anda pahami dulu”Tiga mode Shield
Section titled “Tiga mode Shield”| Mode | Perilaku |
|---|---|
observe |
Semua keputusan dicatat sebagai OBSERVE; tidak ada challenge atau blokir. Mode awal yang aman. |
challenge |
Ban skor diubah menjadi challenge. Signature critical tetap diblokir. |
enforce |
Semua keputusan dijalankan: challenge, blokir, dan ban. |
Signature critical selalu diblokir di challenge dan enforce. Di observe,
signature tetap dicatat tetapi tidak memblokir.
Denylist dan allowlist
Section titled “Denylist dan allowlist”- Denylist adalah pola yang Shield tolak (aturan bawaan).
- Allowlist membuat host, path, atau IP melewati pemeriksaan signature dan perilaku. Pengecualiannya: signature critical tetap diproses dan dapat memblokir request.
Threshold (ambang batas)
Section titled “Threshold (ambang batas)”Shield menghitung skor risiko untuk tiap request. Semakin mencurigakan, semakin tinggi skornya. Ambang batas menentukan keputusan:
public int $thresholdChallenge = 10; // mulai minta challengepublic int $thresholdBan = 20; // mulai banpublic int $thresholdStrongBan = 30; // ambang ban kuatRequest dengan skor 14 mendapat challenge; request dengan skor 25 mendapat
ban. Saat ini thresholdStrongBan juga menghasilkan TEMP_BAN, bukan durasi
yang otomatis lebih panjang. Durasi tetap ditentukan oleh jumlah offense dan
banDurations.
Default aman: observe
Section titled “Default aman: observe”Semua opsi di bawah sudah punya nilai bawaan yang aman untuk pertama kali
dipasang. Anda tidak perlu mengatur semuanya di awal — baca
shield:report beberapa hari dulu.
Cara mengatur konfigurasi
Section titled “Cara mengatur konfigurasi”Konfigurasi bawaan sudah cukup untuk memulai. Kalau ingin menyesuaikan, buat
file app/Config/Shield.php di aplikasi Anda yang mewarisi konfigurasi
paket:
<?php
namespace Config;
class Shield extends \Ganadev\Shield\Codeigniter\Config\Shield{ public string $mode = 'observe';
public array $sensitivePaths = ['/login', '/admin/login'];
public string $adminAuthorize = 'admin.authorize';}Kelas ini diambil otomatis oleh config('Shield'). Nilai yang tidak Anda tulis
ulang memakai default bawaan. Jangan mewarisi BaseConfig langsung karena Anda
akan kehilangan seluruh default Shield.
Properti config lewat .env
Section titled “Properti config lewat .env”Karena config class mewarisi CodeIgniter\Config\BaseConfig, properti scalar
bisa diganti dari .env tanpa memanggil env() di config class. Prefix pendek
class Shield adalah shield (huruf kecil), dan nama properti harus sama persis
dengan nama di class:
shield.mode = observeshield.thresholdChallenge = 10shield.challengeDriver = turnstileBentuk underscore juga dikenali:
shield_mode = observeshield_thresholdChallenge = 10Pengecualian: kunci challenge dibaca langsung oleh paket dengan getenv() dan
tetap memakai nama uppercase:
SHIELD_TURNSTILE_SITE_KEY=0x4AAAAAAA...SHIELD_TURNSTILE_SECRET_KEY=0x4AAAAAAA...SHIELD_RECAPTCHA_SITE_KEY=...SHIELD_RECAPTCHA_SECRET_KEY=...Jangan memberi nilai default properti dengan env():
// Bukan PHP yang valid: memanggil fungsi di default properti.public string $mode = env('SHIELD_MODE', 'observe');
// Benar: BaseConfig yang mengganti nilai dari .env.public string $mode = 'observe';| Properti | Default | Untuk apa |
|---|---|---|
enabled |
true |
Matikan seluruh Shield sekaligus. |
mode |
observe |
observe (catat saja), challenge (ban menjadi challenge), atau enforce (jalankan semua keputusan). |
appId |
'my-app' |
Nama unik aplikasi Anda, tercatat di setiap kejadian. |
responseCode |
404 |
Kode status saat request diblokir. Umumnya ditolak halus sebagai 404 agar penyerang tidak tahu. |
failMode |
'open' |
open (lewati ban check) atau closed (blokir) saat lookup ban aktif gagal. |
decodeDepth |
2 |
Berapa kali URI di-decode sebelum dicocokkan dengan aturan. |
failMode saat infrastruktur mati
Section titled “failMode saat infrastruktur mati”open(default): kalau lookup ban aktif (findActiveByIp()) melempar exception, ban check dilewati daninfrastructureDegradeddiset. Request tidak otomatis lolos — signature dan sinyal perilaku lain tetap dapat memblokir. Anda kehilangan proteksi berbasis ban, tapi situs tetap hidup.closed: engine langsung membalas blokir denganresponseCode(default 404) dan skor 99 saat lookup ban aktif gagal. Jika exception infrastruktur lolos sampai ke filter, filter membalas 503 Service Unavailable. Situs bisa berhenti total — pilihan ini hanya untuk aplikasi yang keamanannya lebih penting daripada ketersediaannya.
Ban dan eskalasi
Section titled “Ban dan eskalasi”| Properti | Default | Untuk apa |
|---|---|---|
thresholdBan |
20 |
Skor yang memicu ban. |
thresholdStrongBan |
30 |
Ambang ban kuat. Saat ini tetap menghasilkan TEMP_BAN; durasi tidak otomatis lebih panjang. |
banDurations |
[15, 60, 360, 1440] |
Durasi ban berjenjang (menit): 15, 1 jam, 6 jam, 24 jam. |
escalationStep |
5 |
Tambahan skor risiko per offense, dibatasi min(offenseCount, 5) * escalationStep. Bukan pengali durasi ban. |
banCacheTtlSeconds |
30 |
Berapa lama ban di-cache sebelum dicek ulang ke database. |
Durasi ban dipilih dari banDurations memakai offenseCount - 1, lalu
di-clamp ke durasi terakhir. offenseCount berasal dari ban sebelumnya; offense
history tidak dihapus saat ban dirilis.
Challenge
Section titled “Challenge”| Properti | Default | Untuk apa |
|---|---|---|
thresholdChallenge |
10 |
Skor yang memicu challenge. |
challengeDriver |
'turnstile' |
turnstile, recaptcha, atau null / test (untuk development/testing). |
trustedEnabled |
true |
Apakah pengunjung yang lolos challenge ditandai cookie agar tidak di-challenge ulang. |
trustedTtlMinutes |
60 |
Masa berlaku trusted cookie. |
Driver dan kunci challenge diatur terpisah:
shield.challengeDriver = turnstileSHIELD_TURNSTILE_SITE_KEY=0x4AAAAAAA...SHIELD_TURNSTILE_SECRET_KEY=0x4AAAAAAA...Nilai driver null, test, 0, atau string kosong memakai NullTestDriver.
Nilai yang tidak dikenal tidak melempar error; Shield jatuh ke Turnstile. Jangan
memakai SHIELD_CHALLENGE karena itu bukan nama properti challengeDriver.
Baca Challenge & Cookie untuk persiapannya.
Perilaku (rate limit berbasis waktu)
Section titled “Perilaku (rate limit berbasis waktu)”| Properti | Default | Untuk apa |
|---|---|---|
uniqueUriLimit |
25 |
Berapa banyak URL berbeda yang boleh diminta satu IP dalam satu jendela. |
behaviorWindowSeconds |
60 |
Panjang jendela waktu perhitungan perilaku. |
notFoundLimit |
20 |
Berapa banyak 404 yang boleh dihasilkan satu IP. |
pathRateLimit |
30 |
Batas request per path per jendela. |
sensitivePathRateLimit |
8 |
Batas request per path sensitif (mis. /login). |
sensitivePaths |
['/login', '/wp-login.php', ...] |
Path yang dianggap sensitif. |
scannerUaSignal |
4 |
Skor tambahan untuk User-Agent scanner (sqlmap, nikto, dll). |
missingRefererSignal |
true |
Beri sinyal bila request tidak membawa Referer. |
suspiciousUserAgents |
[] |
Marker substring UA tambahan yang memicu sinyal suspicious_user_agent (+2). |
suspiciousUserAgentOverrides |
[] |
Tidak dipakai oleh core CI4; gunakan suspiciousUserAgents. |
scannerUserAgents |
['sqlmap', 'nikto', ...] |
Daftar UA scanner yang mendapat sinyal. |
Paket tidak menyediakan opsi skipBehaviorCounters. skipPaths hanya
melewati pemeriksaan body dan deteksi perilaku; counter unique dan path
tetap naik sebelum keputusan dibuat. Untuk halaman publik yang sering diakses,
gunakan pola gateSkipPaths + ShieldGateFilter yang dipakai default di
Instalasi; penjelasannya ada di
Registrasi & Urutan Filter.
Bot dan crawler
Section titled “Bot dan crawler”| Properti | Default | Untuk apa |
|---|---|---|
botMode |
'observe' |
observe (catat saja, aman untuk SEO), challenge, atau off. |
crawlerVerificationEnabled |
true |
Verifikasi klaim “saya Googlebot” lewat DNS. |
crawlerVerificationTtlHours |
24 |
Berapa lama hasil verifikasi diingat. |
crawlerHostnames |
['googlebot' => [...], ...] |
Suffix host DNS untuk tiap crawler. |
crawlerIpRanges |
[] |
Map ['googlebot' => ['203.0.113.0/24'], ...]; bukan list CIDR datar. |
unverifiedClaimSignal |
4 |
Skor tambahan untuk User-Agent bot yang belum terverifikasi. |
knownBotAgents |
['googlebot', 'bingbot', ...] |
Daftar bot yang dipercaya untuk verifikasi crawler (18 entri default). |
ruleVersion |
'1.0.0' |
Versi rule pack yang dimuat. |
crawlerIpRanges dicocokkan per nama agent. CIDR di bawah key yang salah tidak
akan dipakai. Baca Perilaku & Bot untuk
detailnya.
Aturan dan inspeksi body
Section titled “Aturan dan inspeksi body”| Properti | Default | Untuk apa |
|---|---|---|
rulesPacksInjection |
true |
Aktifkan paket aturan injection (SQLi, XSS, RCE, dll). |
rulesPacksWordpress |
false |
Aktifkan paket aturan WordPress. |
bodyInspectionEnabled |
true |
Periksa isi body request (mendeteksi serangan di JSON). |
bodyInspectionMaxBytes |
65536 |
Batas body yang diperiksa (64 KB). |
maxUriLength |
2048 |
Panjang URI maksimal yang diproses. |
rules.skip_paths
Section titled “rules.skip_paths”Path yang bebas dari pemeriksaan body dan deteksi perilaku. Berguna untuk endpoint M2M atau webhook yang isinya teks bebas:
public array $skipPaths = [ '/api/webhooks/github', '/api/webhooks/xendit',];Perhatikan: path yang di-skip tetap melewati pemeriksaan aturan dasar, hanya body dan deteksi perilaku yang dilewati.
Klien API dan M2M
Section titled “Klien API dan M2M”| Properti | Default | Untuk apa |
|---|---|---|
apiPaths |
[] |
Prefix path yang diperlakukan sebagai API (mis. ['/api']). |
apiDetectAccept |
true |
Otomatis anggap request dengan Accept: application/json sebagai API. |
Untuk request yang terdeteksi sebagai API, respons blokir & challenge dikirim sebagai JSON — bukan HTML.
Logging dan privasi
Section titled “Logging dan privasi”| Properti | Default | Untuk apa |
|---|---|---|
loggingLevel |
'suspicious' |
all, suspicious, atau blocked — seberapa banyak yang dicatat. |
logBypassEvents |
true |
Catat juga kejadian allowlist/trusted-cookie yang lolos. |
retentionDays |
30 |
Umur kejadian sebelum dihapus shield:prune. |
sensitiveQueryParameters |
['token', 'password', ...] |
Parameter query yang nilainya disamarkan di log. |
| Properti | Default | Untuk apa |
|---|---|---|
adminEnabled |
false |
Nyalakan panel admin (default nonaktif). |
adminAuthorize |
'' |
Permission yang dibutuhkan (mis. 'admin.authorize'). Kosong = siapa saja bisa membuka admin, bukan hanya user login. |
adminPrefix |
'shield' |
Prefix URL panel admin. |
Baca Admin API sebelum menyalakannya.
Tampilan dan performa
Section titled “Tampilan dan performa”| Properti | Default | Untuk apa |
|---|---|---|
blockedView |
'shield/blocked' |
View halaman blokir. |
challengeView |
'shield/challenge' |
View halaman challenge. |
brandingTitle |
'Ganadev CodeIgniter Shield' |
Judul di halaman blokir/challenge. |
brandingAccentColor |
'#22d3ee' |
Warna aksen. |
brandingBackgroundColor |
'#0b1220' |
Warna latar. |
brandingShowRuleId |
false |
Tampilkan ID rule di halaman blokir (untuk debugging). |
Allowlist
Section titled “Allowlist”| Properti | Default | Untuk apa |
|---|---|---|
allowlistHosts |
[] |
Host yang selalu lolos. |
allowlistPaths |
[] |
Prefix path yang melewati signature non-critical dan deteksi perilaku. |
allowlistIps |
[] |
IP yang selalu lolos. |
Signature critical tetap diproses meskipun host/path/IP ada di allowlist. Untuk item non-critical, allowlist melewati pemeriksaan signature dan perilaku. Jangan meng-allowlist path yang memuat input dari internet tanpa berpikir panjang.
allowlistPaths dicocokkan dengan str_starts_with polos, bukan per segmen.
/api/health juga cocok dengan /api/healthcheck. Jika ingin hanya path dan
anak-anaknya, pakai trailing slash (/api/health/) dan tambahkan path persisnya
bila perlu.
Contoh lengkap untuk produksi
Section titled “Contoh lengkap untuk produksi”<?php
namespace Config;
class Shield extends \Ganadev\Shield\Codeigniter\Config\Shield{ public string $mode = 'observe'; // naikkan ke 'enforce' setelah yakin public string $appId = 'toko-online-saya'; public string $failMode = 'open'; public array $sensitivePaths = ['/login', '/admin/login', '/api/auth']; public string $botMode = 'observe'; public array $skipPaths = ['/api/webhooks/github']; public array $apiPaths = ['/api']; public string $adminAuthorize = 'admin.authorize'; public int $retentionDays = 14;}Setelah mengubah konfigurasi, pastikan benar-benar terpakai dengan:
php spark shield:rules:listphp spark shield:healthPowered by PT Ganadev Multi Solusi