WAF是什么:云WAF、反向代理与规则引擎选型指南 简介《WAF的实现与架构演进.pptx》面向Web安全初学者及运维、开发人员系统梳理Web应用防火墙的防护对象、产品形态与架构选型。内容从SQL注入、XSS、CSRF、恶意爬虫与CC等七层攻击的识别阻断切入对比硬件WAF、软件WAF与云WAF的部署差异并展开云WAF的流量接入、HTTP(S)反向代理和安全规则引擎三大要点对DNS调度、CNAME接入与Anycast的优劣也有对照说明。后半部分聚焦Nginx/OpenResty扩展、ModSecurity CRS与Naxsi的规则机制并给出action、vars、match等配置要素的拆解便于读者建立从产品选型到规则落地的完整认知。压缩包仅含1个pptx大小约3.93MB结构紧凑、便于按章节浏览。目前已有316人学习适合用作培训提纲、方案汇报或WAF入门复习材料。1. 到底什么是 WAF一封被拦下来的请求长什么样凌晨两点值班的人被一条 WAF 告警叫醒某个查询接口的参数里躺着一串 or 11 --。奇怪的是数据库日志干干净净业务也没出问题——这串东西压根没走到代码里它在门口就被拦下了。拦住它的那个东西就是 WAFWeb Application FirewallWeb 应用防火墙。通俗地说WAF 是站在 Web 应用门口的一道岗它不看服务器开了哪些端口只看每个 HTTP(S) 请求里写了什么。它工作在七层能看懂?id1和?id1的差别。搞懂它的价值在于知道它拦得住什么、拦不住什么才知道该在哪补第二道锁。2. WAF 的三种形态硬件盒子、软件插件和云上的中间人WAF 常被当成某一个产品名其实它是一类能力。同样叫 WAF落地时可以是机房里一台专用的硬件设备、装在 Web 服务器上的一个模块也可以是云上一个你根本没见过的反向代理节点。三种形态的差别不只是“贵不贵”而是“它站在哪里、能对流量做什么、出事时谁背锅”。把这三件事分清楚选型就不会被销售话术带着走。2.1 硬件盒子串行和旁路是两种完全不同的承诺硬件 WAF 是一台独立设备部署在本地网络里接法有两种。串行部署意味着所有进出 Web 服务器的流量都要从它身上过它说放行才放行所以能真正把攻击挡在门外代价是它成了链路的一环设备挂掉、断电、升级卡住业务跟着一起断所以正规做法都要配 bypass硬件直通或软件旁路一旦检测到设备异常就自动把流量短接过去。旁路部署则从交换机的镜像口复制一份流量过来看不干扰原链路永远不会因为自己挂掉而拖垮业务但它只能“看”——所谓阻断通常是发 RST 包拆连接或者联动上游设备封 IP属于事后劝架慢半拍而且加密流量镜像过来是一堆密文看不到内容。这类设备的另一层成本在“人”上。盒子买回来只是开始规则要按业务调误报要一条条放行规则库要定期更新。见过不少机房设备指示灯常年绿灯规则还停在上线那年攻击特征库比业务代码还老。它适合的是自建机房、流量不方便出门、对链路有完全掌控权的场景。2.2 软件形态装在 Web 服务器上的守门员软件 WAF 以模块或进程的形式直接跑在承载业务的服务器上。开源世界里最常被提起的两个名字一个是以规则集为核心的 ModSecurity一个是不依赖规则库、靠学习正常请求来建立基线的 Naxsi商业软件也大多是这条路子挂在 Web 服务器前面或者嵌进去。它的好处很实在不用动 DNS不用改网络拓扑请求已经到本机了看到的就是最原始的那份数据成本低一台机器装完就能用日志留在自己手里排查时不用看别人的脸色。坏处同样实在它吃的是业务机器自己的 CPU 和内存规则写复杂一点QPS 掉一截是常事规则写错影响的是同一台机器上的业务进程一次误配就可能让整站 502最麻烦的是规模化——机器从三台扩到三十台就得一台台装、一台台同步配置漏装一台就是一个没人知道的缺口这种坑踩过的人都懂。它比较适合中小站点、机器数量不多的业务、预算有限又想快速补一层的团队或者作为云 WAF 之外的“最后一米”补充。2.3 云 WAF天生就是反向代理的中间人云 WAF 大多是从 CDN 长出来的先在各地铺缓存节点让用户就近取内容节点上已经有了完整的 HTTP 解析和转发能力再往上加一层规则检查就成了防护。所以它天生是一个反向代理——用户浏览器连的是它它再回源连你的服务器它站在中间看得到每一个请求和每一段响应。接入方式因此特别轻把域名的解析改一下让流量先到它的节点源站一行代码都不用动。节点多、带宽足面对大流量冲击时能分摊掉一部分规则由服务方维护不用自己养一个安全团队顺带还隐藏了源站地址扫描器只能看到边缘 IP。代价也清楚。第一所有请求都经过第三方数据敏感的业务要掂量清楚尤其是带个人信息、带内网标识的接口。第二多一跳就多一份延迟对时延敏感的业务要实测。第三源站 IP 一旦泄露——历史解析记录、邮件头、没做防护的子域名、直连的测试域名——攻击者可以绕过去直连防护等于零所以源站要配白名单只允许边缘节点回源。第四它只管 HTTP(S)其它端口的服务它看不见。第五整条链路出了问题是黑匣子用户说慢你得先证明不是自己慢。2.4 三种形态怎么选一张表看清差别维度硬件盒子软件形态云 WAF部署位置本地机房链路源站服务器上服务方边缘节点能否真正阻断串行可以旁路只能事后可以可以改造量改网络拓扑改服务器环境改 DNS 解析性能开销专用设备容量固定占用源站 CPU不占源站故障影响面大可能断站小单机范围大全站入口典型场景自建机房、链路可控中小站点、机器少公网业务、无专职安全团队选型判断其实可以简化成三个问题业务有没有公网域名、愿不愿意让流量经过第三方、团队有没有人长期维护规则。三个答案都想清楚了形态基本就定了。剩下的细节往往不是“哪种更强”而是“哪种在你手里不会变成摆设”。3. 云 WAF 的三根支柱流量接入、反向代理、规则引擎云 WAF 看起来只是“改个 DNS 就完事”实际上要三样东西同时成立流量得先到得了它那里它得有本事把请求接住再转出去最后才是规则判断这道攻击该不该拦。三根支柱缺一根整个系统就是空的。这一章按顺序把这三件事拆开讲。3.1 流量接入DNS、CNAME 与 Anycast 的三条路正常的访问流程是浏览器把域名交给 DNS拿到一个 IP然后直连过去。要让流量先到 WAF就得在这个解析环节动手。最简单的是把域名的 A 记录直接改成 WAF 节点地址。改起来直接问题在于切换成本——解析生效要等 TTLTTL 设得长回滚就慢攻击来了想把流量切走只能干等缓存过期。更常见的是 CNAME把自己的域名别名指向服务方给的一个域名真正的解析权留在服务方那一侧。这样做的好处是调度权不在你手上节点切换、灰度、回滚都在服务方内部完成你不用等 TTL也不用半夜改解析。云 WAF 普遍要求 CNAME 接入原因就在这里。接入之后是调度。DNS 调度指的是解析时按来源返回不同的节点不同地区的用户就近接入不同线路的用户走对应线路的机房攻击压力大时把一部分流量分到更空闲的机房。它的短板是粒度粗、生效慢受本地 DNS 缓存影响你这边改完了那边可能还在用旧结果。Anycast任播是另一套思路多个机房同时对外宣告同一段地址用户到底落到哪个节点由路由协议决定而不是由 DNS 决定。表现出来也是“就近接入”但解析出来的 IP 本身就是边缘节点没有第二跳。它的好处很硬路由策略调整生效快不用等 DNS 过期对 DNS 解析性能要求低抗干扰单点故障时路由自动收敛流量自己换条路走。坏处同样硬全球路由表错综复杂做 BGP 优化是门手艺要自己持有一整段地址成本高地址利用率低浪费得让人心疼。注意接入方式决定了“出事时能不能快速回滚”。能用 CNAME 就别硬编码 A 记录能留一键回源的开关就别省这一步。3.2 反向代理怎么挑性能、扩展与 ACL 的权衡流量到了节点得有人把它接住、解析、再转发回源站这就是反向代理干的活。WAF 的所有规则判断都挂在反向代理的某个环节上所以代理选谁直接决定了 WAF 能做到多细。Nginx 是最常见的选择。事件驱动的异步模型效率高多核能吃满模块化设计想加功能不用改内核最大的价值是可编程——借助 Lua 扩展能在请求处理的不同阶段插入自己的逻辑规则引擎才有地方落。除此之外它还自带 Web 服务器和缓存能力一个进程把接入、缓存、防护三件事都干了。另一类代理以 ACL 见长原生 ACL 表达能力强能写出很复杂的转发条件纯转发性能略好官方还自带后端健康检查和主动探测。但它的扩展基本靠改配置甚至改代码做不了“按请求内容动态决策”这种活规则要读请求体、要分词、要查外部名单它就吃力了。所以选择的标准不是谁更快而是“你的规则需要多深地介入请求”。只做四层转发和简单路由ACL 型更省心要做内容级判断就得选可编程的那一个。注意多一层代理就多一层坑。真实客户端 IP、Host 头、协议头要正确透传否则 WAF 看到的源 IP 全是代理地址CC 防护和限速直接失效——这种翻车现场一点都不稀奇。3.3 Lua 八个执行阶段WAF 到底挂在哪一步把 Nginx 和 Lua 绑在一起就是 OpenResty 干的事。它在 Nginx 的请求处理流程上开了若干个“钩子”每个钩子对应请求生命周期的一个时刻你可以选择在哪个时刻执行自己的代码。这八个阶段基本就是 WAF 的作战地图。阶段触发时机WAF 通常用来做什么ssl_certificate_by_luaTLS 握手阶段按 SNI 动态选择证书set_by_lua变量初始化预置开关、标记位rewrite_by_lua重写、转发、缓存判断跳转、灰度分流、限速前置access_by_lua请求头已解析、尚未回源主力检查点规则匹配与拦截content_by_lua生成响应内容输出自定义拦截页header_filter_by_lua响应头返回前去掉版本指纹、补安全响应头body_filter_by_lua响应体分块返回时防篡改、防敏感信息外泄log_by_lua请求结束后异步写日志、计数统计# 只示意挂载位置不是完整配置 server { listen 443 ssl; server_name example.com; location / { access_by_lua_block { -- 请求还没回源此时做规则匹配最划算 -- 命中规则直接 ngx.exit(403)后端根本收不到这个请求 local waf require(waf) waf.check_request() } body_filter_by_lua_block { -- 响应体是分块过来的这里检查是否泄露了内部报错或敏感字段 local waf require(waf) waf.check_response() } proxy_pass http://backend; } }access_by_lua_block是请求方向的主战场请求行、请求头、参数、Cookie 都已经解析好请求体还没转发给后端此时判定并拦下代价最小、效果最直接。body_filter_by_lua_block是响应方向的检查点因为响应体是流式分块返回的检查逻辑要能处理“跨块”的情况不能假设一次拿到完整内容。log_by_lua_block则用来做异步统计把命中的规则、来源 IP、请求特征落到日志里事后追查全靠它。3.4 一条请求穿过云 WAF 的完整旅程把三根支柱串起来一条请求的路径是这样的用户在浏览器里输入域名DNS 或 CNAME 把它导向边缘节点节点完成 TLS 握手在access阶段跑一遍规则引擎——先做变量提取和归一化转换再逐条匹配没命中就带着真实的客户端 IP 回源命中就返回拦截页源站处理完把响应发回来响应头和响应体再过一遍过滤最后在log阶段落一条记录。这条链路上任何一环松了结果只有两种要么漏攻击穿过去要么误杀正常用户被拦。所谓“调优”本质上就是在两者之间找那个刚刚好的点。4. 规则引擎的两条路线正则匹配与语义分析谁更靠得住规则引擎是 WAF 的大脑。同样一句1 or 11有的引擎把它当成一串字符去比对黑名单有的引擎把它拆成词法看“这句话想干什么”还有的引擎压根不认识它只是觉得“这个参数从来没见过这么长、这么怪”。三种思路对应三种工程取舍也对应三种不同的翻车方式。4.1 规则验证把已知攻击写成一份清单最经典的做法是规则验证核心是正则匹配。开源世界里最有代表性的是 ModSecurity 引擎配它的核心规则集CRS规则数量在两百多条这个量级覆盖公开的十大 Web 风险类别注入、跨站脚本、文件包含、命令执行、敏感文件访问、恶意扫描等等基本把常见攻击的“长相”都写进去了。这条路线的优点是可控每条规则有编号、有说明、有等级命中了就知道违反了哪一条误杀了就针对这一条放行审计时也拿得出证据。规则可以按业务开关某个接口天生要接收 HTML就把对应的 XSS 规则在该路径上关掉。缺点也很直白它认的是“长相”。攻击者只要把同一句话换个写法——改大小写、插注释、加多余空白、做 URL 编码、十六进制编码、Unicode 变形——正则就可能认不出来了。所以规则引擎里必须有“转换函数”这一步先把请求参数归一化把所有变形还原成同一种形态再去匹配。归一化做得不全绕过就是从这些缝里钻进去的。另一个副作用是误报。规则越多误报越多业务一改版参数格式变了昨天还好好的规则今天就开始拦正常用户。真正的血泪经验是被误报折腾几次之后运维干脆把规则一整片关掉WAF 就这么变成了一个只占资源不干活的摆设。4.2 语义分析不看长相看这句话到底想干什么语义分析换了个思路不猜攻击长什么样而是判断这段输入在语法上像不像攻击。SQL 注入检测通常靠一个专门的词法分析库把参数按 SQL 的规则切成一个个 token再统计 token 的类型分布和位置关系——是不是出现了不该出现的引号、注释符、逻辑运算符组合整体结构是不是像一段被塞进参数里的 SQL 片段。跨站脚本检测同理先把 HTML 实体解码还原再判断是不是构成可执行的标签结构。这条路线的价值在于抗变形。1 or 11、1/**/or/**/11、大小写混写、加一堆空白拆成 token 之后结构高度相似规则没覆盖到的变体也能被认出来。它不需要为每一种 payload 写一条规则维护成本低得多。但它有明确的边界只覆盖它建模过的那几类语法。SQL 注入、XSS 这类有清晰语法结构的能建模命令注入、文件包含、反序列化这类“要看上下文才知道危不危险”的语义分析帮不上太多忙还得回到规则验证那条路上。所以成熟的引擎通常是两条腿走路——语义检测兜住变体规则覆盖剩下的类别。4.3 自主学习不依赖规则库的那种思路还有一条更“野”的路子不写规则让引擎自己学。Naxsi 就是这么干的它先记录正常请求里每个参数的长度范围、字符集、出现频率形成一份基线之后再有请求进来参数长度超标、出现了基线里从没出现过的字符就判为异常。它的好处是能对未知威胁有反应——不需要等规则更新只要攻击行为和正常流量有明显差异就会被拦下。对于来不及打补丁的窗口期这种能力很值钱。坏处同样明显。第一学习期本身就是风险窗口这段时间等于没穿盔甲。第二业务是活的新上线一个字段、改一次参数格式基线就过期误报立刻冒出来。第三正常但少见的输入——富文本编辑器提交的 HTML、嵌套很深的 JSON、上传文件的二进制内容——很容易被判成异常。所以这类引擎必须支持“学习模式”和“防护模式”分开跑切换前要拿真实流量回放验证一遍。4.4 一条规则长什么样动作、变量、解析、转换、操作符不管走哪条路线规则的骨架都差不多从哪个变量取值、怎么解析、先做哪些转换、用什么操作符、拿什么去比、命中之后做什么动作。下面这条规则的意思是“请求 URI 或参数值里出现../就阻断”写成这样-- 规则骨架示意路径穿越检测 { action DENY, -- 命中后的动作DENY 阻断PASS 只跳过当前阶段本条规则ALLOW 跳过所有检查 phase access, -- 在哪个阶段执行对应反向代理的 access 阶段 match { { vars { -- 变量组数组内多个变量之间是或的关系 { var REQUEST_URI }, { var ARGS, parse { values true } }, -- 只取参数的值不取参数名 }, -- 先归一化再比对顺序有讲究解码要在小写化之前 transform { uri_decode, lowercase, compress_whitespace }, operator regex, -- 操作函数正则匹配 pattern \\.\\./, -- 操作参数正则表达式本身 op_negated false, -- 是否取反默认 false }, }, }vars决定“看哪儿”常用变量组包括REQUEST_METHOD、URL、REQUEST_URI、ARGS、HTTP_USER_AGENT、HTTP_REFERER、REMOTE_ADDR、REQUEST_HEADERS、RESPONSE_HEADERS、TIME_WDAY。ARGS是参数集合里面既有名字也有值parse就是用来指定取哪一部分的五种写法互斥specific取指定 key、ignore忽略某个 key、keys只取全部 key、values只取全部 value、all全取。选错 parse规则要么漏检要么误伤这是新手最容易忽视的一处。operator决定“怎么比”。字符串类的有begins_with、ends_with、contains、equalcontains_word带词边界能避免select命中selected这种误伤regex最灵活也最慢detect_sqli和detect_xss直接调用语义检测validate_url_encoding检查%xx编码是否合法很多绕过都藏在不规范的编码里num_range、str_range、ip_utils分别处理数值范围、时间范围和 IP 段支持单 IP、网段、以连字符表示的区间pf从文件读匹配串和pattern互斥。transform决定“先怎么把输入摆平”。常用的有uri_decode、base64_decode、hex_decode、html_decode、sql_hex_decode、lowercase、uppercase、compress_whitespace、remove_whitespace、remove_comments、remove_comments_char、replace_comments、remove_nulls、replace_nulls、trim系列、normalise_path、length、md5、sha1、counter、cmd_line。转换不是越多越好每加一个函数就是一次字符串遍历规则量大时性能开销会明显堆上去。动作就那么几个PASS跳过当前阶段的规则DENY阻断请求ALLOW跳过所有检查慎用等于开后门REDIRECT重定向RESET_CONNECTION直接重置连接。生产环境里最该设的是“观察模式”——所有规则只记录不阻断跑够一周看清楚哪些规则在误伤再逐条放开。5. 容易搞混的几个概念WAF、防火墙、IPS、CDN 与 RASP 的边界WAF 这个词最大的麻烦不是难懂而是它太好用——什么都能往里装。买设备的人说防火墙做渗透的人说 IPS运维说 CDN开发说 RASP聊的常常不是同一件事。下面这几组概念是初学者最容易糊在一起的地方。5.1 WAF 和传统防火墙看信封的和看信纸的易混点两个名字里都带“firewall”都长得像网络安全设备。为什么会混在不少采购清单里它们被归到同一栏宣传材料也都爱用“守护网络安全”这种词。怎么区分传统防火墙管的是“谁能连进来”依据是 IP、端口、协议工作在三四层它只拆信封不看信纸上写了什么。WAF 管的是“连进来的人想干什么”依据是请求行、请求头、参数、Cookie、请求体工作在七层。举个具体场景443 端口对外开放防火墙的任务到此结束它认为这是一条合法的 HTTPS 连接至于这个连接里的?id1 or 11是不是注入防火墙根本不知道那是 WAF 要判的事。两者不是替代关系是接力关系。5.2 WAF 和 IPS/IDS一个看连接一个看内容易混点都能“检测攻击并阻断”告警日志长得还挺像。为什么会混很多 IPS 产品也带 Web 攻击特征库销售话术里会写“可防御 SQL 注入”听起来功能重叠。怎么区分IDS 只负责发现和告警不阻断IPS 能阻断但以网络层特征为主而且流量加密之后它看到的是密文除非做解密否则对 HTTPS 内容基本无能为力。WAF 要么部署在 TLS 终止之后要么自己就是终止点看到的是明文请求还能理解 URL 结构、参数语义、Cookie 含义。反过来端口扫描、暴力破解、协议异常这些IPS 更擅长WAF 不一定管。判断标准很简单攻击发生在应用语义层找 WAF攻击发生在连接与协议层找 IPS。5.3 WAF 和 CDN加速和防护是两件事易混点云 WAF 大多从 CDN 演进而来接入方式都是改 DNS。为什么会混同一批节点同时干着缓存和防护两件事控制台上往往也是同一个入口。怎么区分CDN 的目标是让内容离用户更近减少回源指标是命中率和时延WAF 的目标是判定每个请求是善是恶指标是检出率和误报率。它们共用一个位置但判断逻辑完全不同。有个容易被忽略的细节静态资源被缓存之后不再回源WAF 对它的检查也就少了真正的攻击面集中在那些必须回源的动态接口上。所以别把“开了 CDN”当成“有了防护”这是两笔账。5.4 WAF 和 RASP门外拦的和屋里喊的易混点防护目标高度重合都是为了挡住注入、挡住反序列化这类攻击。为什么会混两者都宣称“能防御 OWASP 十大风险”效果描述几乎一样。怎么区分WAF 站在流量入口只能看到请求长什么样不知道应用内部会怎么处理它所以遇到复杂业务逻辑就无能为力RASP 以探针形式跑在应用进程里能看到方法调用栈和真实参数攻击已经进到代码里它也能拦下来代价是要改应用、要适配运行时出问题可能直接影响进程。两者是互补的WAF 挡批量扫描和已知模式RASP 挡漏网的复杂逻辑攻击。预算有限时先上 WAF因为它不需要改代码有合规要求或者业务逻辑复杂再考虑 RASP。5.5 规则引擎和规则集发动机和货物清单易混点ModSecurity 和它的 CRS 核心规则集经常被当成一个东西说。为什么会混安装时它们总是一起出现配置文件里也挨着写。怎么区分引擎负责解析规则语法、管理执行阶段、执行动作是一台发动机规则集只是一堆规则文件是装在上面的货。发动机可以空转规则集为空时 WAF 等于没开规则集可以换换一套规则不需要换引擎。升级的时候这两者要分开评估引擎升级可能带来语法不兼容规则集升级可能带来新的误报一起上出了问题根本分不清是谁的锅。6. 什么时候该上 WAF什么时候它帮不了你先把能力边界说清楚WAF 擅长的是“已知模式 高频异常”。SQL 注入、XSS、木马上传、命令执行、文件包含、敏感文件访问、第三方组件漏洞攻击、CSRF、恶意爬虫扫描、CC 攻击这些有迹可循的东西它拦得住补丁还没打上的窗口期用虚拟补丁挡一挡也是它最值钱的用法之一。但它解决不了业务逻辑漏洞。越权访问、支付金额被改、优惠券重复领取、账号体系设计缺陷——这些请求在语法上完全合法参数看着也正常WAF 没有任何理由拦它。指望靠 WAF 兜住逻辑漏洞多半会失望。也解决不了流量层的洪水。带宽被打满的时候请求根本到不了规则引擎这时候要靠流量清洗。什么时候别硬上服务只对内网提供、没有公网域名硬套云 WAF 只会给自己加一跳业务跑的是私有协议、不是 HTTP(S)WAF 看不懂团队里没人能长期维护规则那就老老实实选托管型别自己搭一套然后放着长草。场景建议公网 Web 业务无专职安全人员云 WAF先用观察模式跑一周自建机房流量不便出门硬件串行 bypass或软件形态机器数量少、预算紧软件形态先把日志和规则跑起来有合规审计要求任意形态但要留完整的拦截与放行日志纯内网服务、非 HTTP 协议别上钱花在别处有个细节值得单独说上线顺序。规则一次性全开最容易出现的不是漏拦而是误杀然后业务方半夜打电话运维顶不住压力把整个规则集关掉从此 WAF 变成一个只占资源的装饰品。正确做法是先只记录不阻断跑够一周把误报按接口、按规则逐条清掉再分批切换成阻断切换当天留好一键回源开关。从那以后我每次接手一套 WAF都强制先跑观察模式、先看三天日志再动阻断开关哪怕上线时间再紧也不跳过这一步。慢三天能省掉后面三个月的扯皮。希望帮到你。本文还有配套的精品资源点击获取