Tao
Tao

目录

使用 Cloudflare Zero Trust 保护 SSH 访问的使用指南

目录

在现代IT基础架构中,安全地访问服务器始终是企业面临的关键挑战。传统的SSH(Secure Shell)安全模型通常依赖于将SSH端口(默认为 22)暴露在公共互联网上,并通过防火墙规则、IP 白名单和 Fail2Ban等工具进行安全加固。然而,随着网络威胁的日益复杂化和攻击手段的不断演进,这种传统的边界防护模式正面临前所未有的挑战。本指南将深入探讨一种更现代、更安全的解决方案:利用Cloudflare Zero Trust 平台构建零信任架构来保护SSH访问。

从传统的边界安全模型转向零信任架构,代表了网络安全领域的一次范式转移。这种转变的核心思想是放弃"信任但验证"的模式,转而采用"从不信任,始终验证"的原则。

传统模型的核心是构建一个坚固的"城堡",保护内部资源。一旦攻击者通过了边界防御(例如,窃取了一个 SSH 密钥),他们通常会在网络内部获得过多的信任和移动自由。

相比之下,零信任SSH架构旨在让服务器对公共互联网完全"隐形",从而消除攻击面。它不依赖于网络位置来判断信任,而是对每一次访问请求都进行严格的身份验证和授权,无论请求来自何处。

应用于SSH访问,零信任的原则体现在以下几个方面:

  • 身份验证为先:在允许任何流量到达 SSH 服务器之前,必须先验证用户身份。
  • 最小权限访问:用户只被授予完成其工作所必需的最低权限。
  • 设备状态验证:访问决策不仅基于用户身份,还应考虑设备的健康状况和安全状态。
  • 全面日志记录和监控:所有访问活动和会话都应被记录和审计,以实现可见性和合规性。

Cloudflare的零信任SSH解决方案由三个核心组件协同工作,共同构成了强大的安全体系:

Cloudflare Tunnel (cloudflared):这是一个安装在源服务器(或同一局域网内的另一台机器)上的轻量级守护进程。它会主动与 Cloudflare 的全球网络建立一个持久的、仅出站的加密连接。由于连接是由内部发起并维持的,因此无需在防火墙上打开任何入站端口。这使得源服务器的 IP 地址可以完全不暴露于公网,从根本上消除了直接的网络攻击。

Cloudflare Access:这是策略执行引擎。管理员可以在 Cloudflare Zero Trust 仪表板中定义精细的访问策略,明确规定"谁"可以在"什么条件下"访问"哪些"资源。Cloudflare Access 与各种身份提供商(如 Google Workspace, Okta, Microsoft Entra ID)集成,并能够评估设备的安全状态(例如,是否加密磁盘、是否运行特定的安全软件),从而做出动态的、基于上下文的访问决策。

WARP 客户端:这是 Cloudflare 的设备客户端,安装在最终用户的设备(如笔记本电脑、手机)上。在推荐的"Access for Infrastructure"模型中,WARP 客户端将用户的设备安全地连接到 Cloudflare 网络,并将发往受保护私有资源的流量(包括 SSH)通过加密隧道进行路由。它使得用户可以像访问本地资源一样无缝地访问私有网络中的服务器,同时接受 Cloudflare Gateway 的安全策略检查。

采用 Cloudflare 的零信任模型来保护 SSH 访问,可以带来多项显著优势:

  • 消除暴露的端口:由于 cloudflared 建立的是出站连接,您的服务器防火墙可以阻止所有入站连接,极大地减少了攻击面。
  • 隐藏源服务器 IP:服务器的真实 IP 地址永远不会暴露在 DNS 记录或网络流量中,有效抵御了直接的 DDoS 攻击和恶意扫描。
  • 集中化策略执行:所有访问策略都在 Cloudflare Zero Trust 仪表板中统一管理,确保了策略的一致性,并为审计提供了清晰的记录。
  • 增强的身份验证:通过与企业现有的单点登录(SSO)系统集成,并强制执行多因素认证(MFA),极大地增强了身份验证的安全性。
  • 详细的会话日志:Cloudflare 能够记录每一次 SSH 连接的认证事件,甚至可以记录会话中的具体命令,为安全审计和事件响应提供了前所未有的可见性。

Cloudflare 提供了多种实现零信任 SSH 的架构,以适应不同的使用场景和安全需求。选择正确的架构是成功部署的第一步。以下表格对三种主要架构进行了详细比较,帮助您做出明智的决策。

