当 WAF 遇上黑客——一次混合式攻击的应急复盘
背景:上周,我负责维护的一个中型电商站点在凌晨遭遇了异常流量,特征是典型的“慢速层七 + UDP 洪水”混合打法。复盘时发现,单纯堆高防 IP 并不能完全解决问题,只有把流量在边缘节点就“按特征切片”,再交给后端动态清洗,才能把业务抖动压到最低。下文把当时落地的三段代码贴出来,均已脱敏,可直接套用到 Nginx/OpenResty 1.25+ 环境。
1. 流量标记得越早越好
思路:在边缘把每个请求先打个标签,后续模块按标签做差异化限速或转发。OpenResty 的 rewrite_by_lua_block
是最廉价的注入点。
-- /etc/nginx/lua/tag_request.lua
local ip = ngx.var.remote_addr
local ua = ngx.var.http_user_agent or ""
local uri = ngx.var.uri-- 1. 识别慢速层七特征:超长的 UA 或故意拖慢上传
local is_slow = #ua > 512 or (ngx.var.content_length or 0) > 10 * 1024 * 1024-- 2. 识别 UDP 放大回源试探:URI 里带大写“AMP”关键字
local is_amp = uri:upper():match("AMP")-- 3. 打标签到请求头,后续阶段用
if is_slow or is_amp thenngx.req.set_header("X-TAG", "suspicious")
end
2. 边缘限速 + 动态回源
思路:普通流量直接透传,可疑流量先走一个 2 秒的令牌桶,超出的部分转发到“弹性清洗集群”(本质上就是某家云厂商的 AI 云防护),清洗完再回源。
# nginx.conf
lua_shared_dict token_bucket 10m;server {listen 80;server_name shop.example.com;access_by_lua_block {local tag = ngx.req.get_headers()["X-TAG"]if tag == "suspicious" thenlocal limit = require "resty.limit.req"local lim, err = limit.new("token_bucket", 50, 50) -- 50 req/s burst 50if not lim thenngx.log(ngx.ERR, "failed to init limiter: ", err)return ngx.exit(500)endlocal delay, err = lim:incoming(ngx.var.binary_remote_addr, true)if not delay thenif err == "rejected" then-- 超过阈值 → 流量转向弹性清洗return ngx.exec("@scrub")endngx.log(ngx.ERR, "limiter error: ", err)return ngx.exit(500)endif delay > 0 thenngx.sleep(delay)endend}location @scrub {internal;proxy_pass http://ai-edge.scrub.example.net; # 清洗节点proxy_set_header Host shop.example.com;}location / {proxy_pass http://backend;}
}
3. 清洗结果二次校验
清洗集群回源时会加一个签名头 X-Scrub-Sig
,业务层用共享密钥做一次轻量校验,防止攻击者伪造回源。
# backend/app.py
import hmac, hashlib, osSECRET = os.getenv("SCRUB_SECRET")def verify_scrub():sig = request.headers.get("X-Scrub-Sig")if not sig:return Falsemac = hmac.new(SECRET.encode(), request.data, hashlib.sha256).hexdigest()return hmac.compare_digest(sig, mac)@app.before_request
def gate():if request.headers.get("X-TAG") and not verify_scrub():abort(403)
小结
这次攻击之所以能在一小时内被压住,核心是把“标记-限速-清洗”三步拆到不同的网络位置,而不是指望单一的高防 IP 扛所有流量。边缘节点只负责“快思考”,真正的“慢思考”留给 AI 云防护;业务层再补最后一道签名校验,防止回源链路被绕过。上线两周后,CPU 峰值从 92% 降到 38%,羊毛党的注册接口失败率也降了两个数量级。