HAProxy+Keepalived+Varnish+Apache架构HTTPS静态资源加载异常求助
问题根源
你遇到的问题核心是混合内容拦截:HAProxy完成SSL终止后,后端Varnish和Apache用HTTP通信,但WordPress不知道前端实际是HTTPS请求,因此生成的静态资源(CSS/JS/图片)URL仍为HTTP,浏览器出于安全策略会拦截这些HTTP资源,导致加载失败。
分步解决步骤
1. 调整HAProxy配置:传递HTTPS标识头
在HAProxy指向Varnish的backend配置块中,添加以下指令,将前端的HTTPS协议信息传递给后端:
# 标记当前请求来自HTTPS http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Port 443 if { ssl_fc } # 保留原始Host头,避免WordPress生成错误的URL http-request set-header Host %[req.hdr(Host)]
修改后重启HAProxy:systemctl restart haproxy
2. Varnish配置:透传HTTPS标识头到Apache
确保Varnish将HAProxy传递的X-Forwarded-Proto和X-Forwarded-Port头完整转发给后端Apache,在VCL配置的vcl_backend_fetch段添加:
sub vcl_backend_fetch { # 透传HTTPS协议标识 set bereq.http.X-Forwarded-Proto = req.http.X-Forwarded-Proto; set bereq.http.X-Forwarded-Port = req.http.X-Forwarded-Port; # 保留原始Host头 set bereq.http.Host = req.http.Host; }
修改后重启Varnish:systemctl restart varnish,并清空现有缓存:varnishadm ban req.url ~ .
3. Apache配置:识别HTTPS前端请求
先启用mod_headers模块(若未启用),再在监听82端口的虚拟主机配置中添加指令,让Apache识别前端的HTTPS请求:
# 启用mod_headers模块 a2enmod headers systemctl restart apache2
<VirtualHost *:82> # 其他原有配置... # 识别X-Forwarded-Proto头,标记为HTTPS请求 SetEnvIf X-Forwarded-Proto "https" HTTPS=on RequestHeader set X-Forwarded-Proto "https" env=HTTPS </VirtualHost>
重启Apache生效:systemctl restart apache2
4. WordPress配置:强制HTTPS并修正资源URL
后台设置调整
登录WordPress后台,进入设置->常规,将WordPress地址(URL)和站点地址(URL)全部修改为https://myexemple.com,保存设置。
wp-config.php强制HTTPS
若后台修改后仍有问题,编辑网站根目录的wp-config.php,添加以下代码:
define('WP_HOME','https://myexemple.com'); define('WP_SITEURL','https://myexemple.com'); define('FORCE_SSL_ADMIN', true); // 识别前端HTTPS请求 if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { $_SERVER['HTTPS'] = 'on'; }
修正已存在的HTTP资源链接
备份数据库后,执行以下SQL语句替换旧的HTTP链接(注意替换实际表前缀wp_):
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://myexemple.com', 'https://myexemple.com'); UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, 'http://myexemple.com', 'https://myexemple.com');
同类架构部署经验
- SSL终止层必须前置:免费版Varnish不支持HTTPS,因此SSL终止只能放在HAProxy(或NGINX)层,你的架构选型是正确的。
- 链路头信息一致性:从HAProxy到Varnish再到Apache,必须确保
X-Forwarded-Proto、Host等核心头信息不被丢弃或篡改,这是后端服务识别前端协议的关键。 - 缓存清理:修改配置后必须清空Varnish缓存,避免旧的HTTP响应继续被返回。
- 测试验证:用
curl命令验证资源URL是否正确:
检查响应内容中的引用URL是否为HTTPS,同时查看请求头是否包含curl -v https://myexemple.com/wp-content/themes/your-theme/style.cssX-Forwarded-Proto: https。
内容的提问来源于stack exchange,提问作者kiminox