特性 SSH with Access for Infrastructure (WARP-to-Tunnel) Browser-Rendered Terminal Client-Side cloudflared Proxy
主要用例 企业环境,保护公司管理的设备对私有网络的访问。 为承包商、第三方开发者或非技术用户提供快速、零安装的客户端访问。 为技术用户(如 DevOps 工程师)提供灵活的、通过本地终端访问的方式。
客户端要求 必须安装并注册 Cloudflare WARP 客户端。 任何现代 Web 浏览器。 必须在本地安装 cloudflared 二进制文件和标准的 SSH 客户端。
服务器端要求 cloudflared 隧道连接到一个私有网络(通过 IP/CIDR 定义)。 cloudflared 隧道配置了一个公共主机名,并启用了浏览器渲染。 cloudflared 隧道配置了一个公共主机名。
安全态势 最高。可结合设备状态检查,确保只有合规的公司设备才能连接。 高。依赖于强大的身份验证,但无法进行设备状态检查。 高。依赖于强大的身份验证,但安全性也依赖于客户端的正确配置。
用户体验 无缝。用户在本地终端中直接使用 ssh user@private_ip,体验与传统 SSH 完全相同。 简单。用户通过浏览器访问一个 URL 即可登录,无需任何本地配置。 需要一次性配置。用户需要在本地 ~/.ssh/config 文件中添加 ProxyCommand。
已知限制 需要在企业内部分发和管理 WARP 客户端。 存在"用户名不匹配"问题;不支持所有终端功能(如自定义字体/颜色)。 需要用户在本地安装和维护 cloudflared。

企业级统一设备管理环境:对于已建立完善设备管理体系(MDM/EMM)的企业组织,我们强烈推荐采用 SSH with Access for Infrastructure (WARP-to-Tunnel) 模型。这种架构代表了零信任安全的最高标准,其核心优势在于能够将访问控制决策与设备的实时安全状态紧密结合。系统可以动态评估设备的合规状态(包括磁盘加密状态、操作系统版本、安全补丁水平、企业域加入状态等),并据此实时调整访问权限,真正实现了"从不信任,始终验证"的零信任核心理念。

外部协作与临时访问场景:对于需要为承包商、第三方开发者或临时协作伙伴提供系统访问的场景,Browser-Rendered Terminal 无疑是最优解。这种方案的突出优势在于完全消除了软件分发和设备管理的复杂性——用户只需一个现代浏览器即可获得完整的 SSH 体验。这显著降低了准入门槛,减少了 IT 团队的管理负担,同时避免了在非企业管控设备上安装软件可能带来的安全风险。但在部署时需要特别关注"用户名映射"挑战:当前实现要求用户的 Cloudflare 身份标识(通常为 SSO 邮箱的用户名部分)与目标服务器上的 Unix 用户账户名称严格匹配,才能实现基于短期证书的无缝身份验证。

技术团队与开发运维场景:对于内部技术人员,特别是开发工程师和运维专家,Client-Side cloudflared Proxy 模型提供了理想的平衡点。这种架构充分尊重了技术用户对工具选择的自主性,允许他们继续使用经过精心配置的本地终端环境(如 iTerm2 with tmux、Windows Terminal with WSL、或带有丰富插件的 Vim/Emacs 工作流)。虽然初始配置需要修改 ~/.ssh/config 文件并设置 ProxyCommand,但这种一次性的投入对于具备技术背景的用户而言完全可以接受,且能够换来长期的高效工作体验和完整的本地工具链集成。

许多组织在考虑远程访问方案时,会在 Cloudflare Tunnel 和传统 VPN 之间进行权衡。虽然两者都能实现远程访问,但其底层哲学、安全模型和架构截然不同。

传统 VPN:通常需要在网络边界的防火墙上打开一个或多个入站端口(如 UDP 500/4500 for IPsec),并将网络的公共 IP 地址暴露给连接的客户端。这使得 VPN 网关本身成为了一个潜在的攻击目标,容易受到扫描和 DDoS 攻击。

Cloudflare Tunnel:如前所述,它通过出站连接工作,无需任何开放的入站端口。服务器的真实 IP 被完全隐藏在 Cloudflare 的网络之后,所有流量都由 Cloudflare 进行清洗,天然具备强大的 DDoS 防护能力。

这是一个至关重要的区别,直接关系到信任模型。

传统 VPN:提供真正的端到端加密。流量在客户端和 VPN 服务器之间形成一个加密隧道,理论上只有通信的两端可以解密和查看流量内容。这对于有严格数据隐私要求的场景至关重要。

Cloudflare Tunnel:在其架构中,Cloudflare 充当了一个可信的中间人(Proxy)。流量从客户端到 Cloudflare 边缘是加密的,从 Cloudflare 边缘到源服务器的隧道也是加密的。然而,在 Cloudflare 的边缘节点,流量可以被解密以进行安全检查,例如应用 Web 应用程序防火墙(WAF)规则、数据丢失防护(DLP)策略等。这是一个功能特性,但同时也意味着您将部分信任授予了 Cloudflare 来处理您的流量。

传统 VPN:一旦用户通过身份验证连接到 VPN,他们通常会获得对整个内部网络的访问权限,就像他们身处办公室一样。虽然可以通过防火墙规则进行限制,但实现精细的、基于应用的访问控制较为复杂。VPN 的优势在于其协议的通用性,可以透明地传输任何网络协议,如 SMB/CIFS 文件共享、RDP、打印协议等。

