我目前在不同的子域下运行着不同的服务:
a.example.com:nginx 代理后面的 Docker 容器
b.example.com:nginx 站点
c.example.com:nginx 代理后面的 Docker 容器
a 和 c 共享相同的 ipv4,b 有自己的 ipv4,而 a、b 和 c 都使用不同的 ipv6 地址。它们都是 SSL 安全的,非 SSL 流量由 nginx(通过 301)重定向到 SSL 安全的站点。
所有这些都通过 HSTS 进行保护(未设置可选的“includeSubdomains”)。
现在,我的问题
- 打开https://a.example.com通过 Firefox -> 工作
- 打开https://b.example.com通过 Firefox -> 工作
- 打开https://a.example.com通过 firefox -> 不起作用,它反而显示 b.example.com。看来 firefox 以某种方式缓存了 b.example.com。如果我按下 shift+reload,firefox 会加载正确的 a.example.com 网站。
这是 Firefox 特有的问题。上述内容在 Chrome、Vivaldi、MS Edge(基于 Chromium)上完美运行。它甚至可以在 wget 上正常运行。我不知道是什么原因导致 Firefox 从其存储中抓取错误的网站。
如能得到任何帮助,我们将不胜感激。
答案1
如果有人遇到同样的问题:这是一个 Firefox 错误,更多详细信息请参见此处:https://matthias.wuerfl.com/firefox-http2-ipv6-pitfall/
概括:
状况
- 两个(或更多)子域(同一域)
- …共享一个通用的通配符 SSL 证书
- 在同一主机上(相同的 IPv4 地址)
- 但使用不同的 IPv6 地址
- 客户端:Firefox(只有 Firefox 有此行为)
- 使用 HTTP/2
- 使用 IPv6
预期行为:
- 地址栏中的 foo.example.com 显示 foo.example.com
- 地址栏中的 bar.example.com 显示 bar.example.com
已见行为
对第二台主机(bar)的请求转到第一台主机(foo)。
解释
使用 HTTP/2,Firefox 可以共享与 Web 服务器的连接(“池化”),从而通过省略握手和 TCP 慢启动来加快页面加载速度。Firefox 不是通过查看主机名来确定哪些连接可以池化,而是通过查看 IPv4 地址和证书来确定。如果第二台主机 (bar) 的 IPv4 地址与第一台主机 (foo) 的 IPv4 地址匹配,并且用于 foo 的证书也与 bar 匹配,则与 foo 的连接将被重新用于 bar。
问题
当有人连接到 foo 的 IPv6 地址时,Web 服务器可能未配置为显示 bar 的内容。Web 服务器管理员对 IPv6 不再需要 SNI 和基于名称的虚拟托管这一事实感到高兴(比如我),他们可能在配置 Web 服务器时错误地认为,如果为主机名 foo 发布 IPv6 地址,则到该主机的传入连接将转到该 IP 地址。
Firefox 的行为非常出人意料 – 或者完全是错误的。