如何通过Nginx Cache-Purge模块高效清除缓存污染的非法响应?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1114个文字,预计阅读时间需要5分钟。
《Cache-Purge模块非法响应——它只按请求URI(或带特定头)删除缓存条目,不校验响应内容是否合法。所谓缓存污染,需先定位污染源,再用purge清理对应缓存键。”
为什么 proxy_cache_purge 不会自动识别非法响应
Nginx 的缓存机制本身不解析响应体内容,也不做签名/哈希校验。即使后端返回了 200 OK 但含恶意 HTML 或错误 JSON,只要满足 proxy_cache_valid 规则,就会被无差别缓存。Cache-Purge 模块仅响应一个 purge 请求(如 GET /foo HTTP/1.1 + Cache-Control: no-cache 或自定义头),然后根据 proxy_cache_key 计算出的 key 删除磁盘上的缓存文件,不做任何内容检查。
常见误操作包括:
- 以为发个
curl -X PURGE http://example.com/bad-api就能“扫描并清除所有异常响应”——实际只删该 URI 对应的缓存(且需配置允许 PURGE 方法) - 未同步更新
proxy_cache_key,导致 purge 请求计算的 key 和缓存时的 key 不一致,删错或删不掉 - 在多级缓存(CDN + Nginx)场景下,只 purge Nginx 缓存,而污染响应早已被 CDN 固化
配置 proxy_cache_purge 的最小可靠组合
必须显式启用 purge 功能,并严格约束触发条件,否则可能引发缓存雪崩或未授权清除。
- 在
http块中加载模块:load_module modules/ngx_http_cache_purge_module.so;(路径依编译选项而定) - 定义缓存区时启用 purge:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m inactive=60m use_temp_path=off; - 在 server 或 location 块中添加 purge 配置:
proxy_cache_purge $purge_key;,其中$purge_key必须与缓存时的proxy_cache_key完全一致(例如都为$scheme$proxy_host$uri$is_args$args) - 限制 purge 权限:用
allow/deny或 JWT 验证,禁止公网直接调用;例如只允 127.0.0.1:allow 127.0.0.1; deny all;
如何精准定位并 purge 被污染的缓存项
污染通常源于上游服务异常、配置错误或中间人篡改,不能靠猜。得从缓存文件反推 key,再构造 purge 请求。
- 查缓存文件路径:进入
proxy_cache_path指定目录(如/var/cache/nginx),用find . -name "*<em>hex-hash</em>" -exec ls -la {} \;找最近修改的缓存文件 - 解码 key:Nginx 缓存文件名是 key 的 MD5,可用
echo -n "http://backend/path?x=1" | md5sum对比(注意 key 中是否含$host、$cookie_xxx等变量) - 构造 purge 请求:确保请求方法、URI、query、headers(尤其是影响
proxy_cache_key的部分)与原始请求完全一致,例如:curl -X PURGE "https://api.example.com/v1/data?id=123" -H "Host: api.example.com" - 验证是否成功:响应应为
204 No Content;若返回404,说明该 key 当前无缓存;返回405表示未启用 PURGE 方法
缓存污染发生后更有效的应对顺序
purge 是补救手段,不是根治方案。优先级应是:阻断污染源 → 临时绕过缓存 → 精准 purge → 加入响应内容校验。
- 立即停用问题 upstream server,或用
proxy_next_upstream error timeout http_500避免缓存错误响应 - 对高风险接口临时禁用缓存:
proxy_cache_bypass $http_x_purge; proxy_no_cache $http_x_purge;,配合 header 切流 - 若污染范围广(如全站 200 响应被注入 script 标签),不要逐个 purge,改用
proxy_cache_path ... inactive=1s;强制快速过期(慎用,可能击穿上游) - 长期方案:在
proxy_cache_valid中排除非预期状态码(如proxy_cache_valid 404 5s;),或用map根据$upstream_http_content_type动态控制是否缓存
真正难的是确认“哪些响应算非法”——Nginx 不提供内容匹配能力,这部分必须前置到应用层或 WAF 实现。Cache-Purge 只管删,不管判。
本文共计1114个文字,预计阅读时间需要5分钟。
《Cache-Purge模块非法响应——它只按请求URI(或带特定头)删除缓存条目,不校验响应内容是否合法。所谓缓存污染,需先定位污染源,再用purge清理对应缓存键。”
为什么 proxy_cache_purge 不会自动识别非法响应
Nginx 的缓存机制本身不解析响应体内容,也不做签名/哈希校验。即使后端返回了 200 OK 但含恶意 HTML 或错误 JSON,只要满足 proxy_cache_valid 规则,就会被无差别缓存。Cache-Purge 模块仅响应一个 purge 请求(如 GET /foo HTTP/1.1 + Cache-Control: no-cache 或自定义头),然后根据 proxy_cache_key 计算出的 key 删除磁盘上的缓存文件,不做任何内容检查。
常见误操作包括:
- 以为发个
curl -X PURGE http://example.com/bad-api就能“扫描并清除所有异常响应”——实际只删该 URI 对应的缓存(且需配置允许 PURGE 方法) - 未同步更新
proxy_cache_key,导致 purge 请求计算的 key 和缓存时的 key 不一致,删错或删不掉 - 在多级缓存(CDN + Nginx)场景下,只 purge Nginx 缓存,而污染响应早已被 CDN 固化
配置 proxy_cache_purge 的最小可靠组合
必须显式启用 purge 功能,并严格约束触发条件,否则可能引发缓存雪崩或未授权清除。
- 在
http块中加载模块:load_module modules/ngx_http_cache_purge_module.so;(路径依编译选项而定) - 定义缓存区时启用 purge:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m inactive=60m use_temp_path=off; - 在 server 或 location 块中添加 purge 配置:
proxy_cache_purge $purge_key;,其中$purge_key必须与缓存时的proxy_cache_key完全一致(例如都为$scheme$proxy_host$uri$is_args$args) - 限制 purge 权限:用
allow/deny或 JWT 验证,禁止公网直接调用;例如只允 127.0.0.1:allow 127.0.0.1; deny all;
如何精准定位并 purge 被污染的缓存项
污染通常源于上游服务异常、配置错误或中间人篡改,不能靠猜。得从缓存文件反推 key,再构造 purge 请求。
- 查缓存文件路径:进入
proxy_cache_path指定目录(如/var/cache/nginx),用find . -name "*<em>hex-hash</em>" -exec ls -la {} \;找最近修改的缓存文件 - 解码 key:Nginx 缓存文件名是 key 的 MD5,可用
echo -n "http://backend/path?x=1" | md5sum对比(注意 key 中是否含$host、$cookie_xxx等变量) - 构造 purge 请求:确保请求方法、URI、query、headers(尤其是影响
proxy_cache_key的部分)与原始请求完全一致,例如:curl -X PURGE "https://api.example.com/v1/data?id=123" -H "Host: api.example.com" - 验证是否成功:响应应为
204 No Content;若返回404,说明该 key 当前无缓存;返回405表示未启用 PURGE 方法
缓存污染发生后更有效的应对顺序
purge 是补救手段,不是根治方案。优先级应是:阻断污染源 → 临时绕过缓存 → 精准 purge → 加入响应内容校验。
- 立即停用问题 upstream server,或用
proxy_next_upstream error timeout http_500避免缓存错误响应 - 对高风险接口临时禁用缓存:
proxy_cache_bypass $http_x_purge; proxy_no_cache $http_x_purge;,配合 header 切流 - 若污染范围广(如全站 200 响应被注入 script 标签),不要逐个 purge,改用
proxy_cache_path ... inactive=1s;强制快速过期(慎用,可能击穿上游) - 长期方案:在
proxy_cache_valid中排除非预期状态码(如proxy_cache_valid 404 5s;),或用map根据$upstream_http_content_type动态控制是否缓存
真正难的是确认“哪些响应算非法”——Nginx 不提供内容匹配能力,这部分必须前置到应用层或 WAF 实现。Cache-Purge 只管删,不管判。

