跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

排查 Cloudflare Tunnel 的 HTTPS 源站问题

最后更新 查看 MarkdownAgent 设置

如果您的 Cloudflare Tunnel 为 Healthy,但 app.example.com 失败,请检查路由的 Service URL、源站证书和 SSL/TLS 加密模式。

Healthy 状态仅确认 cloudflared 已连接到 Cloudflare。它不会测试路由的服务或本地源站。

本指南适用于已经使用 Let's Encrypt 证书提供 HTTPS 的源站。您可以保留已安装的现有证书。

对于将 HTTP 重定向到 HTTPS 的 Apache 源站,请使用以下设置:

  • Service URL:当 cloudflared 运行在 Apache 主机上时,使用 https://localhost:443
  • Origin Server Name(源站服务器名称):证书所覆盖的主机名,例如 app.example.com
  • Disable TLS certificate verification(禁用 TLS 证书验证):关闭
  • Encryption mode(加密模式):保持选中 Automatic SSL/TLS (recommended)(自动 SSL/TLS(推荐)),或选择 Full (Strict)

了解路由

公共主机名是访问者请求的 URL。Service URL 是 cloudflared 可以到达的地址、协议和端口。这些值不可互换。当公共主机名指向 Tunnel CNAME 时,不要将其用作服务 URL。

例如,http://localhost:80 对本地连接使用 HTTP,而 https://localhost:443 使用 HTTPS。请将这些示例替换为您源站使用的地址和端口。

Cloudflare 与 cloudflared 之间的连接独立于 zone 的 SSL/TLS 模式进行加密。cloudflared 通过源站参数验证本地源站证书。

zone 的 SSL/TLS 模式不会更改 Service URL。先在路由中配置本地协议,然后使用 originServerName 和其他源站参数配置证书验证。

如果 originServerName 为空,cloudflared 会期望证书覆盖 Service URL 中的主机。对于使用 localhost 的服务 URL,请将 originServerName 设置为证书所覆盖的主机名。该值还会为 TLS 连接提供 Server Name Indication (SNI)。

选择路由和 SSL/TLS 设置

使用以下决策树选择本地协议和证书设置:

flowchart TD
    accTitle: Service URL 与 SSL/TLS 模式决策树
    accDescr: 根据源站协议选择 Service URL,然后为 HTTPS 源站配置证书验证。
    A{源站接受 HTTPS?}
    A -->|否| B{HTTP 是否重定向到 HTTPS?}
    B -->|否| C[使用 HTTP Service URL]
    B -->|是| D{是否保留该重定向?}
    D -->|否| C
    D -->|是| E[配置 HTTPS 侦听器]
    A -->|是| F[使用 HTTPS Service URL]
    E --> F
    F --> G{证书是否覆盖服务主机?}
    G -->|是| H[保持 TLS 验证开启]
    G -->|否| I[设置 Origin Server Name 并保持验证开启]

如果源站没有 HTTPS 侦听器,请在保留 HTTP Service URL 之前移除或调整其重定向。不要将 HTTPS Service URL 指向 HTTP 侦听器。

使用下表比较常见的源站和 zone 设置:

源站行为 Service URL 源站参数 Zone SSL/TLS 指导
仅 HTTP,没有重定向 http://127.0.0.1:80 无 TLS 参数 Automatic、Flexible、Full 和 Full (strict) 都不会更改本地 HTTP 连接。
HTTP 重定向到 HTTPS https://localhost:443,或移除重定向并使用 HTTP 将路由配置为 HTTPS 不要使用 Flexible 来解决重定向循环。
使用覆盖 app.example.com 的有效 Let's Encrypt 证书的 HTTPS https://localhost:443 设置 originServerName: app.example.com。保持 Disable TLS certificate verification 关闭,并省略 caPool。 单独选择 zone 模式。它不会验证本地证书。
使用私有证书颁发机构 (CA) 的 HTTPS https://localhost:443 设置 originServerName 和 caPool。保持 Disable TLS certificate verification 关闭。 单独选择 zone 模式。先修复证书信任。

对于公共 HTTPS 主机名,Full (strict) 与此配置兼容。不过,cloudflared 会独立验证本地 Let's Encrypt 证书。zone 模式不会取代路由的 Service URL 或 originServerName 设置。

Full 也不会更改 Tunnel 服务协议或修复源站证书错误。不要为这两种问题切换到 Flexible。请改为更新路由的 Service URL 或源站参数。

更新远程管理的路由

对于远程管理的隧道,请在仪表板中更新路由及其源站参数:

  1. 在 Cloudflare 仪表板 ↗中,转到 Networking(网络) > Tunnels(隧道),然后选择您的隧道。

    前往 Tunnels(隧道) ↗
  2. 在 Routes(路由) 上,为 app.example.com 选择 Edit route(编辑路由)。

  3. 在 Service URL 中,当源站提供 HTTPS 时输入 https://localhost:443。仅当服务使用 HTTP 且不会重定向到 HTTPS 时,才使用 http://127.0.0.1:80。

  4. 展开 Additional application settings(其他应用程序设置)。在 TLS 下,当证书覆盖该主机名时,将 Origin Server Name 设置为 app.example.com。

    保持 Disable TLS certificate verification 关闭。对于受公众信任的 Let's Encrypt 证书,将 CA Pool 留空。仅当源站使用私有 CA 时再设置它。

  5. 选择 Save changes(保存更改)。

