mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-12-01 06:55:45 +01:00
Compare commits
3 Commits
v1.0.27
...
e5d836d037
| Author | SHA1 | Date | |
|---|---|---|---|
| e5d836d037 | |||
| 99d5105768 | |||
| a8dc11b024 |
@@ -41,12 +41,35 @@ const getClientIP = (req: Request): string => {
|
||||
return remoteAddress;
|
||||
};
|
||||
|
||||
// Helper to check if an IP is a loopback address (IPv4 or IPv6)
|
||||
const isLoopbackAddress = (ip: string): boolean => {
|
||||
// IPv4 loopback: 127.0.0.0/8
|
||||
if (ip.startsWith('127.') || ip === 'localhost') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// IPv6 loopback: ::1
|
||||
// Also handle IPv4-mapped IPv6 addresses like ::ffff:127.0.0.1
|
||||
if (ip === '::1' || ip === '::ffff:127.0.0.1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle full IPv6 loopback notation
|
||||
if (ip.toLowerCase().startsWith('0000:0000:0000:0000:0000:0000:0000:0001') ||
|
||||
ip.toLowerCase() === '0:0:0:0:0:0:0:1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// Helper to check if request should be limited
|
||||
const shouldSkipLimit = (req: Request): boolean => {
|
||||
const skipPaths = [
|
||||
'/api/health',
|
||||
'/api/setup/status',
|
||||
'/api/auth/validate'
|
||||
'/api/auth/validate',
|
||||
'/api/auth/me',
|
||||
];
|
||||
|
||||
// Skip for successful GET requests (data fetching)
|
||||
@@ -54,9 +77,16 @@ const shouldSkipLimit = (req: Request): boolean => {
|
||||
return true;
|
||||
}
|
||||
|
||||
const clientIP = getClientIP(req);
|
||||
|
||||
// Skip for loopback addresses (local development)
|
||||
if (isLoopbackAddress(clientIP)) {
|
||||
console.log(`✅ Loopback address skipped: ${clientIP}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip for whitelisted IPs from environment
|
||||
const whitelist = process.env.RATE_LIMIT_WHITELIST?.split(',') || [];
|
||||
const clientIP = getClientIP(req);
|
||||
if (whitelist.includes(clientIP)) {
|
||||
console.log(`✅ IP whitelisted: ${clientIP}`);
|
||||
return true;
|
||||
@@ -72,8 +102,8 @@ const getRateLimitConfig = () => {
|
||||
return {
|
||||
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || '900000'), // 15 minutes default
|
||||
max: isProduction
|
||||
? parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '1000') // Stricter in production
|
||||
: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '5000'), // More lenient in development
|
||||
? parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '50') // Stricter in production
|
||||
: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'), // More lenient in development
|
||||
|
||||
// Development-specific relaxations
|
||||
skip: (req: Request) => {
|
||||
@@ -112,7 +142,7 @@ export const apiLimiter = rateLimit({
|
||||
// Strict limiter for auth endpoints
|
||||
export const authLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: parseInt(process.env.AUTH_RATE_LIMIT_MAX_REQUESTS || '100'),
|
||||
max: parseInt(process.env.AUTH_RATE_LIMIT_MAX_REQUESTS || '50'),
|
||||
message: {
|
||||
error: 'Zu viele Login-Versuche, bitte versuchen Sie es später erneut'
|
||||
},
|
||||
@@ -135,7 +165,7 @@ export const authLimiter = rateLimit({
|
||||
// Separate limiter for expensive endpoints
|
||||
export const expensiveEndpointLimiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000,
|
||||
max: parseInt(process.env.EXPENSIVE_ENDPOINT_LIMIT || '100'),
|
||||
max: parseInt(process.env.EXPENSIVE_ENDPOINT_LIMIT || '20'),
|
||||
message: {
|
||||
error: 'Zu viele Anfragen für diese Ressource'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user