Cloudflare Tunnel:与 Cloudflare Access 结合使用时,可以实现极其精细的访问控制。您可以为每一个应用(例如,一个特定的 SSH 主机、一个内部网站)设置独立的访问策略。这种模式更符合零信任的最小权限原则。然而,标准 Tunnel 主要针对特定的 TCP 服务(如 SSH, RDP)和 HTTP/S 流量,对于需要广泛网络层访问的场景,可能需要更高级的解决方案,如 WARP Connector。

这种对比揭示了一个根本性的架构选择:服务暴露 (Service Exposure) vs. 网络扩展 (Network Extension)。VPN 的本质是网络扩展,它将远程用户置于私有网络的边界之内,延续了传统的"可信网络"概念。而 Cloudflare Tunnel 则是服务暴露的典范,它将内部网络中的特定服务安全地、有选择地暴露给经过验证的用户,而 Cloudflare 充当了智能且安全的访问代理。

选择 Tunnel 方案,意味着组织正在明确地向基于单个服务的零信任模型迈进,这在安全态势和管理复杂性上都与传统 VPN 有着深刻的区别。

本部分将提供在服务器上配置 Cloudflare 零信任 SSH 所需的详细、可操作的步骤,为后续的客户端访问打下坚实的基础。

cloudflared 是连接您的服务器与 Cloudflare 网络的桥梁。在目标 SSH 服务器或能够访问该服务器的同一网络中的另一台机器上安装此守护进程是第一步。

以下是针对主流操作系统的详细安装命令,整合了多种可靠来源的信息。

推荐使用官方仓库进行安装,以便于后续更新:

bash

# 添加 Cloudflare GPG 密钥
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

# 添加 Cloudflare apt 仓库
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main' | sudo tee /etc/apt/sources.list.d/cloudflared.list

# 更新包列表并安装
sudo apt-get update
sudo apt-get install cloudflared

或者,也可以手动下载 .deb 包进行安装:

bash

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

同样推荐使用仓库进行安装:

bash

sudo rpm --import https://pkg.cloudflare.com/cloudflare-main.gpg
sudo tee /etc/yum.repos.d/cloudflare.repo <<EOF
[cloudflare]
name=Cloudflare
baseurl=https://pkg.cloudflare.com/cloudflared/rpm
gpgcheck=1
gpgkey=https://pkg.cloudflare.com/cloudflare-main.gpg
enabled=1
EOF
sudo yum install cloudflared

注意:在像 Fedora Silverblue 这样的不可变操作系统上安装时,可能需要采用分层(layering)等特殊方法,并可能遇到符号链接相关的错误。

最简单的方法是使用 Homebrew:

bash

brew install cloudflared

可以从 Cloudflare 的发布页面下载最新的 .msi 安装程序或 .exe 二进制文件,并按照图形化界面或命令行指示进行安装。

Cloudflare 提供了官方的 Docker 镜像,非常适合容器化环境:

bash

docker pull cloudflare/cloudflared

安装完成后,需要对 cloudflared 进行认证,使其能够代表您的 Cloudflare 账户操作。在服务器的终端中运行以下命令:

bash

cloudflared tunnel login

该命令会生成一个 URL。将此 URL 复制并粘贴到本地计算机的浏览器中。浏览器将引导您登录 Cloudflare 账户,并请求授权。选择您希望该隧道关联的域名并批准。

成功授权后,cloudflared 会在服务器上下载一个名为 cert.pem 的证书文件。这个文件是守护进程与您的 Cloudflare 账户之间的信任凭证,通常存储在 ~/.cloudflared//etc/cloudflared/ 目录下。请妥善保管此文件。

为了确保隧道在服务器重启后能够自动运行并保持稳定,必须将其配置为系统服务。

systemd (Linux)

如果您是通过令牌(token)进行远程管理的隧道,安装服务非常简单:

bash

sudo cloudflared service install <YOUR_TUNNEL_TOKEN>

如果您是本地管理的隧道(使用 config.yml),则只需运行:

bash

sudo cloudflared service install

然后启用并启动服务:

bash

sudo systemctl enable cloudflared
sudo systemctl start cloudflared
# 检查服务状态
sudo systemctl status cloudflared

launchd (macOS) 和 Windows 服务:安装过程类似,cloudflared 提供了相应的服务管理命令。可以参考官方文档获取详细步骤。

隧道的创建和管理主要有两种模式:通过仪表板进行远程管理,或通过命令行和配置文件进行本地管理。选择哪种模式对后续的维护和自动化流程有重要影响。

这是最直观、最适合初学者的方法:

  1. 登录 Cloudflare Zero Trust 仪表板,导航至 Networks > Tunnels
  2. 点击 Create a tunnel
  3. 选择 Cloudflared 作为连接器类型,然后为隧道命名(例如 ssh-prod-server)。
  4. 保存隧道后,仪表板会显示一个安装命令,其中包含一个唯一的隧道令牌(token)。

bash

cloudflared service install <YOUR_TUNNEL_TOKEN>
  1. 在您的服务器上执行此命令。cloudflared 服务会使用这个令牌连接到 Cloudflare,并自动获取后续的所有配置。
  2. 之后,您可以在仪表板的 Public HostnamesPrivate Networks 选项卡中为该隧道配置路由规则。

