Keamanan API: Implementasi Rate Limiting di Go Fiber
Sebagai backend engineer, salah satu aspek yang paling sering dilupakan adalah Rate Limiting. Fokus sering tertuju pada fitur, performa, atau skalabilitas, sementara lapisan proteksi dasar seperti ini justru diabaikan.
Padahal tanpa batasan yang jelas, API sangat rentan terhadap:
- Brute Force attack
- Credential stuffing
- Bot scraping
- Distributed Denial of Service (DoS)
Tanpa mekanisme kontrol, satu endpoint sederhana bisa menjadi bottleneck yang menjatuhkan seluruh sistem.
Apa Itu Rate Limiting?
Rate Limiting adalah teknik untuk membatasi jumlah request yang dapat dilakukan oleh client dalam periode waktu tertentu.
Contoh sederhana:
- Maksimal 20 request per menit per IP
- Maksimal 5 login attempt per 10 menit
- Maksimal 100 request per API key per jam
Dengan aturan ini, sistem dapat tetap stabil meskipun ada lonjakan traffic atau aktivitas mencurigakan.
Mengapa Rate Limiting Penting?
1. Mencegah Abuse
Tanpa pembatasan, satu pengguna atau bot bisa menghabiskan seluruh resource server. Rate limiting memastikan distribusi resource tetap adil.
2. Meningkatkan Keamanan
Serangan seperti brute force sangat bergantung pada jumlah percobaan. Dengan membatasi request, probabilitas keberhasilan serangan turun drastis.
3. Cost Efficiency
Pada infrastruktur berbasis cloud (AWS, GCP, dll), setiap request bisa berarti biaya. Rate limiting membantu mengontrol pengeluaran.
4. Stabilitas Sistem
Lonjakan traffic mendadak (traffic spike) dapat menyebabkan downtime. Rate limiter bertindak sebagai lapisan proteksi pertama.
Strategi Rate Limiting
Tidak semua rate limiting itu sama. Beberapa pendekatan yang umum digunakan:
1. Fixed Window
- Menghitung request dalam interval waktu tetap
- Contoh: 100 request per menit
- Kekurangan: bisa terjadi burst di akhir window
2. Sliding Window
- Lebih presisi karena menghitung berdasarkan waktu aktual request
- Lebih kompleks, tapi lebih adil
3. Token Bucket
- Setiap request mengonsumsi token
- Token diisi ulang secara berkala
- Fleksibel untuk mengakomodasi burst traffic
4. Leaky Bucket
- Request diproses dengan rate konstan
- Cocok untuk menjaga kestabilan throughput
Fiber secara default menggunakan pendekatan sederhana yang cukup untuk sebagian besar use case.
Implementasi di Fiber v3
Fiber menyediakan middleware limiter yang ringan dan mudah digunakan. Cocok untuk aplikasi skala kecil hingga menengah tanpa perlu dependency tambahan.
Contoh Kode Middleware
package main
import (
"time"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/limiter"
)
func main() {
app := fiber.New()
// Global Rate Limiter
app.Use(limiter.New(limiter.Config{
Max: 20, // Maksimal 20 request
Expiration: 1 * time.Minute, // Dalam 1 menit
LimitReached: func(c fiber.Ctx) error {
return c.Status(429).JSON(fiber.Map{
"message": "Terlalu banyak permintaan, coba lagi nanti.",
})
},
}))
app.Get("/api/data", func(c fiber.Ctx) error {
return c.SendString("Data berhasil diambil!")
})
app.Listen(":3000")
}
Penjelasan Konfigurasi
- Max: jumlah maksimal request dalam periode tertentu
- Expiration: durasi window
- LimitReached: handler ketika limit tercapai (biasanya HTTP 429)
HTTP status 429 Too Many Requests adalah standar untuk kondisi ini.
Rate Limiting Berdasarkan IP vs API Key
Berdasarkan IP
Default behavior limiter menggunakan IP address:
- Mudah diterapkan
- Cocok untuk public API
Kekurangan:
- Tidak akurat jika user di balik NAT / proxy
- Bisa diakali dengan IP rotation
Berdasarkan API Key / User ID
Lebih presisi:
KeyGenerator: func(c fiber.Ctx) string {
return c.Get("X-API-Key")
},
Keuntungan:
- Setiap user punya limit sendiri
- Lebih adil dan aman
Menggunakan Storage Eksternal (Redis)
Limiter default menggunakan memory lokal. Masalahnya:
- Tidak sinkron antar instance (horizontal scaling)
- Data hilang saat restart
Solusinya: gunakan Redis
Contoh konsep:
Storage: redisStorage
Dengan Redis:
- Rate limit konsisten di semua instance
- Cocok untuk sistem distributed
Best Practice dalam Implementasi
1. Gunakan Layered Limiting
Jangan hanya satu limiter global:
- Global limiter
- Per endpoint limiter
- Per user limiter
2. Bedakan Endpoint Sensitif
Contoh:
/login→ limit ketat (5 request / menit)/public-data→ limit longgar
3. Berikan Header Informasi
Tambahkan response header:
X-RateLimit-LimitX-RateLimit-RemainingRetry-After
Ini membantu client menyesuaikan behavior.
4. Logging dan Monitoring
Pantau:
- IP yang sering kena limit
- Endpoint yang paling sering diakses
Data ini bisa digunakan untuk deteksi anomali.
Kesalahan Umum
Beberapa kesalahan yang sering terjadi:
- Limit terlalu longgar → tidak efektif
- Limit terlalu ketat → merusak UX
- Tidak mempertimbangkan burst traffic
- Tidak menggunakan distributed storage di sistem scale besar
Kapan Rate Limiting Tidak Cukup?
Rate limiting bukan silver bullet. Untuk sistem serius, perlu kombinasi dengan:
- WAF (Web Application Firewall)
- CAPTCHA pada endpoint sensitif
- Authentication & authorization
- IP reputation filtering
Kesimpulan
Rate limiting adalah komponen fundamental dalam desain API modern. Implementasinya sederhana, tetapi dampaknya sangat besar terhadap:
- Keamanan
- Stabilitas
- Efisiensi biaya
Fiber memberikan cara cepat untuk mengimplementasikannya, namun untuk sistem skala besar, pendekatan harus diperluas dengan storage terdistribusi dan strategi yang lebih adaptif.
Jika API Anda sudah live tanpa rate limiting, itu bukan sekadar kekurangan—itu celah yang siap dieksploitasi.