跳转到内容
搜索文档

使用自助管理 SSH 密钥进行连接

最后更新 查看 MarkdownAgent 设置

如果您想自己管理 SSH 密钥,可以使用 Cloudflare Tunnel 从服务器到 Cloudflare 的全球网络创建安全的、仅出站的连接。这需要在服务器(或私有网络内的任何其他主机)上运行 cloudflared 守护进程。拥有被 SSH 服务器信任的 SSH 密钥的用户,可以通过在其设备上安装 Cloudflare One Client 并加入您的 Zero Trust 组织来访问该服务器。用户可以直接 SSH 到服务器的私有主机名(例如,ssh.internal.local)。您可以使用网络级 Gateway 策略来控制对服务器的访问,而不是使用应用级的 Access 策略。

前提条件

1. 创建一个示例 SSH 服务器

本示例将逐步介绍如何在 Google Cloud Platform (GCP) 虚拟机 (VM) 上设置 SSH 服务器,但您可以使用任何支持 SSH 连接的机器。如果您已经配置了 SSH 服务器,可以跳到步骤 2

1.1 创建 SSH 密钥对

在创建 VM 实例之前,您需要创建一个 SSH 密钥对。

  1. 打开终端并输入以下命令:

    ssh-keygen -t rsa -f ~/.ssh/gcp_ssh -C <username in GCP>
  2. 出现提示时输入您的密码短语。需要输入两次。

    将生成两个文件:包含私钥的 gcp_ssh 和包含公钥的 gcp_ssh.pub

  3. 在命令行中输入:

    cat ~/.ssh/gcp_ssh.pub
  4. 复制输出。在 GCP 中创建 VM 实例时将使用此内容。

1.2 在 GCP 中创建 VM 实例

既然已创建 SSH 密钥对,您就可以创建 VM 实例了。

  1. 在您的 Google Cloud 控制台中,创建一个新项目
  2. 转到 Compute Engine(计算引擎)> VM instances(VM 实例)
  3. 选择 Create instance(创建实例)
  4. 命名您的 VM 实例,例如 ssh-server
  5. 向下滚动到 Advanced options(高级选项) > Security(安全) > Manage access(管理访问)
  6. SSH Keys (manually generated)(手动生成的 SSH 密钥) 下,选择 Add item(添加项) 并粘贴您创建的公钥。
  7. 选择 Create(创建)
  8. 您的 VM 实例运行后,打开 SSH 旁的下拉菜单并选择 Open in browser window(在浏览器窗口中打开)

2. 将服务器连接到 Cloudflare

本节介绍如何为您的 SSH 服务器创建新的 Cloudflare Tunnel。您可以为可通过 cloudflared 主机访问的私有网络上的所有服务重复使用相同的隧道。

  1. 登录 Cloudflare 仪表板,转到 Networking(网络) > Tunnels(隧道)

    Go to Tunnels ↗
  2. 选择 Create a tunnel(创建隧道)

  3. 为您的隧道输入名称。我们建议选择能够反映您希望通过此隧道连接的资源类型的名称(例如,enterprise-VPC-01)。

  4. 选择 Create Tunnel(创建隧道)

  5. 选择您的操作系统,然后复制安装命令并在您的源服务器的终端上运行。

  6. 等待隧道连接。连接建立后,选择 Continue(继续)

3. 使用主机名路由

主机名路由允许您直接 SSH 到 ssh.internal.local,而无需管理静态 IP 路由。当您的 SSH 服务器具有未知或临时 IP 地址(例如由云提供商配置的动态基础设施)时,主机名路由特别有用。

主机名路由的工作原理

当您在 Cloudflare Tunnel 中创建主机名路由时:

  1. 用户 SSH 到您的私有主机名(例如,ssh [email protected])。
  2. Gateway 将主机名解析为来自 CGNAT 范围的 初始解析 IP
  3. 流量通过 WARP 隧道路由到 Cloudflare。
  4. Gateway 网络策略评估该连接。
  5. Cloudflared 将连接代理到您的 SSH 服务器的私有 IP。

