Nginx限流漏桶令牌桶算法,网站防CC原理
网站被CC攻击时,服务器CPU飙升、正常用户打不开页面。
Nginx自带的限流模块能缓解这类问题,核心依赖漏桶和令牌桶两种算法。
下面从原理讲到配置,零基础也能跟着做。
先搞懂漏桶和令牌桶到底在限制什么
漏桶算法把请求当成水,桶底有个固定大小的洞,水只能匀速漏出。
请求进来先灌进桶里,桶满了就丢弃。它的特点是强制匀速处理,能平滑突发流量,但无法应对短时高并发。
对应Nginx的limit_req模块,默认就是漏桶行为。
令牌桶算法则相反,系统按固定速率往桶里放令牌,请求只有拿到令牌才能被处理。
桶里可以存一定数量的令牌,所以允许短时突发。
Nginx的limit_req配合burst参数,本质是在漏桶基础上增加了令牌桶的缓冲能力。
简单判断:如果你的接口必须严格限速,比如短信发送,用漏桶思路;
如果允许偶尔突发,比如网页静态资源,用令牌桶思路更合适。
防CC攻击时Nginx限流怎么生效
CC攻击的特点是模拟正常用户高频请求动态页面,比如搜索、登录接口。
这类请求单看IP可能不多,但总量很大。
Nginx的限流模块按key来统计,通常用$binary_remote_addr(客户端IP)作为key。每个IP对应一个漏桶,超出速率的请求直接返回503。
这样单个IP无法压垮后端,正常用户不受影响。
需要注意,如果攻击者用代理IP池,单IP限流效果会打折扣。
这时可以叠加limit_conn限制并发连接数,或者配合WAF使用。
配置limit_req限流的完整步骤
以下操作在Nginx配置文件nginx.conf或站点配置文件中进行,修改后需重载Nginx。
- 在
http块中定义限流区域,命令如下:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
}
zone=one:10m表示用10MB内存存储IP状态,大约能存16万个IP。rate=10r/s表示每个IP每秒允许10个请求。
- 在
server或location块中引用限流区域:
location /api/ {
limit_req zone=one burst=20 nodelay;
proxy_pass http://backend;
}
burst=20表示允许超过速率的请求排队,最多20个。nodelay表示排队的请求立即处理,不延迟。
如果不加nodelay,超出速率的请求会被延迟到下一个时间窗口处理。
- 保存配置后执行重载:
nginx -t && nginx -s reload
nginx -t先检查语法,通过后再重载。
如果报错,根据提示行号修改。
参数调优和常见报错处理
rate值设太小:正常用户也会被限,表现为间歇性503。
建议先观察访问日志,统计单IP正常请求频率,再留出2-3倍余量。
burst设太大:攻击者可以堆积大量请求占用内存。
一般建议burst不超过rate的2-3倍,例如rate=10r/s时burst设20-30。
忘记加nodelay:排队请求会被延迟处理,用户感觉页面变慢。
对实时性要求高的接口,建议加nodelay。
如果重载后报limit_req_zone directive is not allowed here,说明配置写在了server块里,需要移到http块。
验证限流是否生效
用ab或curl模拟高频请求:
for i in $(seq 1 50); do curl -s -o /dev/null -w "%{http_code}\n" http://你的域名/api/; done
如果配置正确,50次请求中会出现部分503。
同时查看Nginx错误日志:
tail -f /var/log/nginx/error.log
看到limiting requests字样说明限流已触发。注意:验证时不要在生产环境用大流量压测,避免影响正常用户。
两个容易踩的坑
坑一:只限流不记录日志。
默认限流日志在error.log中,建议单独配置limit_req_log_level,方便排查误伤。
坑二:忽略白名单。
公司办公IP或监控IP可能被误限,可以在limit_req_zone前用geo模块或map做白名单跳过。
常见疑问
限流能完全防住CC吗? 不能。
单IP限流对代理池攻击效果有限,建议配合防火墙或CDN的流量清洗。
漏桶和令牌桶在Nginx里能同时用吗? 可以,limit_req本身是漏桶,burst参数引入了令牌桶的缓冲思想,实际是组合效果。
rate=10r/s是每秒10个请求吗? 是的,但Nginx按毫秒精度计算,实际是每100毫秒放行1个请求。
修改配置后需要重启Nginx吗? 用nginx -s reload重载即可,不断开现有连接。
如果按步骤配置后仍然被攻击打满,建议检查后端是否还有未限流的入口,比如直接暴露的IP和端口。
限流是缓解手段,不是万能药,结合日志分析和流量监控才能持续优化。