DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

HAProxy 跳到 www 后仍重定向循环:用当前 Host 判断目标

HAProxy 终止 TLS 后按 SNI 跳转,可能把已到达目标域的请求再次跳到自己。核对当前 Host 与 Location,用 HTTP 主机名判断并保留透传模式边界。

HAProxy 把 example.com 跳到 www.example.com,部分浏览器却不断收到同一个跳转,最终提示 ERR_TOO_MANY_REDIRECTS。如果规则依据 ssl_fc_sni 判断来源主机,而入口证书同时覆盖两个名称,应核对每条 HTTP 请求的 Host。

SNI 是 TLS 握手时发送的名称,不会随着同一连接上的每次 HTTP 请求重新发送。满足客户端连接复用条件时,浏览器可以通过已有连接请求证书覆盖的另一个主机名。此时 SNI 仍是 example.com,当前请求的 Host 已经是 www.example.com,旧条件仍可能命中。

本文讨论 HAProxy 终止 TLS、并以 HTTP 模式处理域名跳转的场景。2.2.x 环境也会遇到这种配置问题,但仅因升级后开始出现,不能认定某一补丁版本修改了连接复用或引入了确定缺陷。当前 HAProxy 文档仍明确区分 SNI 与 HTTP Host。

看每一次 Location,而不是只看最终错误

在浏览器网络面板保留请求记录,查看首个域名和跳转后的请求、各次状态及 Location。若请求已经指向 www.example.com,响应仍指向相同地址,应找出哪一层生成了这次跳转。

在受控诊断日志中关联实际 Host、入站 SNI 和匹配的规则。只记录必要字段,不收集 Cookie、认证令牌或带敏感查询参数的完整 URL。SNI 与 Host 不同是这条判断路径的关键证据,而不是证书同时包含两个名称就必然出错。

curl 或另一个浏览器没有复现,也不能证明规则正确:客户端可能采用不同的连接复用方式。若循环发生在 HTTP/HTTPS 两种协议之间,或由后端的公共 URL 配置生成,应沿实际跳转链查对应层,不能全部归因于 SNI。

域名跳转按 HTTP Host 匹配

以下是 HTTP frontend 中的结构片段,展示只把源域名送到固定首页的规则:

mode http
http-request redirect location https://www.example.com/ code 302 if { hdr(host) -i example.com }

它替代以 ssl_fc_sni 判断域名的同类条件。目标域名 www.example.com 不满足这个 Host 条件,因此不会由这条规则再次跳到自己。先使用临时跳转便于验收,再按站点策略决定是否使用永久跳转。

这个固定 Location 示例会把路径与查询参数送到首页;需要保留它们的网站,应另外设计保留 URI 的跳转规则,并分别验收路径和查询参数,不能把首页示例直接当成完整迁移配置。

实际 Host 可能包含非默认端口,应按网站允许的入口处理匹配,不能一面仅匹配裸域名,一面假设所有端口都会命中。目标使用固定的获准域名,避免把未经核对的请求头直接拼成任意跳转目标。

保留其他必要的 HTTP/HTTPS 跳转、证书与后端路由,但检查它们是否与这条规则互相循环。既有规则同时检查 SNI 和 Host 时,也应确认保留 SNI 限制是否有明确用途,而不是把握手名当作当前请求名称。

TLS 透传不适用这条 HTTP 配置

TCP 模式透传 TLS 时,HAProxy 看不到加密后的 HTTP Host。该模式下依赖握手中的 SNI 选择后端是另一种用途,不能直接把条件替换成 hdr(host),也不能在未终止 TLS 的连接上生成 HTTP 跳转。

还要区分 ssl_fc_sni 与 req.ssl_sni:前者读取由 HAProxy 本地解密的 TLS 连接信息,后者用于查看尚未解密的握手数据。改用 HTTP Host 的前提是当前层确实在处理 HTTP 请求。

配置加载后验证原域和目标域

修改前保存配置、有效证书和已有规则,在本机对同一个 HAProxy 实例检查语法,再按既有管理流程加载。若调整规则位置,同时核对其他 HTTP 请求规则的先后关系。

验收应覆盖原域请求、直接访问目标域,以及此前出错的浏览器。原域按规划跳转,目标域不再跳回自己,最终到达预期页面。若有保留 URI 的设计,再单独检查含路径和查询参数的请求,确认登录回调等没有改变目标。

永久跳转可能已被浏览器缓存,修正服务端规则后需区分缓存与新响应。回退时恢复保存的配置并重新加载;服务端回退不会自动清除客户端已记住的跳转,因此应保留诊断记录并验证新的请求链。