Varnish配置HTTP转HTTPS重定向误触发HTTPS请求问题排查
配置问题根因
你写的配置有三类问题直接导致HTTPS请求被误触发跳转:
- 条件判断逻辑完全错误:使用
||(逻辑或)拼接两个请求头校验规则,同时额外校验了非通用的Scheme头。逻辑或的判定规则是只要任意一个子条件成立,整个判断结果就为真,原逻辑的思路是“只要请求没明确标记为HTTPS就跳转”,而正确的判断逻辑应该是“只有请求明确标记为HTTP时才跳转”。绝大多数HTTPS卸载场景(HTTPS终止在Varnish前端的CDN、负载均衡、Nginx上),前端只会通过X-Forwarded-Proto头传递原始请求的协议,根本不会传递Scheme头;当Scheme头不存在时,req.http.Scheme != "https"这个条件会永久成立,不管请求本身是HTTP还是HTTPS,都会触发重定向,直接造成HTTPS请求循环跳转。 - 语法版本过时:你用的
vcl_error子程序、error关键字是Varnish 3.x的废弃语法,在目前主流使用的Varnish 4.0+版本中已经被替换为vcl_synth和return(synth()),旧语法在新版本下运行会出现不可预期的行为。另外你贴的原始代码中vcl_recv子程序缺少闭合大括号,会直接导致配置加载失败。 - 状态码选择不规范:目前返回的302是临时重定向,生产环境强制HTTPS跳转应该使用301永久重定向,既能减少重复跳转的请求开销,也更符合搜索引擎的爬取规则。
修正后配置
以下配置适用于HTTPS在Varnish前端设备终止、前端通过X-Forwarded-Proto头传递原始协议的最常见部署场景:
sub vcl_recv { # 仅当X-Forwarded-Proto头存在,且值标识原始请求为HTTP时触发跳转 if (req.http.X-Forwarded-Proto && req.http.X-Forwarded-Proto != "https") { return (synth(750, "Redirect to HTTPS")); } # 此处保留你原有的其他vcl_recv业务逻辑 } sub vcl_synth { if (resp.status == 750) { set resp.status = 301; set resp.http.Location = "https://" + req.http.Host + req.url; return (deliver); } # 此处保留你原有的其他vcl_synth业务逻辑 }
如果你是用Varnish本身直接监听443端口终止HTTPS连接,不需要依赖X-Forwarded-Proto头判断,把vcl_recv里的跳转判断条件替换为下面的即可:
if (req.proto != "https") { return (synth(750, "Redirect to HTTPS")); }
验证注意事项
- 修改配置后需要执行Varnish配置重载命令让新规则生效
- 测试时优先使用浏览器无痕模式,避免之前错误跳转产生的301/302缓存干扰验证结果
内容的提问来源于stack exchange,提问作者susan
相关产品推荐
相关产品推荐

