近期遇到一种情况:主域名(例如 https://example.net/)及其附加路径(如 /path1/, /path2/ 等)在苹果手机(iOS Safari)上无法访问,但子域名(如 mail.example.net, chat.example.net)可以正常访问。此问题在非苹果浏览器(如 Windows Chrome 或 Android 浏览器)中不会出现,表现为白屏、无响应或直接连接失败。

经过详细排查,总结出原因及解决方案如下。


🟢 初步排查方向

  1. SSL 证书链完整性
    使用 SSL Labs 进行检测,确认没有中间证书丢失或链错误,评分为 A 或 A+。
  2. TLS 协议与加密套件
    确认服务器仅开启 TLS 1.2 和 TLS 1.3,不使用 TLS 1.0/1.1 或 SSL3 等旧协议;并启用现代加密套件(AES-GCM、CHACHA20 等)。
  3. HTTP header 检查
    通过 curl -I -L https://example.net/ 检测响应头,查看是否包含异常字段。

🔥 根本原因分析

在配置文件中发现,主域名使用了以下配置:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

这两行配置用于 WebSocket 或需要协议升级的后端(如即时通讯服务),但普通 Web 服务或静态资源并不需要。如果后端(如 Apache)返回了 Upgrade: h2,h2c header,Nginx 会将此 header 透传给前端浏览器。苹果 Safari 对该 header 十分敏感,如果出现多余或错误的 Upgrade header,会直接拒绝连接,导致无法访问。


✅ 解决方案

1️⃣ 注释多余的 header

将主域名配置中的以下两行注释:

# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";

这两行只在后端真正需要 WebSocket 或 HTTP/2 cleartext (h2c) 时使用。


2️⃣ 强制隐藏后端返回的 header

即使在前端 Nginx 中注释了上述 header,如果后端服务(如 Apache)依旧返回 Upgrade: h2,h2c,需要在 Nginx 配置中强制移除:

proxy_hide_header Upgrade;
proxy_hide_header Connection;

3️⃣ 重载 Nginx

完成修改后执行:

nginx -t
systemctl reload nginx

✅ 验证

  • 再次通过 curl -I -L https://example.net/ 验证,确认没有 Upgrade header,且返回 200 正常。
  • 在 Safari 浏览器中清理缓存后重新访问,确认页面可以正常加载。

⚡️ SSL Labs 再次检测结果

修复后再次提交 SSL Labs 检测,表现为:

  • 评分 A
  • 所有主流客户端、系统、浏览器握手模拟均通过
  • 没有 Upgrade header 或协议错误

💬 附加建议

  • 如果需要进一步强化 HTTPS,可考虑配置 HSTS header:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  • 如果希望限制证书签发机构,可配置 DNS CAA 记录,提升证书安全性。

🟢 总结

此问题主要来源于错误或不必要的 Upgrade header,修复后可彻底解决苹果设备无法访问的问题,并不会影响其他浏览器或平台的正常访问。

Leave a Reply

Your email address will not be published. Required fields are marked *