在服务器上设置访问限制,主要有以下几种常见方式:
1. Nginx 限流配置
http { # 定义限流区域 limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; server { location /api/ { # 应用限流,burst=5 允许突发5个请求 limit_req zone=api burst=5 nodelay; proxy_pass http://backend; } } }
http { limit_conn_zone $binary_remote_addr zone=conn:10m; server { location /download/ { limit_conn conn 5; # 每个IP最多5个并发连接 } } }
2. Apache 限流配置
<IfModule mod_security.c> SecRuleEngine On # 限制每分钟最多60次请求 SecRule REQUEST_URI "@streq /api" "phase:1,deny,status:429,\ setvar:ip.requests=+1,expirevar:ip.requests=60" </IfModule>
3. 应用层限流(以 Node.js 为例)
使用 express-rate-limit
const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 限制每个IP在15分钟内最多100次请求 message: '请求过于频繁,请稍后再试' }); app.use(limiter);
const rateLimitMap = new Map(); function rateLimitMiddleware(req, res, next) { const ip = req.ip; const now = Date.now(); const windowMs = 60000; // 1分钟 const maxRequests = 60; // 最多60次请求 if (!rateLimitMap.has(ip)) { rateLimitMap.set(ip, { count: 1, startTime: now }); } else { const data = rateLimitMap.get(ip); if (now - data.startTime > windowMs) { // 重置时间窗口 data.count = 1; data.startTime = now; } else { data.count++; if (data.count > maxRequests) { return res.status(429).json({ error: '请求过于频繁,请稍后再试' }); } } } next(); } app.use(rateLimitMiddleware);
4. 使用 Redis 实现分布式限流
const redis = require('redis');
const client = redis.createClient();
async function redisRateLimit(ip, maxRequests, windowMs) {
const key =rate_limit:${ip}
;
const current = await client.incr(key);
if (current === 1) {
await client.expire(key, windowMs / 1000);
}
if (current > maxRequests) {
return false; // 超过限制
}
return true;
}
app.use(async (req, res, next) => {
const allowed = await redisRateLimit(req.ip, 100, 60000);
if (!allowed) {
return res.status(429).json({ error: '请求过于频繁' });
}
next();
});
5. iptables 限制连接数
限制每个IP最多10个并发连接 iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 10 -j REJECT 限制每分钟最多30个新连接 iptables -A INPUT -p tcp --dport 80 -m limit --limit 30/minute -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j DROP
6. 使用 fail2ban 自动封禁
/etc/fail2ban/jail.local [nginx-limit-req] enabled = true filter = nginx-limit-req action = iptables-multiport[name=nginx-limit-req, port="http,https"] logpath = /var/log/nginx/error.log maxretry = 5 findtime = 600 bantime = 3600
最佳实践建议
1、分层限流:在多个层面设置限流(网络层、Web服务器层、应用层)
2、差异化限流:对不同的API端点设置不同的限制
3、合理的限制值:根据业务需求设置合理的限制值
4、返回适当的状态码:使用 429 Too Many Requests
5、添加重试头部:在响应中包含Retry-After
头部
选择哪种方式取决于你的具体需求、服务器架构和技术栈。
文章摘自:https://idc.huochengrm.cn/fwq/17529.html
评论