Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!
[NODE JS] Rate Limiting ile Brute Force Koruması
Merhaba, bu konuda rate limiting yani istek sınırlama konusunu ele alacağız. Brute force saldırıları, DDoS girişimleri ve API suistimallerine karşı en temel savunma mekanizmalarından biri. Bir IP adresinden veya kullanıcıdan belirli sürede kaç istek gelebileceğini sınırlıyoruz.
Rate limiting olmadan ne olur? Saldırgan giriş formunuza saniyede yüzlerce deneme yaparak şifre kırmaya çalışabilir. API'nize dakikada binlerce istek atarak sunucunuzu çökertebilir. Veya bir bot tüm ürün bilgilerinizi dakikalar içinde scrape edebilir. Bunların hepsini rate limiting ile engelleyebilirsiniz.
Ben her projemde en az iki katmanlı rate limiting uygularım: genel bir sınır tüm endpoint'ler için, ve hassas endpoint'ler için daha sıkı bir sınır. Login, register, şifre sıfırlama gibi endpoint'lere çok daha düşük limitler koyarım çünkü bunlar brute force'un hedefidir.
Express için express-rate-limit paketi standart çözüm. Basit uygulamalar için yeterli. Ama büyük ölçekli uygulamalarda Redis tabanlı rate limiting kullanmanız gerekir, çünkü birden fazla sunucu instance'ı varsa her biri kendi belleğindeki sayaçları tutar ve toplam limit aşılabilir.
Express Rate Limit Kullanımı
JavaScript:
const express = require('express');
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');
const app = express();
app.use(express.json());
// Genel rate limiter - tum endpointler icin
const genelLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 dakika
max: 100, // 15 dakikada max 100 istek
standardHeaders: true, // RateLimit-* headerlari ekle
legacyHeaders: false,
message: {
hata: 'Cok fazla istek gonderdiniz. Lutfen 15 dakika sonra tekrar deneyin.',
limitResetSuresi: '15 dakika'
},
keyGenerator: (req) => {
// IP bazli sinirla (proxy arkasindaysa X-Forwarded-For kullan)
return req.ip || req.headers['x-forwarded-for'] || 'unknown';
},
skip: (req) => {
// Healthcheck endpointi limitten muaf
return req.path === '/health';
}
});
app.use(genelLimiter);
// Login icin siki limiter
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 dakika
max: 5, // 15 dakikada max 5 giris denemesi
message: {
hata: 'Cok fazla giris denemesi. 15 dakika sonra tekrar deneyin.',
kalanDeneme: 0
},
keyGenerator: (req) => {
// Hem IP hem kullanici adi bazli
return req.ip + ':' + (req.body.email || 'unknown');
}
});
// API icin ayri limiter
const apiLimiter = rateLimit({
windowMs: 60 * 1000, // 1 dakika
max: 30, // Dakikada 30 istek
message: { hata: 'API istek limiti asildi.' }
});
// Route'lara uygula
app.post('/api/giris', loginLimiter, (req, res) => {
// Giris islemi
res.json({ basarili: true });
});
app.use('/api/', apiLimiter);
// Redis tabanli rate limiting (coklu sunucu icin)
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: 6379
});
const redisLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
store: new RedisStore({
sendCommand: (...args) => redis.call(...args)
})
});
// Kendi rate limiter middleware'imiz (Redis ile)
async function ozelRateLimiter(limit, pencereSaniye) {
return async (req, res, next) => {
const anahtar = 'rl:' + req.ip + ':' + req.path;
const multi = redis.multi();
multi.incr(anahtar);
multi.expire(anahtar, pencereSaniye);
const sonuclar = await multi.exec();
const istekSayisi = sonuclar[0][1];
res.setHeader('X-RateLimit-Limit', limit);
res.setHeader('X-RateLimit-Remaining', Math.max(0, limit - istekSayisi));
if (istekSayisi > limit) {
return res.status(429).json({
hata: 'Istek limiti asildi',
tekrarDeneme: pencereSaniye + ' saniye sonra'
});
}
next();
};
}
app.listen(3000);
Gelişmiş Stratejiler
Basit rate limiting yeterli olmayabilir. Sliding window algoritması daha adil bir dağılım sağlar, fixed window'daki sınır geçişi sorununu çözer. Token bucket algoritması ise burst traffic'e izin verirken ortalama hızı sınırlar, API'ler için idealdir.
Bir de progressive delay stratejisi var ki ben bunu çok seviyorum. İlk 3 başarısız giriş denemesinde anında cevap verirsiniz, 4. denemede 1 saniye bekletirsiniz, 5. denemede 2 saniye, 6. denemede 4 saniye... Üssel artış ile saldırgan her denemede daha uzun beklemek zorunda kalır. Bu brute force'u pratik olarak imkansız hale getirir.
Ayrıca sadece IP bazlı limit koymak yetmez. Saldırgan proxy arkasından binlerce farklı IP ile gelebilir. Login endpoint'inde hem IP hem kullanıcı adı bazlı limit koyun. Böylece aynı hesaba farklı IP'lerden de sınırlı sayıda deneme yapılabilir.
Production'da rate limit ayarlarınızı çok sıkı tutmayın, gerçek kullanıcıları kızdırırsınız. Özellikle paylaşımlı IP'lerde (ofis, okul) çok kullanıcı aynı IP'den gelir. Bu durumlar için IP + User-Agent kombinasyonu veya authenticated kullanıcılar için daha yüksek limitler düşünün.
Kolay gelsin!
