使用 IAP 保护虚拟机

本页面介绍如何使用 Identity-Aware Proxy (IAP) TCP 转发功能对没有外部 IP 地址或不允许通过互联网直接访问的虚拟机实例进行管理员权限。

IAP TCP 转发允许您建立加密隧道,通过该隧道,您可以将 SSH、RDP 和其他流量转发到虚拟机实例。IAP TCP 转发还可让您精确地控制允许哪些用户建立隧道以及允许用户连接哪些虚拟机实例。

如需详细了解 IAP TCP 转发的工作原理,请参阅 TCP 转发概览

准备项目以使用 IAP TCP 转发

本部分逐步介绍了在 Google Cloud 项目中启用 IAP TCP 转发所需的步骤。

创建防火墙规则

如需允许 IAP 连接到您的虚拟机实例,请创建一条防火墙规则:

  • 适用于您希望使用 IAP 访问的所有虚拟机实例。
  • 允许来自 IP 范围 35.235.240.0/20 的入站流量。此范围包含 IAP 用于 TCP 转发的所有 IP 地址。
  • 允许连接到您想使用 IAP TCP 转发功能访问的所有端口,例如用于 SSH 的端口 22 和用于 RDP 的端口 3389

控制台

如需允许 RDP 和 SSH 访问网络中的所有虚拟机实例,请执行以下操作:

  • 打开“防火墙规则”页面,然后点击创建防火墙规则

    打开“防火墙规则”页面

  • 配置以下设置:

    • 名称allow-ingress-from-iap
    • 流量方向入站
    • 目标网络中的所有实例
    • 来源过滤条件IP 地址范围
    • 来源 IP 地址范围35.235.240.0/20
    • 协议和端口:选择 TCP 并输入 22,3389 以允许 RDP 和 SSH。
  • 点击创建

gcloud

如需允许 RDP 访问网络中的所有虚拟机实例,请运行以下命令:

gcloud compute firewall-rules create allow-rdp-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:3389 \
  --source-ranges=35.235.240.0/20

对于 SSH 访问权限,请运行以下命令:

gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:22 \
  --source-ranges=35.235.240.0/20

对于其他协议,请运行以下命令:

gcloud compute firewall-rules create allow-ingress-from-iap \
  --direction=INGRESS \
  --action=allow \
  --rules=tcp:PORT \
  --source-ranges=35.235.240.0/20

其中,PORT 是协议使用的端口。

授予使用 IAP TCP 转发的权限

如需控制哪些用户和组可以使用 IAP TCP 转发以及它们可以连接到哪些虚拟机实例,请配置 Identity and Access Management (IAM) 权限。

我们建议您为可信管理员授予以下所有角色:

此外,如果您使用的是 OS Login(推荐),请参阅在用户帐号上配置 OS Login 角色。 如果您使用的是服务帐号,请参阅这些说明,了解如何设置 serviceAccountUser 角色。

您可以通过在项目级层配置 IAM 权限,向用户或群组授予访问项目中的所有虚拟机实例的权限:

控制台

  1. 在 Cloud Console 中打开 IAM 和管理页面。

    打开“IAM 和管理”页面

  2. 点击添加并配置以下内容:

    • 新成员:指定要授予访问权限的用户或组。
    • 选择角色:选择 Cloud IAP > 受 IAP 保护的隧道用户
  3. (可选)点击添加条件并配置成员限制:

    • 标题:输入限制的名称。
    • 表达式:输入一个条件,用户只有在满足该条件后才能使用 IAP 进行 TCP 转发。

    例如,以下 CEL 表达式限制访问端口 22:

    destination.port == 22
    

    您还可以按访问权限级别限制访问权限:

    destination.port == 22 && "FULL_ACCESS_LEVEL_NAME" in request.auth.access_levels
    

    其中,FULL_ACCESS_LEVEL_NAME 是现有的访问权限级别,使用 accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME 格式。

  4. 点击添加其他角色并配置以下内容:

    • 选择角色 选择 Compute Engine &Compute Instance Admin (v1)
  5. 点击保存

gcloud

通过运行以下命令向用户授予两个角色:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=user:EMAIL \
    --role=roles/iap.tunnelResourceAccessor
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=user:EMAIL \
    --role=roles/compute.instanceAdmin.v1

替换以下内容:

  • PROJECT_ID:项目的 ID
  • EMAIL:您要授予访问权限的用户的电子邮件地址,例如 user@example.com

如果需要,您可以改为按虚拟机配置 iap.tunnelResourceAccessor 角色(其他角色必须位于项目中):