如果您没有配置私有 DNS 解析器,或者更愿意 SSH 到 IP 地址,请跳至步骤 4

3.1 添加主机名路由

要将主机名路由添加到您的隧道:

  1. 转到 Networking(网络) > **Tunnels(隧道)**并选择您的隧道。

  2. 在 **Routes(路由)**选项卡上,选择 Add route(添加路由),然后选择 Private hostname(私有主机名)

  3. 输入您的 SSH 服务器的主机名(例如,ssh.internal.local)。

    主机名格式限制

    • 字符限制:必须少于 255 个字符。
    • 支持的通配符:允许使用单个通配符(*),且它必须代表一个完整的 DNS 标签。 示例:*.internal.local
    • 不支持的通配符:不支持以下通配符格式:
      • 部分通配符,例如 *-dev.internal.localdev-*.internal.local
      • 中间的通配符,例如 foo*bar.internal.localfoo.*.internal.local
      • 主机名中的多个通配符,例如 *.*.internal.local
    • 通配符修剪:前导通配符(*)会被修剪掉,并假定有一个隐式的点(.)。例如,*.internal.local 会保存为 internal.local,但会匹配通配符级别的所有子域名(涵盖 foo.internal.local,但不涵盖 foo.bar.internal.local)。
    • 点修剪:允许前导点和尾随点(.),但会被修剪掉。
  4. 选择 Save(保存)

3.2 配置 DNS 解析

当 Gateway 收到针对您的私有主机名的请求时,它必须将该主机名解析为您的 SSH 服务器的私有 IP 地址。

场景 A:使用系统解析器(默认)

默认情况下,cloudflared 使用在其主机上配置的私有 DNS 解析器(例如,Linux 中的 /etc/resolv.conf)。如果运行 cloudflared 的机器已经可以使用本地系统解析器将 ssh.internal.local 解析为其私有 IP,则无需进一步配置。您可以跳到步骤 3.3

验证本地 DNS 解析

要检查 cloudflared 是否可以成功解析 ssh.internal.local,请从 cloudflared 主机运行以下命令:

nslookup ssh.internal.local
Server:		127.0.2.2
Address:	127.0.2.2#53

Non-authoritative answer:
Name:	ssh.internal.local
Address: 10.2.0.3

输出应包含服务器的私有 IP 地址(GCP VM 的内网 IP)。如果主机名解析失败:

  • 确保您的私有 DNS 解析器具有将 ssh.internal.local 指向服务器私有 IP 的记录。
  • 在 GCP 中,您可能需要将私有区域添加到 Cloud DNS,以便使用您的私有 DNS resolver 解析 internal.local

场景 B:使用特定的私有 DNS 服务器(高级)

如果您需要 cloudflared 使用与主机默认解析器不同的特定内部 DNS 服务器,您必须通过 IP/CIDR 路由将该 DNS 服务器显式连接到 Cloudflare。您还需要配置 Gateway 解析器策略以将查询路由到该特定专用 DNS 服务器。

  1. 要为 DNS 服务器创建 IP/CIDR 路由:

    1. 转到 Networking(网络) > Routes(路由)

      Go to Routes ↗
    2. 选择 Add CIDR route(添加 CIDR 路由)

    3. 输入您内部 DNS 解析器的私有 IP 地址。

    4. 选择连接到该 DNS 服务器所在网络的 Cloudflare Tunnel。

    5. 选择 Create(创建)

  2. 要创建解析器策略:

    1. 转到 Traffic policies(流量策略) > Resolver policies
    2. 选择 Create a policy(创建策略)
    3. 创建匹配私有主机名的表达式:
      选择器运算符
      Hostinssh.internal.local
    4. Configure custom DNS resolvers 下,输入您内部 DNS 服务器的私有 IP 地址。
    5. 从下拉菜单中,选择 - Private 路由选项以及分配给您在上一步中选择的隧道的虚拟网络
    6. 选择 Create a policy(创建策略)

3.3 配置 Cloudflare One Client

