Nginx+Varnish+SSL环境下Varnish缓存清除失败求助
问题排查与解决步骤
1. 确认Varnish的purge ACL包含WebServer内网IP
你VCL里用!client.ip ~ purge限制了能发送PURGE请求的IP,但没给出purge这个访问控制列表(ACL)的定义。如果WebServer的内网IP不在这个列表里,从WP所在WebServer发出的PURGE请求会直接被Varnish拒绝(返回405)。
- 找到VCL中的
acl purge块,补充WebServer的内网IP:acl purge { "127.0.0.1"; "::1"; # 替换成你的WebServer内网IP,比如192.168.1.100 "192.168.1.100"; } - 添加后重启Varnish生效。
2. 检查CacheServer上的Nginx是否转发PURGE请求到Varnish
CacheServer的Nginx负责SSL终结,必须确保它把PURGE请求转发给Varnish,而非自行拦截。查看Nginx虚拟主机配置:
- 确保反向代理规则允许PURGE方法转发:
location / { proxy_pass http://127.0.0.1:6081; # 对应Varnish监听的端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 允许PURGE方法传递给Varnish proxy_method $request_method; } - 如果Nginx拦截了PURGE请求,Varnish根本收不到,插件自然无法清除缓存。
3. 验证缓存对象是否带有x-url和x-host头
你的ban规则依赖obj.http.x-url和obj.http.x-host两个头,但如果缓存对象时Varnish没设置它们,ban规则会匹配不到任何内容,等于无效执行。
- 检查VCL的
vcl_backend_response部分,添加这两个标记头:sub vcl_backend_response { # 给缓存对象标记URL和Host,用于后续ban操作匹配 set beresp.http.x-url = bereq.url; set beresp.http.x-host = bereq.http.host; # 其他缓存配置... } - 添加后重启Varnish,新缓存的对象才会带有这两个头,旧缓存需重启清除或手动ban。
4. 确认WP插件的PURGE目标配置正确
插件里必须填写CacheServer的内网IP+Varnish监听端口(比如192.168.1.200:6081),不要填公网IP或localhost:
- WP在WebServer上,直接走内网发请求到CacheServer,可绕过Cloudflare——Cloudflare默认拦截PURGE这类非常规HTTP方法,绕开它才能让请求到达Varnish。
- 同时确保Varnish监听内网IP或0.0.0.0,而非仅监听127.0.0.1,否则WebServer无法连接。
5. 手动用curl测试PURGE请求,排除插件问题
在WebServer上直接执行curl命令,测试Varnish的PURGE功能是否正常:
# 替换为你的CacheServer内网IP、端口、域名和页面路径 curl -X PURGE http://192.168.1.200:6081/your-target-page/ -H "Host: your-domain.com"
- 返回
200 Purged:说明Varnish的PURGE功能正常,问题出在插件配置; - 返回
405 PURGE not allowed for this IP address:说明WebServer的IP不在purge ACL中; - 连接超时/失败:要么Varnish没监听内网IP,要么防火墙拦截了端口。
6. 避免Cloudflare干扰PURGE请求
如果插件填了公网IP,请求会经过Cloudflare,但Cloudflare默认不允许PURGE方法(除非专门配置规则,但这不是清除Varnish缓存的正确方式)。必须让插件直接访问CacheServer的内网IP,绕开Cloudflare。
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