控制台

  1. 打开 IAP 管理页面,选择 SSH 和 TCP 资源标签页。

    打开 BeyondCorp Enterprise 管理页面

  2. 选择要配置的虚拟机实例。
  3. 如果系统未显示信息面板,请点击显示信息面板
  4. 点击添加成员并配置以下内容:

    • 新成员:指定要授予访问权限的用户或组。
    • 选择角色:选择 Cloud IAP > 受 IAP 保护的隧道用户
  5. (可选)点击添加条件并配置成员限制:

    • 标题:输入限制的名称。
    • 表达式:输入一个条件,用户只有在满足该条件后才能使用 IAP 进行 TCP 转发。

    例如,以下 CEL 表达式限制访问端口 22:

    destination.port == 22
    

    您还可以按访问权限级别限制访问权限:

    destination.port == 22 && "FULL_ACCESS_LEVEL_NAME" in request.auth.access_levels
    

    其中,FULL_ACCESS_LEVEL_NAME 是现有的访问权限级别,使用 accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME 格式。

  6. 点击保存

API

如需修改应用的 policy.json 文件,请按照以下过程操作。 如需详细了解如何使用 IAM API 管理访问权限政策,请参阅管理对 BeyondCorp Enterprise 保护的资源的访问权限

  1. 下载服务帐号的凭据文件。

    1. 转到“服务帐号”页面
      转到“服务帐号”页面

    2. 点击您的服务帐号的电子邮件地址。

    3. 点击修改

    4. 点击创建密钥

    5. 选择 JSON 作为密钥类型。

    6. 点击创建并关闭显示的确认窗口,以创建新密钥。

    您的 JSON 凭据文件现已下载完毕。

  2. 导出以下变量。

    export IAP_BASE_URL=https://iap.googleapis.com/v1/projects/PROJECT_NUMBER/iap_tunnel
    # Replace with the path to your local service account's downloaded JSON file
    export JSON_CREDS=EXAMPLE.IAM.GSERVICEACCOUNT.COM.JSON
    # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy
    export JSON_NEW_POLICY=POLICY_FILE.JSON
    

  3. 运行以下命令,使用 Oauth2l 将服务帐号凭据 JSON 文件转换为 OAuth 访问令牌:

    oauth2l header --json ${JSON_CREDS} cloud-platform

  4. 如果这是您第一次运行上述命令,请在出现提示时执行以下操作:

    1. 点击显示的链接并复制验证码,以获取验证码。
    2. 将验证码粘贴到您的应用提示中。
    3. 复制返回的不记名令牌。
    4. 导出分配给返回的不记名令牌值的新变量。
      export CLOUD_OAUTH_TOKEN=AUTHORIZATION_BEARER_TOKEN
  5. 如果您之前运行过此命令,请导出以下变量。

    export CLOUD_OAUTH_TOKEN="$(oauth2l header --json ${JSON_CREDS} cloud-platform)"

  6. 使用 getIamPolicy 方法获取 Compute Engine 实例的 IAM 政策。末尾的空数据位表示将 curl 请求转换为 POST,而不是 GET。

    curl -i -H "${CLOUD_OAUTH_TOKEN}" \
         ${IAP_BASE_URL}/zones/ZONE_NAME/instances/INSTANCE_ID or INSTANCE_NAME:getIamPolicy \
         -d ''

  7. 通过修改 IAM 政策 JSON 文件向您的成员授予 iap.tunnelResourceAccessor 角色。

  8. (可选)根据 IAM Conditions访问权限级别添加成员限制。

    以下是一个经过修改的 policy.json 文件示例,该文件将 iap.tunnelResourceAccessor 角色绑定到一组虚拟机实例管理员,并授予他们对 BeyondCorp Enterprise 保护的隧道资源的访问权限。新增了一项 IAM 条件,以便使用 destination.ipdestination.port IAM Conditions 使虚拟机实例管理员群组中的成员在端口 22 上具有专用 IP 地址 10.0.0.1 的成员可以访问资源。它们还必须符合 ACCESS_LEVEL_NAME 访问权限级别的要求。

    请注意,如果成员具有 Owner 角色,则他们有权使用 IAP 进行 TCP 转发。


    policy.json 文件示例

    {
      "policy": {
        "bindings": [
          {
            "role": "roles/iap.tunnelResourceAccessor",
            "members": ["group:instance-admins@example.com"],
            "condition": {
              "expression": "\"accessPolicies/POLICY_NAME/accessLevels/ACCESS_LEVEL_NAME\" in request.auth.access_levels && destination.ip == \"10.0.0.1\" && destination.port == 22",
              "title": "CONDITION_NAME"
            }
          }
        ]
      }
    }

    如需查找政策名称,请调用 accessPolicies.list

    GET https://accesscontextmanager.googleapis.com/v1/accessPolicies
    
  9. 使用 setIamPolicy 方法设置新的 policy.json 文件。

    curl -i -H "Content-Type:application/json" \
              -H "$(oauth2l header --json ${JSON_CREDS} cloud-platform)" \
              ${IAP_BASE_URL}/zones/ZONE_NAME/instances/INSTANCE_ID or INSTANCE_NAME:setIamPolicy \
              -d @${JSON_NEW_POLICY}
    