这种方法更适合自动化和基础设施即代码(IaC)的工作流。

创建隧道

在服务器上运行命令:

bash

cloudflared tunnel create <TUNNEL_NAME>

此命令会返回一个隧道的 UUID,并在 ~/.cloudflared/ 目录下生成一个与该 UUID 对应的 JSON 凭证文件(例如 f9b4a...d3e.json)。

理解 config.yml 文件

这是本地管理的核心。您需要创建一个配置文件,通常位于 /etc/cloudflared/config.yml。一个典型的 config.yml 文件用于 SSH 访问的结构如下:

yaml

# 隧道的唯一标识符
tunnel: f9b4a1b1-0a43-47cf-b2af-97a3d906ad3e

# 指向隧道凭证文件的路径
credentials-file: /root/.cloudflared/f9b4a1b1-0a43-47cf-b2af-97a3d906ad3e.json

# Ingress 规则定义了流量如何从公共主机名路由到本地服务
ingress:
  # 规则一:将 ssh.yourdomain.com 的 SSH 流量转发到本地的 22 端口
  - hostname: ssh.yourdomain.com
    service: ssh://localhost:22

  # 规则二:将 web.yourdomain.com 的 HTTP 流量转发到本地的 8080 端口
  - hostname: web.yourdomain.com
    service: http://localhost:8080

  # 捕获所有规则(Catch-all rule):对于任何不匹配上述主机名的请求,返回 404 错误
  # 这是一个重要的安全实践,可以防止隧道意外暴露未配置的服务
  - service: http_status:404

配置完成后,将 cloudflared 作为服务运行,它将读取此文件来启动和配置隧道。

重要提示:一个常见的混淆点在于这两种管理模式的区别。当隧道是在仪表板中创建并使用令牌运行时(远程管理),cloudflared 守护进程会从 Cloudflare API 拉取其配置,并完全忽略本地的 config.yml 文件。许多用户在编辑本地 config.yml 后发现更改未生效,原因就在于此。相反,通过 CLI 创建的隧道(本地管理)则完全依赖于本地 config.yml 的内容。

因此,在项目开始时就必须明确选择一种管理模式并坚持使用。对于需要版本控制和自动化部署的环境,本地管理是更优的选择;而对于简单的手动设置,远程管理则更为便捷。明确这一点可以避免大量的排错时间和精力。

最后一步是配置 SSH 服务器本身,使其能够与 Cloudflare Access 的高级功能(如短时证书)协同工作。

在进行任何 Cloudflare 集成之前,建议遵循 SSH 的基本安全最佳实践,例如在 /etc/ssh/sshd_config 文件中禁用密码登录:

ssh

PasswordAuthentication no
PermitRootLogin no

这是 Cloudflare 推荐的最安全的 SSH 认证方式,它用动态生成的、生命周期极短的证书取代了传统的、静态的 SSH 公钥。

生成并放置 CA 公钥

  1. 在 Cloudflare Zero Trust 仪表板中,导航至 Access > Service Auth
  2. SSH 标签页下,为您的 SSH 应用生成一个证书。仪表板将显示一个公钥。
  3. 复制此公钥。
  4. 在您的 SSH 服务器上,将此公钥粘贴到 /etc/ssh/ca.pub 文件中。您可能需要 sudo 权限:

bash

sudo nano /etc/ssh/ca.pub

配置 sshd_config

编辑 SSH 守护进程的配置文件 /etc/ssh/sshd_config。添加或确保以下两行存在且未被注释。这两行告诉 SSHD 启用公钥认证,并信任由 /etc/ssh/ca.pub 中指定的证书颁发机构(即 Cloudflare)签名的任何证书:

ssh

PubkeyAuthentication yes
TrustedUserCAKeys /etc/ssh/ca.pub

处理不同的用户名

在某些情况下,用户登录 Cloudflare 的身份(如 [email protected])可能与他们在服务器上的 Unix 用户名(如 jdoeadmin)不同。为了处理这种情况,sshd_config 提供了 AuthorizedPrincipalsCommandAuthorizedPrincipalsFile 指令。这允许您定义一个命令或文件,用于将传入证书中的"principal"(即 Cloudflare 用户身份)映射到服务器上允许登录的本地用户。这是一个高级配置,但对于解决社区中反复出现的用户名不匹配问题至关重要。

重启并验证

保存对 sshd_config 的更改后,必须重启 SSH 服务以使配置生效:

bash

# 对于 Debian/Ubuntu
sudo systemctl restart ssh
# 对于 RHEL/CentOS
sudo systemctl restart sshd

使用 systemctl status sshd 检查服务是否正常运行。

完成这些服务器端步骤后,您的 SSH 服务器就已经准备好通过 Cloudflare 的零信任架构进行安全访问了。

服务器端基础搭建完成后,下一步是配置最终用户的设备,使他们能够通过 Cloudflare 安全地连接到 SSH 服务器。本部分将详细介绍三种主流的客户端访问方法。

