CC攻击防御实战:利用HAProxy的stick table实现连接频率限制
摘要:# 别让CC攻击拖垮你的网站:用HAProxy这个“老伙计”轻松设卡 前两天,一个做电商的朋友半夜给我打电话,声音都变了:“网站突然卡成PPT,后台一看,全是同一拨IP在疯狂刷商品页,订单量却一动不动。”我一听就明白了——老熟人,CC攻击(Challen…
别让CC攻击拖垮你的网站:用HAProxy这个“老伙计”轻松设卡
前两天,一个做电商的朋友半夜给我打电话,声音都变了:“网站突然卡成PPT,后台一看,全是同一拨IP在疯狂刷商品页,订单量却一动不动。”我一听就明白了——老熟人,CC攻击(Challenge Collapsar)又来“上班”了。
说实话,很多中小公司一遇到CC攻击就慌神,第一反应是“赶紧买高防!”。结果呢?有的高防方案PPT上写得天花乱坠,真被打的时候,误杀率比攻击还让人头疼,正常用户连验证码都刷不出来。其实吧,对于很多业务场景,攻击流量还没到需要“核武器”的地步,你缺的往往是一把精准的“手术刀”。
今天,我就想聊聊HAProxy里一个被严重低估的功能:stick table。它不是什么新玩意儿(HAProxy的老用户可能都见过),但用它来对付CC攻击,尤其是那种低频、慢速、模拟真实的攻击,效果出奇地好——而且,它几乎是免费的。
CC攻击到底在“攻击”什么?
先扯句大实话。很多人觉得CC攻击就是“疯狂发请求”,这没错,但它的阴险之处在于伪装。它不像DDoS那样用流量冲垮你,而是用大量看似合法的HTTP请求(比如疯狂搜索、频繁刷新商品详情、重复提交表单),精准地消耗你的服务器资源(CPU、数据库连接、应用线程)。
你的服务器就像一家热门餐厅。DDoS是派一千个人堵在门口,谁也别进;而CC攻击是派两百个人进去,每人只点一杯白开水,然后坐一整天。你的服务员(应用线程)、厨师(数据库)全被这些“低消费客户”占满了,真正的顾客(用户)反而进不来。
所以,防御的核心不是一刀切拦IP,而是快速识别出哪些是“只喝白开水”的恶意客户。HAProxy的stick table,干的就是这个“记仇小本本”的活儿。
HAProxy的“记仇小本本”:stick table怎么工作?
你可以把stick table想象成前台的一张客户行为记录表。每个进来的客户(IP地址、或会话ID)都对应表里的一行。
HAProxy会实时在这张表里记录:
- 他来了多少次(连接频率)
- 他最近一次来是什么时候(过期时间)
- 他总共“消耗”了多少资源(比如请求字节数)
配置起来,核心就是几行代码(假设你HAProxy基础配置已经OK了):
# 1. 先定义一个“小本本”(stick table)
# 这里我们按源IP(src)来跟踪,记录请求速率(req_rate),10秒为一个计算周期,大小10万条
backend track_backend
stick-table type ip size 100k expire 30s store http_req_rate(10s)
# 2. 在前端(接收流量的地方)告诉HAProxy:开始记!
frontend http-in
bind *:80
# 将客户端源IP写入到track_backend的stick table中
stick-table track-sc1 src table track_backend
# 3. 设定规则:查小本本,如果这个IP过去10秒内请求超过50次,就拒绝他30秒
acl abuse src_http_req_rate(track_backend) gt 50
tcp-request connection reject if abuse
# 正常的转发规则
default_backend your_servers
这就完了? 对,核心逻辑就这么简单。它的精妙之处在于:
- 轻量:只在内存里维护一张表,开销极小。
- 精准:只针对异常IP,不影响其他正常用户。
- 动态:记录会过期(
expire 30s),攻击停了30秒后,IP自动从“黑名单”释放,避免永久封禁误伤。
实战进阶:光限制连接数可能不够
如果你的攻击者更“狡猾”,用一堆代理IP,每个IP只发少量请求,但总数很大怎么办?这时候,我们可以用stick table配合更细的维度,比如跟踪URI或Session ID。
举个栗子,防止对某个登录接口的暴力破解:
frontend http-in
bind *:80
# 关键:我们不仅记IP,还记他请求的特定路径(/api/login)
stick-table track-sc2 src table track_backend
stick-table track-sc3 path table track_backend
# 规则:如果同一个IP对 /api/login 的请求频率过高
acl login_page path_beg /api/login
acl login_abuse sc_http_req_rate(track_backend) gt 5
# 直接返回一个429(Too Many Requests)状态码,优雅拒绝
http-request deny deny_status 429 if login_page login_abuse
看到没?这样即使攻击者换着IP刷你同一个接口,只要频率超了,照样被卡住。这种颗粒度的控制,是很多“傻瓜式”高防产品做不到的。
一些掏心窝子的经验(和坑)
我自己在线上环境折腾过不少,总结几点,你可能会遇到:
- “误杀”问题:阈值(上面例子里的
50和5)怎么设?没有标准答案。你得先看看自己业务的正常流量曲线。一个内容站和一個秒杀接口的常态请求率天差地别。我的建议是:先设一个你觉得绝对安全的宽松值(比如每秒5次),观察几天,再慢慢收紧。灰度调整,永远比一刀切更重要。 - 表大小(
size):size 100k意味着最多记录10万个独立标识(IP或会话)。你得预估一下自己最大并发连接数。设小了,表满了新连接就记不进去;设大了,浪费内存。一般中型网站,10万到100万足矣。 - 别忘了监控:HAProxy的stats页面可以实时查看stick table的使用情况。哪些IP被拦截了、表用了多少,一目了然。这是你调整策略的最佳依据。
- 它不是什么银弹:对于超大流量的、分布式的CC攻击,单靠HAProxy可能力不从心,这时候需要结合高防IP、WAF等做分层防御。但stick table绝对是成本最低、效果最直接的第一道精准防线。
写在最后
技术圈总爱追新概念,但有时候,像HAProxy stick table这样沉淀多年的“老家伙”,用对了地方,比啥都管用。它给你的不是一种被动的“防护”,而是一种主动的“控制感”——你能清晰地定义什么是异常,并亲手把它拦在门外。
下次再遇到网站因为CC攻击变慢,别急着掏钱包。打开你的HAProxy配置,加上几行“记仇”的代码,可能问题就解决了。毕竟,最好的防御,永远是理解攻击,然后用最合适的工具,精准地还击。
行了,不废话了,配置去吧。有坑的话,回来聊聊。