权限详情

所需权限会因用户将使用 IAP TCP 转发的方式而异:

场景 所需权限
全部
  • iap.tunnelInstances.accessViaIAP
使用 gcloud compute [start-iap-tunnel, ssh, scp]
  • compute.instances.get
  • compute.instances.list
使用 gcloud compute [ssh, scp]
  • compute.projects.get
使用 OS Login 的虚拟机 请参阅这些说明
不使用 OS Login
  • compute.instances.setMetadata
  • compute.projects.setCommonInstanceMetadata
  • compute.globalOperations.get
使用服务帐号通过 SSH 连接到虚拟机
  • iam.serviceAccounts.actAs
通过浏览器进行 SSH 连接 请参阅这些说明

例如,如果用户希望使用 gcloud compute ssh 连接到未使用 OS Login 但使用服务帐号的虚拟机,则该用户需要以下权限:

  • iap.tunnelInstances.accessViaIAP
  • compute.instances.get
  • compute.instances.list
  • compute.projects.get
  • compute.instances.setMetadata
  • compute.projects.setCommonInstanceMetadata
  • compute.globalOperations.get
  • iam.serviceAccounts.actAs

建立 SSH 连接隧道

您可以通过 IAP 建立 SSH 流量隧道,以连接到没有外部 IP 地址的 Linux 实例。

使用 IAP 隧道时,IAP 代理将连接到虚拟机上 nic0 的主要内部 IPv4 地址。

控制台

如需连接到您的实例,请使用 Cloud Console 中的 SSH 按钮。您的实例的访问配置(通过 IAM 权限定义)必须允许通过 IAP 建立 TCP 隧道。

gcloud

如需连接到您的实例,请使用 gcloud compute ssh 命令。您的实例的访问配置(通过 IAM 权限定义)必须允许通过 IAP 建立 TCP 隧道。

gcloud compute ssh INSTANCE_NAME

INSTANCE_NAME 替换为要通过 SSH 连接的实例的名称。

如果实例没有外部 IP 地址,则连接会自动使用 IAP TCP 隧道。如果实例具有外部 IP 地址,则连接会使用外部 IP 地址,而非 IAP TCP 隧道。

您可以使用 --tunnel-through-iap 标志,使 gcloud compute ssh 始终使用 IAP TCP 隧道。

使用 --internal-ip 标志,使 gcloud compute ssh 绝不会使用 IAP TCP 隧道,而是直接连接到虚拟机的内部 IP。这样做对于连接到目标虚拟机所在 VPC 网络的客户端非常有用。

IAP 桌面

您可以使用 IAP 桌面通过 SSH 和 IAP TCP 转发功能连接到虚拟机实例。

  1. 在应用中,选择 File > Add Google Cloud project

  2. 输入项目的 ID 或名称,然后点击确定

  3. Project Explorer 窗口中,右键点击要连接的虚拟机实例,然后选择连接

IAP 桌面

如需详细了解 IAP 桌面,请参阅 GitHub 项目页面

PuTTY 键盘

您可以设置 PuTTY 以使用 IAP TCP 转发连接到虚拟机实例。您的实例的访问配置(通过 IAM 权限定义)必须允许通过 IAP 建立 TCP 隧道。