这是 Cloudflare 官方为企业环境推荐的旗舰模型,提供了最高级别的安全性和最无缝的用户体验。

此模型的核心前提是,所有需要访问 SSH 服务器的用户设备上都必须安装 Cloudflare WARP 客户端,并且该客户端必须注册到您组织的 Zero Trust 账户中。这通常通过 MDM/UEM 解决方案在企业内部进行批量部署和管理。

这是配置此模型时最关键且最容易被忽略的一步。默认情况下,为了避免干扰用户对本地网络资源(如打印机、NAS)的访问,WARP 客户端会排除对私有 IP 地址范围(RFC 1918,如 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)的流量捕获。

然而,您的 SSH 服务器很可能就位于这些私有网段中。因此,您必须在 Zero Trust 仪表板的 Settings > WARP Client > Device settings 中配置 Split Tunnels 规则,明确地将您的 SSH 服务器所在的 IP 地址或 CIDR 网段包含在 WARP 的流量路由范围内。

例如,如果您的服务器 IP 是 10.1.2.3,您需要添加一条规则,将 10.1.2.0/24 或更具体的 10.1.2.3/32 加入到 Include 列表中。只有这样,当用户尝试 SSH 连接到该 IP 时,流量才会被 WARP 客户端拦截并发送到 Cloudflare 网络进行策略评估和路由。

此模型的最大优点在于其对最终用户的透明性。一旦管理员完成了所有后台配置,用户的体验将与传统 SSH 完全一样。他们只需打开自己喜欢的终端应用程序,输入熟悉的命令:

bash

ssh <username>@<private-ip-of-server>

无需任何特殊的代理命令或复杂的客户端配置。WARP 客户端在后台默默地处理了所有的认证和流量代理工作,用户对此毫无感知。这极大地降低了用户的学习成本和操作阻力。

对于不希望或无法使用 WARP 客户端的技术用户,此方法允许他们继续使用原生 SSH 客户端,同时享受 Cloudflare Access 带来的安全优势。

此方法要求用户在自己的本地计算机(Windows, macOS, or Linux)上安装 cloudflared 二进制文件。安装方法与服务器端相同。

所有魔法都发生在用户的 SSH 客户端配置文件 ~/.ssh/config 中。通过配置 ProxyCommand,可以指示 SSH 客户端在连接特定主机时,首先通过 cloudflared 程序来建立连接。

对于简单的、不使用短时证书的认证,配置如下:

ssh

Host ssh.yourdomain.com
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h

这里,ssh.yourdomain.com 是您在 Cloudflare Tunnel 中配置的公共主机名。ProxyCommand 指定了当 ssh ssh.yourdomain.com 命令被调用时,实际执行的命令。%h 是一个占位符,会被替换为目标主机名(即 ssh.yourdomain.com)。您需要将 /usr/local/bin/cloudflared 替换为 cloudflared 在您系统上的实际路径。

当使用最安全的短时证书认证时,配置会稍微复杂一些,因为 cloudflared 需要先生成证书,然后再建立代理连接:

ssh

Host ssh.yourdomain.com
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
  IdentityFile ~/.cloudflared/%h-cf_key
  CertificateFile ~/.cloudflared/%h-cf_key-cert.pub

更健壮的配置方式是使用 Match exec,它会在连接前执行一个命令来生成证书,确保证书总是最新的:

ssh

Match host ssh.yourdomain.com exec "/usr/local/bin/cloudflared access ssh-gen --hostname %h"
  ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
  IdentityFile ~/.cloudflared/%h-cf_key

当用户执行 ssh [email protected] 时,SSH 客户端会首先执行 cloudflared access ssh-gen,这个过程会触发浏览器进行 Cloudflare Access 登录认证。认证成功后,cloudflared 会生成一个短时证书和对应的私钥,并保存在 ~/.cloudflared/ 目录下。随后,ProxyCommand 会使用这个刚刚生成的证书通过 Cloudflare 网络代理 SSH 连接。

许多用户遇到的"浏览器能用,命令行失败"的问题,其根本原因就在于缺少或错误配置了 ProxyCommand。标准的 SSH 客户端本身无法理解 OAuth, SAML, OIDC 等现代 Web 认证流程。cloudflared access ssh 命令在这里扮演了一个认证垫片 (Authentication Shim) 的角色。它拦截了本地 SSH 客户端的连接请求,将其"翻译"成 Cloudflare Access 能理解的、基于浏览器的认证流程,获取认证令牌(JWT),然后再建立实际的代理连接。理解了 cloudflared 的这个双重角色——既是代理又是认证桥梁——是排查此类问题的关键。

此方法为用户提供了最简单的访问体验,无需在本地安装任何客户端软件,只需一个浏览器即可。

配置非常简单。在 Zero Trust 仪表板中,找到对应的 Access 应用,进入其设置,在 Additional settings 下找到 Browser rendering,并将其设置为 SSH