要连接到 私有主机名,必须配置 Cloudflare One Client 以将以下流量转发到 Cloudflare:

  • 初始解析的 IP(CGNAT 范围:100.64.0.0/10
  • 针对您的私有主机名的 DNS 查询

3.3.1 配置 Split Tunnels

在您的 WARP 设备配置文件中,配置分流隧道(Split Tunnels),使 初始解析的 IP 通过 WARP 隧道进行路由。配置取决于您的分流隧道模式

  • 排除模式:从您的分流隧道列表中删除 100.64.0.0/10。我们建议重新添加未明确用于 Cloudflare One 服务的 IP 范围。这可以减少与可能使用 CGNAT 地址空间的现有私有网络配置发生冲突的风险。
  • 包含模式:为以下 IP 地址添加分流隧道条目:
    • IPv4: 100.80.0.0/16
    • IPv6: 2606:4700:0cf1:4000::/64

3.3.2 配置 Local Domain Fallback

Local Domain Fallback 中,删除您私有主机名的顶级域名。这将配置 WARP 将 DNS 查询发送到 Cloudflare Gateway 进行解析。

例如,如果您的 SSH 主机名是 ssh.internal.local,请从 Local Domain Fallback 中移除 internal.local

4. (可选)使用 IP 路由

4.1 添加 IP 路由

要使用其 IP 地址(而不是主机名)连接到 SSH 服务器,请添加 CIDR 路由,其中包含服务器的私有 IP 地址。

4.2 配置 Cloudflare One Client

默认情况下,WARP 会排除发往 RFC 1918 地址空间的流量,这些 IP 地址通常用于私有网络,且无法从互联网访问。为了让 Cloudflare One Client 向您的 private network 发送流量,您必须配置分流隧道(Split Tunnels),以便将您的 private network 的 IP/CIDR 路由通过 Cloudflare One Client。

  1. 首先,检查您的分流隧道模式是设置为**Exclude(排除)还是Include(包含)**模式。

  2. 根据该模式编辑您的分流隧道路由:

    如果您使用的是**Exclude(排除)**模式:

    a. 删除包含您的 private network 的 IP/CIDR 范围的路由。例如,如果您的网络使用默认 AWS 范围 172.31.0.0/16,请删除 172.16.0.0/12

    b. 重新添加您的 private network 没有明确使用的 IP/CIDR 范围。对于上述 AWS 示例,您需要为 172.16.0.0/13172.24.0.0/14172.28.0.0/15172.30.0.0/16 添加新条目。这可确保只有发往 172.31.0.0/16 的流量通过 Cloudflare One Client 进行路由。

    您可以使用以下计算器来确定要重新添加的 IP 地址:

    计算器说明

    1. Base CIDR 中,输入您从分流隧道中删除的 RFC 1918 范围。
    2. Subtracted CIDRs 中,输入您的 private network 所使用的 IP/CIDR 范围。
    3. 将计算器结果重新添加到您的分流隧道“排除”模式列表中。

    通过缩小 Cloudflare One Client 中包含的私有 IP 范围,您可以降低破坏用户访问本地资源的风险。

    如果您使用的是**Include(包含)**模式:

    1. 将所需的 Zero Trust 域IP 地址添加到您的分流隧道“包含”列表中。
    2. 添加一条路由以包含您的 private network 的 IP/CIDR 范围。

5. (可选)创建 Gateway 网络策略

默认情况下,加入您组织的所有设备都可以 SSH 到该服务器,除非您构建 Gateway 网络策略来允许或阻止特定用户。您可以根据用户身份、设备安全状况、位置和其他标准创建策略。

  1. 转到 Traffic policies(流量策略)> Traffic settings(流量设置)
  2. 在 **Proxy and inspection(代理和检查)**中,开启 Allow Secure Web Gateway to proxy traffic(允许 Secure Web Gateway 代理流量)
  3. 选择 TCP
  4. 选择 UDP(将流量代理到内部 DNS 解析器所必需)
  5. (推荐)要代理 pingtraceroute 等诊断工具的流量,请选择 ICMP。您可能还需要更新您的系统以允许 ICMP 流量通过 cloudflared
  1. 向您的 cloudflare_api_token 添加以下权限:

    • Zero Trust Write
  2. 使用 cloudflare_zero_trust_device_settings 资源启用 TCP 和/或 UDP 代理:

    resource "cloudflare_zero_trust_device_settings "global_warp_settings" {
    	account_id            = var.cloudflare_account_id
      gateway_proxy_enabled = true
    	gateway_udp_proxy_enabled = true
    }