在配置 PuTTY 之前,请使用 gcloud compute ssh 命令确保您本地计算机上具有 SSH 私钥,并且您的 SSH 公钥已发布到 Compute Engine:

  1. 打开命令提示符并运行以下命令,以连接到虚拟机实例:

    gcloud compute ssh INSTANCE_NAME `
      --tunnel-through-iap `
      --project PROJECT_ID `
      --zone ZONE
    

    替换以下内容:

    • INSTANCE_NAME:要连接的实例的名称
    • PROJECT_ID:虚拟机实例所在项目的 ID
    • ZONE:虚拟机实例所在的地区

    如有必要,请按 Y 确认您希望生成 SSH 密钥。

  2. 在虚拟机上,通过运行以下命令确定您的用户名:

    whoami
    

    您稍后需要使用此用户名。

您现在可以将 PuTTY 配置为使用 IAP TCP 转发:

  1. 打开 PuTTY 并选择类别连接 &代理
  2. 配置以下代理设置:

    • 对于代理类型,选择本地
    • Telnet 命令或本地代理命令字段中,输入以下内容:

      gcloud.cmd compute start-iap-tunnel %host %port --listen-on-stdin --project PROJECT_ID --zone ZONE
      

      替换以下内容:

      • PROJECT_ID:虚拟机实例所在项目的 ID
      • ZONE:虚拟机实例所在的区域
    • 对于在终端窗口中打印代理诊断,选择仅在会话开始前

  3. 选择 Connection 类别 SSH &gt Auth

  4. 点击浏览并粘贴以下文件名,然后点击打开

    %USERPROFILE%\.ssh\google_compute_engine.ppk
    
  5. 选择会话类别。

  6. 配置以下代理设置:

    • 主机名(或 IP 地址)字段中,输入以下内容:

      USERNAME@INSTANCE_NAME
      

      替换以下内容:

      • USERNAME:您之前确定的 Linux 用户名
      • INSTANCE_NAME:要连接的虚拟机实例的名称
    • 已保存的会话:输入会话的名称。

  7. 点击保存

  8. 点击打开以启动 SSH 会话。

建立 RDP 连接

您可以通过 IAP 建立 RDP 流量隧道,以连接到没有外部 IP 地址的 Windows 实例:

IAP 桌面

您可以使用 IAP 桌面通过 IAP TCP 转发功能连接到一个或多个虚拟机实例的远程桌面。

  1. 在应用中,选择 File > Add Google Cloud project

  2. 输入项目的 ID 或名称,然后点击确定

  3. Project Explorer 窗口中,右键点击要连接的虚拟机实例,然后选择连接

IAP 桌面

如需详细了解 IAP 桌面,请参阅 GitHub 项目页面

gcloud

如需连接到虚拟机实例的远程桌面,请先创建隧道。

  1. 使用 gcloud compute start-iap-tunnel 命令创建到虚拟机实例 RDP 端口的加密隧道。

    gcloud compute start-iap-tunnel INSTANCE_NAME 3389 \
        --local-host-port=localhost:LOCAL_PORT \
        --zone=ZONE
    

    INSTANCE_NAME 替换为您要连接的虚拟机实例的名称。将 LOCAL_PORT 替换为您希望绑定代理的 localhost 端口,或使用 0 自动选择未使用的代理。将 ZONE 替换为虚拟机实例所在的区域。

  2. gcloud 会对虚拟机实例执行连接测试,然后打开隧道并显示端口号。

    Listening on port [LOCAL_PORT].
    

    发送到 localhost:LOCAL_PORT 的所有流量都会转发到虚拟机实例。该端口只能供本地计算机上运行的应用访问。

  3. gcloud 保持运行状态,然后打开 Microsoft Windows 远程桌面连接应用。

  4. 输入隧道端点作为计算机名称:

    localhost:LOCAL_PORT
    

    LOCAL_PORT 替换为 gcloud 打开隧道时显示的端口号。

  5. 点击连接

建立其他 TCP 连接隧道

您可以将 IAP TCP 转发用于其他基于 TCP 的协议,方法是使用 gcloud compute start-iap-tunnel 命令来分配本地端口。本地端口通过 HTTPS 数据流将来自本地机器的数据流量隧道到远程机器。然后,IAP 会接收数据、应用访问权限控制,并将未封装的数据转发到远程端口。相反,来自远程端口的所有数据也会在发送到本地端口之前进行封装,然后该端口会解封装。

gcloud

创建指向虚拟机实例端口的加密隧道:

gcloud compute start-iap-tunnel INSTANCE_NAME INSTANCE_PORT \
    --local-host-port=localhost:LOCAL_PORT \
    --zone=ZONE

INSTANCE_NAMEINSTANCE_PORT 替换为您要连接的虚拟机实例的名称和端口。将 LOCAL_PORT 替换为您希望绑定代理的 localhost 端口。将 ZONE 替换为虚拟机实例所在的区域。

gcloud 会对虚拟机实例执行连接测试,然后打开隧道并显示端口号。

Listening on port [LOCAL_PORT].

发送到 localhost:LOCAL_PORT 的所有流量都将转发到虚拟机实例。该端口只能供本地计算机上运行的应用访问。

增加 IAP TCP 上传带宽

要增加 IAP TCP 上传带宽,请考虑安装 NumPy。 有关安装 NumPy 的说明,请参阅 NumPy.org

gcloud

运行以下命令以允许 gcloud 访问外部软件包:

export CLOUDSDK_PYTHON_SITEPACKAGES=1.

已知限制

带宽:IAP 的转发功能不适用于批量传输数据。IAP 保留对滥用此服务的用户施加速率限制的权利。

连接时长:IAP 会在处于非活跃状态 1 小时后自动断开会话。我们建议在应用中设置逻辑,以便在隧道断开连接时处理其重新建立隧道。

后续步骤