node-ip-rate-limiter
v1.0.5
Published
Adaptive IP rate limiter with hierarchical pattern tracking (p2/p3 patterns) for in-memory rate limiting
Maintainers
Readme
node-ip-rate-limiter
An adaptive IP rate limiter with hierarchical pattern tracking (p2/p3 patterns) for in-memory rate limiting. This package automatically detects patterns in IP addresses and applies rate limiting at different levels (single IP, /24 subnet, /16 network).
Features
- Adaptive Rate Limiting: Automatically detects and groups IPs by patterns
- Hierarchical Pattern Tracking:
- Single IP: Individual IP address tracking
- P3 Pattern (/24 subnet): Groups IPs sharing the first 3 octets (e.g.,
72.145.152.*) - P2 Pattern (/16 network): Groups IPs sharing the first 2 octets (e.g.,
72.145.*.*)
- Pattern Count Tracking: Increments counts for both p3 and p2 patterns independently
- Automatic Promotion: IPs are automatically promoted to higher levels when patterns are detected
- In-Memory Storage: Fast, efficient in-memory storage with automatic expiration
- Zero Dependencies: No external dependencies required
Installation
npm install node-ip-rate-limiterQuick Start
const { initRateLimiter, ipRateLimiting } = require('node-ip-rate-limiter');
// Initialize the rate limiter
initRateLimiter({
moduleName: 'my-api',
single: {
maxCount: 10, // Max requests per IP
expiryTime: 60000 // 60 seconds in milliseconds
},
p3Series: {
maxCount: 50, // Max requests per /24 subnet
expiryTime: 60000 // 60 seconds
},
p2Series: {
maxCount: 100, // Max requests per /16 network
expiryTime: 60000 // 60 seconds
}
});
// Check an IP address
const result = ipRateLimiting('72.145.152.42');
if (result.isDuplicate) {
console.log('Rate limit exceeded!');
console.log(result.reason);
} else {
console.log('Request allowed');
console.log(`Current level: ${result.level}`);
console.log(`Count: ${result.count}`);
}How It Works
Pattern Detection
The rate limiter tracks IP addresses at three levels:
- Single IP (
72.145.152.42): Individual IP tracking - P3 Pattern (
72.145.152.*): First 3 octets - /24 subnet - P2 Pattern (
72.145.*.*): First 2 octets - /16 network
Pattern Count Tracking
When an IP is processed:
- The p3 count (first 3 octets) is incremented
- The p2 count (first 2 octets) is incremented
- Different p3 patterns under the same p2 are tracked separately
Example:
IP: 72.145.152.42
→ p3 pattern: 72.145.152 (count = 1)
→ p2 pattern: 72.145 (count = 1)
IP: 72.145.83.96
→ p3 pattern: 72.145.83 (count = 1) [new p3 pattern]
→ p2 pattern: 72.145 (count = 2) [incremented]
IP: 72.145.83.98
→ p3 pattern: 72.145.83 (count = 2) [incremented]
→ p2 pattern: 72.145 (count = 3) [incremented]Automatic Promotion
IPs are automatically promoted to higher rate limiting levels when patterns are detected:
- Single → P3: When 2+ IPs share the same /24 subnet
- Single → P2: When 2+ IPs share the same /16 network
- P3 → P2: When multiple /24 subnets are detected in the same /16 network
Once promoted, IPs stay at that level or higher (no demotion).
API Reference
initRateLimiter(config)
Initializes the rate limiter with configuration.
Parameters:
config(Object): Configuration objectmoduleName(string): Unique name for this rate limiter instancesingle(Object): Configuration for single IP rate limitingmaxCount(number): Maximum number of requests allowedexpiryTime(number): Time in milliseconds before the limit resets
p3Series(Object): Configuration for /24 subnet rate limitingmaxCount(number): Maximum number of requests allowed per subnetexpiryTime(number): Time in milliseconds before the limit resets
p2Series(Object): Configuration for /16 network rate limitingmaxCount(number): Maximum number of requests allowed per networkexpiryTime(number): Time in milliseconds before the limit resets
Example:
initRateLimiter({
moduleName: 'api-server',
single: { maxCount: 100, expiryTime: 60000 },
p3Series: { maxCount: 500, expiryTime: 60000 },
p2Series: { maxCount: 1000, expiryTime: 60000 }
});ipRateLimiting(ip)
Checks if an IP address should be rate limited.
Parameters:
ip(string): IPv4 address (e.g.,"192.168.1.1")
Returns:
Object: Rate limiting resultisDuplicate(boolean):trueif rate limit exceeded,falseotherwiselevel(string): Current rate limiting level ("single","p3", or"p2")reason(string): Human-readable explanation of the resultcount(number): Current count at the current level
Example:
const result = ipRateLimiting('192.168.1.100');
// {
// isDuplicate: false,
// level: 'single',
// reason: 'Request allowed under the per-IP rate limit...',
// count: 1
// }Usage Examples
Express.js Middleware
const express = require('express');
const { initRateLimiter, ipRateLimiting } = require('node-ip-rate-limiter');
const app = express();
// Initialize rate limiter
initRateLimiter({
moduleName: 'express-api',
single: { maxCount: 100, expiryTime: 60000 },
p3Series: { maxCount: 500, expiryTime: 60000 },
p2Series: { maxCount: 1000, expiryTime: 60000 }
});
// Rate limiting middleware
function rateLimitMiddleware(req, res, next) {
const clientIP = req.ip || req.connection.remoteAddress;
const result = ipRateLimiting(clientIP);
if (result.isDuplicate) {
return res.status(429).json({
error: 'Rate limit exceeded',
reason: result.reason,
retryAfter: 60
});
}
// Add rate limit headers
res.setHeader('X-RateLimit-Level', result.level);
res.setHeader('X-RateLimit-Count', result.count);
next();
}
app.use(rateLimitMiddleware);
app.get('/api/data', (req, res) => {
res.json({ message: 'Success' });
});
app.listen(3000);Batch Processing
const { initRateLimiter, ipRateLimiting } = require('node-ip-rate-limiter');
const fs = require('fs');
// Initialize
initRateLimiter({
moduleName: 'batch-processor',
single: { maxCount: 10, expiryTime: 60000 },
p3Series: { maxCount: 50, expiryTime: 60000 },
p2Series: { maxCount: 100, expiryTime: 60000 }
});
// Process IPs from file
const ips = JSON.parse(fs.readFileSync('ip_addresses.json', 'utf8'));
const results = [];
for (const ip of ips) {
const result = ipRateLimiting(ip);
results.push({ ip, ...result });
if (result.isDuplicate) {
console.log(`Blocked: ${ip} - ${result.reason}`);
}
}
console.log(`Processed ${results.length} IPs`);Response Examples
Single IP (First Request)
{
isDuplicate: false,
level: 'single',
reason: 'Request allowed under the per-IP rate limit. The client is currently treated as a single IP.',
count: 1
}P3 Pattern Detected
{
isDuplicate: false,
level: 'p3',
reason: 'Request allowed under the /24 subnet rate limit. Multiple IPs were detected in the same subnet and are sharing a common quota.',
count: 2
}P2 Pattern Detected
{
isDuplicate: false,
level: 'p2',
reason: 'Request allowed under the /16 network rate limit. Traffic from a wider network is being grouped and rate-limited together.',
count: 3
}Rate Limit Exceeded
{
isDuplicate: true,
level: 'p3',
reason: 'Request blocked because the /24 subnet rate limit has been exceeded. Multiple IPs from the same subnet are sharing this quota.',
count: 6
}Important Notes
- In-Memory Only: This package uses in-memory storage. Data is lost on process restart.
- Single Process: Designed for single-process applications. For multi-process setups, consider using Redis or a shared storage solution.
- Automatic Cleanup: Expired entries are automatically cleaned up every 10 minutes.
- IPv4 Only: Currently supports IPv4 addresses only.
License
ISC
Author
Mirabel Technologies
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues, questions, or contributions, please visit the npm package page.