Cloudflare 现在将代理来自注册设备的流量,但在您的 Split Tunnel 设置中排除的流量除外。有关 Gateway 如何转发流量的更多信息,请参阅 Gateway 代理

示例策略

以下示例包含两个策略:第一个策略允许特定用户访问您的 SSH 服务器,第二个策略阻止所有其他流量。

策略 1:允许授权用户

  1. 转到 Traffic policies(流量策略)> Firewall policies(防火墙策略)> Network(网络)

  2. 选择 Create a policy(创建策略)

  3. 命名您的策略(例如,Allow SSH to internal server)。

  4. 创建一个表达式以匹配您的 SSH 主机名和授权用户:

    选择器 运算符
    SNI(服务器名称指示) in ssh.internal.local
    User Email(用户电子邮件) in [email protected], [email protected]
  5. 在 **Action(操作)**中,选择 Allow(允许)

  6. 选择 Create policy(创建策略)

策略 2:兜底阻止策略

为防止 Cloudflare One Client 用户访问您的整个私有网络,我们建议为您的私有 IP 空间创建一个兜底 Gateway 阻止策略。然后,您可以在此基础上叠加更高优先级的允许策略(在 Access 或 Gateway 中),以授予用户对特定应用程序或 IP 的访问权限。

通过 DNS 策略提供额外安全性

为了获得额外的保护层,请创建 Gateway DNS 策略来控制 DNS 解析:

  1. 转到 Traffic policies(流量策略)> Firewall Policies(防火墙策略)> DNS(DNS)

  2. 选择 Create a policy(创建策略)

  3. 命名您的策略(例如,Allow SSH hostname resolution)。

  4. 创建一个表达式:

    选择器 运算符
    Host(主机) in ssh.internal.local
    User Email(用户电子邮件) in [email protected], [email protected]
  5. 在 **Action(操作)**中,选择 Allow(允许)

  6. 选择 Create policy(创建策略)

6. 作为用户进行连接

设置好隧道路由和用户设备后,用户现在可以 SSH 到该机器。如果您的 SSH 服务器需要 SSH 密钥,则应在 SSH 命令中包含该密钥。

ssh -i ~/.ssh/gcp_ssh <username>@ssh.internal.local

Cloudflare One Client 必须连接到您的 Zero Trust 组织。如果用户符合您创建的 Gateway 网络策略,他们将能够连接。

故障排除

如果无法连接,请确认以下内容:

  1. 确认 DNS 解析 - 从设备确认您可以成功解析私有主机名:

    nslookup ssh.internal.local
    Server:		127.0.2.2
    Address:	127.0.2.2#53
    
    Non-authoritative answer:
    Name:	ssh.internal.local
    Address: 100.80.200.48

    该查询应使用 WARP 的 DNS 代理进行解析,并返回 Gateway 初始解析 IP。如果查询解析失败或返回了不同的 IP,请检查您的 Local Domain Fallback 配置和 Gateway 解析器策略

  2. 检查 Gateway 日志 - 审查您的 Gateway 网络日志以查看连接是否被策略阻止。

  3. 验证隧道状态 - 通过检查隧道状态来确认您的隧道健康且已连接。

  4. 测试到初始解析 IP 的连接性 - 当您使用私有主机名连接到 SSH 服务器时,设备应建立到 初始解析 IP 的连接:

    ssh -v <username>@ssh.internal.local
    ...
    Authenticated to ssh.internal.local ([100.80.200.48]:22) using "publickey".
    ...

    查找显示连接到 100.64.0.0/10 范围内 IP 的行。如果请求失败,请确认初始解析 IP 通过 WARP 隧道路由。您也可以检查隧道日志以确认请求正路由到服务器的私有 IP。

这篇文档对您有帮助吗?