Pendahuluan: Mengapa Rate Limit Adaptif Diperlukan
Untuk endpoint login dan upload, serangan seperti brute force, credential stuffing, dan upload brute memanfaatkan volume permintaan berbahaya. Rate limit adaptif membantu menjaga endpoint tetap responsif terhadap pengguna sah sambil menekan serangan otomatis dengan menyesuaikan batas berdasarkan keadaan autentikasi, header klien, dan ukuran payload. Dalam paragraf ini, solusi langsung mencakup analisis ancaman, middleware rate limiter, konfigurasi cache, serta fallback dan pemantauan.
Analisis Ancaman Pada Login dan Upload
Brute force login mencoba kombinasi password tanpa batas; credential stuffing menggunakan daftar kredensial bocor dengan kecepatan tinggi; upload brute mengirim file berulang untuk mengeksploitasi fitur upload. Rate limit adaptif harus mempertimbangkan konteks tambahan seperti apakah sesi pengguna sudah terautentikasi, header X-Forwarded-For atau fingerprint, serta payload size karena file besar memerlukan perlindungan lebih ketat.
Tanpa mekanisme adaptif, pembatasan per IP statis mudah terhindari melalui rotasi IP atau proxy. Dengan mempertimbangkan session/auth state, kita bisa menaikkan ambang untuk pengguna terautentikasi dan menurunkannya untuk permintaan anonim yang mencurigakan.
Middleware Rate Limiter yang Mempertimbangkan Konteks
Konsep Dasar
Membuat middleware yang menggabungkan rate limit per minggu memerlukan data input: IP, user-id (jika ada), upload token, header client (User-Agent, X-Client-Id), dan payload size. Middleware menghitung nilai penyesuaian dan menyimpan counters di cache (misalnya Redis).
Contoh Middleware CodeIgniter 4
namespace Appilters;
use CodeIgniteriltersilterInterface;
use CodeIgniter
est
esourceController;
use CodeIgniteriltersilterArguments;
use CodeIgniteriltersilterReturn;
use CodeIgniteriltersilterResult;
use CodeIgniteriltersilterServices;
class AdaptiveRateLimit implements FilterInterface
{
protected $redis;
public function __construct()
{
$this->redis = \\Config\\Cache::getHandler();
}
public function before(RequestInterface $request, $arguments = null)
{
$ip = $request->getIPAddress();
$userId = service('auth')->check() ? service('auth')->user()->id : null;
$token = $request->getHeaderLine('X-Upload-Token');
$size = strlen($request->getBody());
$key = $this->buildKey($ip, $userId, $token);
$limit = $this->calculateLimit($userId, $size, $arguments);
$count = $this->redis->increment($key);
$this->redis->setTimeout($key, 60);
if ($count > $limit) {
return Services::response()
->setStatusCode(429)
->setJSON([
'status' => 'error',
'message' => 'Too many requests. Coba lagi nanti.',
'retry_after' => 60
]);
}
return null;
}
protected function buildKey($ip, $userId, $token)
{
$parts = [$ip];
if ($userId) $parts[] = 'user:' . $userId;
if ($token) $parts[] = 'token:' . $token;
return implode('|', $parts);
}
protected function calculateLimit($userId, $size, $arguments)
{
$base = $arguments['base'] ?? 30;
if ($userId) {
$base *= 2;
}
if ($size > 1024 * 512) {
$base = max(10, $base / 2);
}
return $base;
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// optional: log sukses untuk metrik
}
}
Middleware ini menyesuaikan limit berdasarkan status autentikasi dan payload size. Fungsi calculateLimit bisa diperluas untuk membaca header X-Client-Strength atau menambahkan penalty khusus.
Konfigurasi Rate Limit Per IP, Per User-ID, dan Per Upload Token
Pengaturan rate limit harus eksplisit: per IP menjaga serangan terdistribusi tetap rendah, per user-id memberikan kontrol granular bagi autentikasi, sementara per upload token relevan untuk API publik yang memberikan token sementara.
Contoh konfigurasi di App/Config/Filters.php:
public $aliases = [
'adaptiveLimit' => \App\Filters\AdaptiveRateLimit::class,
];
public $methods = [];
public $filters = [
'adaptiveLimit' => [
'before' => [
'auth/login' => ['base' => 20],
'upload/*' => ['base' => 10]
]
]
];
Dengan pengaturan di atas, middleware dikenakan sebelum route login dan upload, dan limit bisa disesuaikan melalui parameter base.
Memanfaatkan Cache Redis dan Fallback
Penyimpanan Counter di Redis
Redis cocok karena mendukung increment dan expire atomik. Pastikan handler cache di CodeIgniter 4 diset ke Redis di App/Config/Cache.php:
public $handler = 'redis';
public $backupHandler = 'file';
public $redis = [
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'database' => 0,
];
Untuk fallback, saat limiter memblokir permintaan, kirim respons JSON dengan Retry-After dan catat di log agar tim ops dapat memantau false positive. Contoh respons fallback sudah ada di middleware.
Jika cache Redis gagal (timeout atau down), jangan langsung membuka semesta; gunakan backup handler atau turbose fallback yang memberikan limit lebih ketat secara lokal.
Monitoring Metrik dan Praktik Operasional
Pantau metrik rate limit melalui:
- Counter Redis: buat key tambahan
limiter:blockedyang diincrement setiap limit tersentuh. - Log Akses: catat IP dan endpoint untuk permintaan diblokir supaya bisa dihubungkan ke SIEM.
- Grafana/Prometheus: gunakan exporter yang menghitung rata-rata permintaan per menit vs batas.
Praktik ops mencakup reset limiter saat maintenance (clear key Redis), mendistribusikan token upload baru setelah kuota reset, dan membuat alert bila blok meningkat drastis — menandakan serangan baru.
Penutup
Rate limit adaptif di CodeIgniter 4 menggabungkan konteks pengguna, header client, dan ukuran payload untuk melindungi endpoint login serta upload. Dengan middleware yang memanfaatkan Redis, konfigurasi granular, dan monitoring operasional, Anda mendapatkan perlindungan yang responsif sekaligus tetap dapat dioperasikan. Jangan lupa menguji fallback cache dan memperbarui ambang saat pola traffic berubah.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!