该路由不要求您移除现有的 Let's Encrypt 证书。当源站名称和服务协议匹配时,cloudflared 可以验证该证书。

将 SSL/TLS 模式分开处理

zone 的 SSL/TLS 模式与 Tunnel 路由是分开的。它不会选择本地协议,也不会修复 cloudflared 与源站之间的证书不匹配。

要查看或更改 zone 模式:

  1. 在 Cloudflare 仪表板 ↗中,转到 SSL/TLS > Overview(概览)。

    前往 Overview(概览) ↗
  2. 在 SSL/TLS Overview 上,选择 Configure(配置)。

  3. 在 Encryption mode(加密模式) 下,查看所选选项。如果已选中 Automatic SSL/TLS (recommended),在排查此 Tunnel 路由时请保持该选项。自动模式不会更改路由的 Service URL。

  4. 若要使用特定模式,请选择 Full (Strict),然后选择 Save(保存)。此 zone 设置不会取代 cloudflared 的证书验证。

  5. 不要选择 Flexible 来解决本地源站证书不匹配。请改为更新 Tunnel 路由的 Service URL 或源站参数。

有关可用模式的详细信息,请参阅 SSL/TLS 加密模式。如果源站将 HTTP 重定向到 HTTPS,HTTP Service URL 可能导致重定向循环。有关其他重定向原因,请参阅 ERR_TOO_MANY_REDIRECTS。

配置本地管理的隧道

对于本地管理的隧道,请将相同设置放入 config.yml:

config.ymlyml
tunnel: <TUNNEL_UUID>
credentials-file: /path/to/<TUNNEL_UUID>.json

ingress:
  - hostname: app.example.com
    service: https://localhost:443
    originRequest:
      originServerName: app.example.com
  - service: http_status:404

此示例保持 TLS 验证启用。它省略了 caPool,因为标准 Let's Encrypt 证书受公众信任。对于私有 CA,请在 originRequest 下添加 caPool: /path/to/ca.pem。

在 Windows 上,如果 cloudflared 报告无法加载系统根证书池,请将 caPool 设置为包含证书颁发机构的本地 PEM 包。

仅在修复证书信任或源站名称时,将 noTLSVerify: true 作为临时的最后手段。解决根本问题后请将其关闭。

文件末尾必须有兜底的 http_status:404 规则。编辑 config.yml 后,验证入站规则:

cloudflared tunnel ingress validate

运行诊断

从公共互联网以及与 cloudflared 相同的主机运行这些检查:

  1. 检查公共主机名和 DNS。 在 Cloudflare 仪表板中,转到 example.com 的 DNS > Records(记录)。确认 app.example.com 是指向 <TUNNEL_ID>.cfargotunnel.com 的 CNAME。

    前往 Records(记录) ↗

    从终端检查确切的主机名:

    dig CNAME app.example.com +short
    dig A app.example.com +short
    dig AAAA app.example.com +short

    已代理记录可能返回 Cloudflare 地址,而不是 CNAME 目标。在这种情况下,请使用仪表板验证目标。

    Cloudflare 不会在 Tunnel 停止后静默回退到 A 或 AAAA 记录。如果隧道停止,DNS 记录仍然存在,访问者会收到 1016 错误。有关更多信息,请参阅 Tunnel DNS 记录。如果流量似乎直接到达源站,请检查该确切主机名是否有 A 或 AAAA 记录而不是预期的 CNAME,或者是否由显式负载平衡器或其他路由提供服务。

  2. 检查重定向标头和状态。 从客户端请求公共主机名,并跟随有限次数的重定向:

    curl -sS -D - -o /dev/null https://app.example.com/
    curl -sS -D - -o /dev/null -L --max-redirs 5 https://app.example.com/

    查找重复的 Location 标头以及 301、302、307 或 308 状态码。从 cloudflared 主机直接测试 HTTP 侦听器:

    curl -sS -D - -o /dev/null -H "Host: app.example.com" http://127.0.0.1:80/

    如果源站返回 HTTPS Location 标头,请使用 HTTPS Service URL 或更改源站重定向策略。HTTP Service URL 会通过 HTTP 将每个请求发送到源站,并可能无限重复重定向。

  3. 检查源站证书和 Server Name Indication (SNI)。 从运行 cloudflared 的主机执行此操作:

    openssl s_client -connect 127.0.0.1:443 -servername app.example.com -verify_hostname app.example.com -verify_return_error </dev/null

    确认证书包含 app.example.com,并且输出包含 Verify return code: 0 (ok)。当服务 URL 使用 localhost 但证书覆盖 app.example.com 时,将 Origin Server Name 设置为 app.example.com。

  4. 流式传输 Tunnel 日志。 如果隧道详情页中有 Live logs(实时日志) 标签页,请打开它并选择 Live。您也可以使用远程日志流式传输,或从已通过身份验证的计算机运行此命令:

    cloudflared tail <TUNNEL_UUID>

    查找 connection refused、格式错误的 HTTP 响应、x509 错误和 TLS 握手错误。这些消息标识 cloudflared 与本地源站之间的故障,即使 Tunnel 状态仍为 Healthy。

有关协议详细信息,请参阅支持的 Tunnel 协议。有关所有源站设置,请参阅 Tunnel 源站参数。

这篇文档对您有帮助吗?