用户只需在浏览器中访问您为 SSH 服务配置的公共主机名(例如 https://ssh.yourdomain.com)。页面会自动跳转到 Cloudflare Access 的登录界面。用户通过其身份提供商(如输入邮箱获取一次性密码,或通过 Google/Okta SSO)完成认证后,一个功能齐全的终端界面将直接在浏览器窗口中渲染出来,用户可以立即开始工作。

然而,这种看似完美的方法存在一个重要的缺陷,即**“用户名不匹配"的认证流程问题**。社区中有大量关于此问题的讨论。其根本原因在于浏览器终端的认证逻辑:它首先通过 Cloudflare Access 完成对用户身份(例如 [email protected])的认证,并为该身份的邮箱前缀(jane.doe)获取一个短时证书。然后,它使用这个固定的用户名 jane.doe 去尝试 SSH 登录服务器。

如果服务器上实际需要的用户名是 jdoeadmin,那么这次基于证书的登录尝试就会失败。失败后,浏览器终端会退而求其次,提示用户手动输入用户名和密码/密钥,这完全违背了使用短时证书进行无缝登录的初衷。

相比之下,CLI (ProxyCommand) 方法之所以能成功处理不同的用户名,是因为用户在执行 ssh [email protected] 时,就已经在认证流程开始之前提供了最终的目标用户名 admin,cloudflared 可以将这个目标用户名信息包含在证书请求中。

因此,在当前阶段,浏览器渲染的终端只有在用户的 Cloudflare 身份邮箱前缀与服务器上的 Unix 用户名完全一致时,才能提供真正无缝的体验。这是在选择架构时必须考虑的一个关键限制因素。

成功建立连接通道后,下一步是利用 Cloudflare Access 的强大功能来精炼访问控制,实现真正的零信任。

Cloudflare Access 的核心是其灵活的策略构建器。管理员可以组合多种规则来定义谁可以访问什么。

策略由一个动作 (Action)(如 Allow, Block, Bypass)和一组规则 (Rules) 构成。规则的逻辑关系如下:

  • Include (OR):定义了有资格访问的初始用户池。用户只需满足多个 Include 规则中的任意一个即可。
  • Exclude (NOT):用于从 Include 定义的用户池中排除特定用户或群体。任何满足 Exclude 规则的用户都将被拒绝访问。
  • Require (AND):在 Include 规则的基础上增加额外的必须满足的条件。用户必须同时满足所有 Require 规则才能获得访问权限。

选择器是构建规则的具体条件。Cloudflare 提供了丰富的选择器,可以分为几大类:

身份 (Identity):这是最基本的选择器,例如:

  • Emails(特定邮箱地址)
  • Emails ending in(特定域名下的所有邮箱)
  • Identity provider group(来自 SSO 提供商的用户组,如 Okta 或 Google Workspace 中的用户组)

设备状态 (Device Posture):这是实现最高安全级别访问的关键。通过与 WARP 客户端集成,您可以设置 Require 规则,强制要求用户设备必须满足特定条件才能连接,例如:

  • Require WARP(必须通过 WARP 连接)
  • Disk encryption(磁盘必须加密)
  • Domain joined(设备必须加入公司域)
  • Firewall(防火墙必须开启)等

上下文 (Context):基于连接时的环境信息,例如:

  • Country(限制来自特定国家/地区的访问)
  • IP ranges(限制来自特定 IP 地址段的访问)
  • Authentication Method(要求用户必须通过 MFA 认证)

了解策略的执行顺序至关重要。Cloudflare Access 会首先评估 Bypass 和 Service Auth 类型的策略。如果没有匹配项,它会接着从上到下评估 Allow 和 Block 策略。一旦用户的请求匹配了某条 Allow 或 Block 策略,评估就会停止,并执行相应的动作。

将 Cloudflare Access 与您组织现有的身份提供商(IdP)集成,是实现单点登录和集中化身份管理的关键。

Google Workspace 是许多企业使用的核心身份系统。将其与 Cloudflare Access 集成,可以利用现有的用户和群组信息来控制 SSH 访问。以下是集成过程的概览:

在 Google Cloud Platform (GCP) 中配置

  1. 创建一个新的 GCP 项目或使用现有项目。
  2. 启用 Admin SDK API,这是 Cloudflare 获取群组信息所必需的。
  3. 配置 OAuth 同意屏幕,设置应用名称,并选择"内部"用户类型。
  4. 创建一个 OAuth 2.0 客户端 ID,类型为"Web 应用”。
  5. 在"授权重定向 URI"中,添加您的 Cloudflare team domain 回调 URL (https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback)。
  6. 记录下生成的客户端 ID 和客户端密钥。

在 Cloudflare Zero Trust 仪表板中配置

  1. 导航至 Settings > Authentication,添加一个新的登录方法,选择 Google Workspace
  2. 输入从 GCP 获取的客户端 ID 和客户端密钥,以及您的 Google Workspace 域名。
  3. 保存后,Cloudflare 会生成一个授权链接。您(或您的 Google Workspace 管理员)必须访问此链接,以授予 Cloudflare 读取用户和群组信息的权限。

在 Access 策略中使用

完成集成后,您就可以在 Access 策略的 Include 或 Require 规则中,使用 Identity provider group 选择器,并直接选择从 Google Workspace 同步过来的用户组。这使得权限管理变得异常简单:只需在 Google Workspace 中添加或移除用户组成员,其 SSH 访问权限就会自动更新。

对于其他支持标准协议的 IdP(如 Okta, Microsoft Entra ID, Auth0),集成过程遵循类似的模式。您需要在 IdP 端创建一个新的应用,并配置相关的元数据,如实体 ID (Entity ID)、断言消费者服务 (ACS) URL 等。然后将这些信息以及应用的客户端 ID/密钥填入 Cloudflare 的通用 SAML 或 OIDC 连接器配置中。

在任何 Access 策略中,您都可以添加一条 Require 规则,将 Authentication Method 选择器设置为 mfa。这会确保只有在 IdP 端成功完成了多因素认证的用户,才能通过该策略的评估,从而为敏感的 SSH 访问增加了一道至关重要的安全防线。

短时证书是 Cloudflare 零信任 SSH 方案中最具变革性的安全特性之一。它彻底改变了传统 SSH 密钥管理的模式。

传统的 SSH 认证依赖于在服务器的 ~/.ssh/authorized_keys 文件中分发和管理静态的公钥。这带来了巨大的运维负担和安全风险:密钥容易泄露,员工离职后忘记移除密钥会导致权限残留,密钥轮换难以执行。一个被盗的 SSH 密钥可能会提供长期的、不受监控的访问权限。

短时证书机制则完全不同。它将信任的根基从分散的、静态的密钥转移到了一个集中的、动态的证书颁发机构(CA),即 Cloudflare Access。服务器端不再需要管理成百上千个个人公钥,它只需要信任一个公钥——Cloudflare 的 CA 公钥。

整个认证流程体现了动态授权的核心思想:

  1. 用户发起连接:用户通过 WARP 或 cloudflared 客户端发起 SSH 连接请求。
  2. Cloudflare Access 认证:请求被重定向到 Cloudflare Access 进行身份验证。用户通过 SSO 和 MFA 证明自己的身份。
  3. 策略评估:Cloudflare Access 评估预设的策略,检查用户身份、设备状态等是否满足要求。
  4. 证书签发:如果策略评估通过,Cloudflare 的 CA 会动态地为该用户、针对该次会话签发一个 SSH 证书。这个证书的有效期极短,通常只有几分钟(例如 3 分钟)。
  5. 证书传递与验证:cloudflared 客户端将这个短时证书传递给目标 SSH 服务器。
  6. 服务器验证:SSH 服务器收到证书后,会检查其签名。由于服务器信任 Cloudflare 的 CA(通过预置的 ca.pub 文件),它会确认签名有效,并检查证书中的 principal 是否是被允许登录的用户。
  7. 授予访问:验证通过后,SSH 会话建立。

这个模型的巨大优势在于,它消除了所有与静态 SSH 密钥管理相关的难题。访问权限是动态授予的,并且与用户的实时身份和设备状态紧密绑定。即使证书被截获,它也很快就会失效,极大地降低了风险。这是一种从根本上更安全的访问控制模式。

由于所有 SSH 连接都通过 Cloudflare 的代理,平台能够提供无与伦比的可见性。管理员可以审计每一次登录尝试(无论成功与否),并且通过启用 Gateway 的 SSH 命令日志记录功能,还可以记录用户在会话中执行的每一条命令。这对于满足合规性要求(如 SOC 2, ISO 27001)和进行安全事件调查至关重要。

即使是设计良好的系统,在实际部署中也可能遇到问题。本部分旨在提供常见问题的诊断思路和解决方案,帮助您快速定位并解决问题。

问题:cloudflared 日志中反复出现 Failed to create new quic connection 或类似的 timeout 错误。

原因:这是最常见的隧道连接问题之一。cloudflared 默认使用 QUIC 协议(基于 UDP)与 Cloudflare 边缘节点通信,通常使用 UDP 端口 7844。如果服务器所在网络的出站防火墙阻止了此端口,连接就会失败。

解决方案

  • 首选方案:请求网络管理员允许服务器对外的 UDP 7844 端口通信。
  • 备用方案:如果无法开放 UDP 端口,可以强制 cloudflared 使用基于 TCP 的 HTTP/2 协议。编辑 cloudflared 的 systemd 服务文件 (/etc/systemd/system/cloudflared.service),在 ExecStart 行的 cloudflared 命令后添加 --protocol http2 参数,然后重载并重启服务。

service

ExecStart=/usr/bin/cloudflared --protocol http2 --config /etc/cloudflared/config.yml tunnel run

问题:在 config.yml 中添加或修改了 ingress 规则,但没有生效。访问新的主机名返回 404 或其他错误。

诊断

  • 语法检查:在服务器上使用 cloudflared tunnel ingress validate 命令可以检查 config.yml 文件的语法是否正确。
  • 配置文件路径:这是一个非常隐蔽但常见的错误。当 cloudflared 作为服务运行时,它通常读取位于 /etc/cloudflared/config.yml 的配置文件。而用户在手动测试时,可能编辑的是位于 ~/.cloudflared/config.yml 的文件。这两个文件路径不同,导致服务使用的配置并未更新。请确保您修改的是服务正在使用的那个配置文件。
  • 管理模式混淆:再次强调,如果您的隧道是远程管理的(通过令牌运行),它会忽略本地的 config.yml。所有 ingress 规则都必须在 Zero Trust 仪表板中进行配置。请确认您的隧道管理模式。

问题:可以通过浏览器渲染的终端访问 SSH,但使用本地终端 ssh [email protected] 时连接超时或失败。

原因:这个问题的根源 99% 在于客户端的 ~/.ssh/config 文件没有配置,或者配置不正确。如前文所述,原生 SSH 客户端需要 cloudflared 作为 ProxyCommand 来处理 Cloudflare Access 的认证流程。

解决方案

  1. 确认 cloudflared 已安装:确保在客户端机器上已经安装了 cloudflared。
  2. 检查 ~/.ssh/config:打开该文件,确保有针对您的 SSH 主机的正确条目。
  3. 路径问题:ProxyCommand 中指定的 cloudflared 路径是否正确?在 Windows 上,路径应为 C:\\path\\to\\cloudflared.exe
  4. 主机名匹配:Host 指令中的主机名是否与您尝试连接的名称完全匹配?
  5. 详细日志:使用 ssh -v [email protected] 命令进行连接。-v (verbose) 参数会打印出详细的调试信息,您可以从中看到 ProxyCommand 是否被正确执行,以及 cloudflared 在哪个阶段失败。

问题:使用浏览器终端时,如果服务器上的 Unix 用户名与 Cloudflare 身份的邮箱前缀不一致,无法通过短时证书自动登录,而是被要求输入密码或密钥。

原因:这是当前浏览器渲染终端的一个已知设计限制。其认证流程是固定的,总是使用邮箱前缀作为目标用户名。

解决方案

  1. 对齐用户名(推荐):如果可能,最简单的解决方法是调整服务器上的 Unix 用户名,使其与用户的邮箱前缀一致。
  2. 使用其他方法:如果无法对齐用户名,对于这些特定用户,应避免使用浏览器渲染终端,而是指导他们使用配置了 ProxyCommand 的本地 CLI 方法,因为 CLI 方法可以正确处理不同的用户名。
  3. 关注社区:Cloudflare 社区中有多个关于此问题的讨论帖。可以关注这些帖子以获取官方的最新进展或解决方案。

问题:登录 Cloudflare Access 后,浏览器终端页面显示错误或无法加载。

原因

  • 不支持的策略:浏览器渲染不支持 Bypass 或 Service Auth 类型的 Access 策略。请检查您的应用策略,确保只使用了 Allow 或 Block。
  • 隧道或服务器问题:确保后端的 cloudflared 隧道处于健康(Healthy)状态,并且 SSH 服务器本身正在正常运行。
  • 网络问题:虽然少见,但客户端的网络问题或浏览器插件也可能干扰 WebSocket 连接,从而导致渲染失败。可以尝试在浏览器的无痕模式下访问。

通过采用 Cloudflare Zero Trust 平台来保护 SSH 访问,组织能够从根本上提升其基础设施的安全防护水平。这种方法将传统的、基于边界防御的被动安全模型,转变为一种主动的、以身份为核心的零信任架构。

其核心优势体现在以下几个方面:

攻击面的彻底消除:通过 Cloudflare Tunnel,SSH 服务器不再需要暴露在公共互联网上,从而彻底消除了来自外部网络的直接扫描和攻击风险。这是一个从"加固城门"到"让城堡隐形"的本质飞跃。

动态且精细的访问控制:Cloudflare Access 将每一次 SSH 连接都置于严格的策略审查之下。访问决策不再依赖于静态的 IP 地址或共享密钥,而是基于用户的实时身份、设备的安全状态以及多因素认证等丰富的上下文信息,真正实现了最小权限原则的精神内核。

认证模式的革命性升级:用动态生成的、生命周期极短的 SSH 证书取代静态的、难以管理的 SSH 密钥,是该方案最具变革性的特征。这不仅极大地降低了因密钥泄露而导致的安全风险,也从根本上解决了密钥轮换和生命周期管理的运维痛点。

在实施过程中,选择适合的架构模式至关重要。WARP-to-Tunnel 模型为企业环境提供了最全面、最无缝的安全保障;浏览器渲染终端为临时访问场景带来了极大的便利性,但需要注意其在用户名处理上的当前限制;而客户端 cloudflared 代理则为技术用户保留了原生终端的灵活性和强大功能。

虽然部署过程涉及服务器、客户端和云平台的协同配置,并可能遇到特定的技术挑战,但通过严格遵循本文中详述的步骤和故障排查指南,任何组织都能够成功地将其 SSH 访问体系升级到现代化的零信任安全标准,为企业的数字化转型奠定坚实的安全基础。

相关内容