使用 IAP 保护虚拟机

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

IAP TCP 转发允许您建立加密隧道,通过该隧道可以将 SSH、RDP 和其他流量转发到 VM 实例。IAP TCP 转发还提供了对哪些用户可以建立隧道和用户可以与哪些虚拟机实例连接的精细控制。

如需了解有关 IAP TCP 转发如何工作的更多信息,请参阅 TCP 转发概览

准备您的项目进行 IAP TCP 转发

本部分将引导您通过必要步骤在 Google Cloud 项目中启用 IAP TCP 转发。

创建防火墙规则

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

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

控制台

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

  1. 打开“防火墙规则”页面。

    打开“防火墙规则”页面

    其余步骤将自动显示在 Google Cloud 控制台中。

  2. 选择 Google Cloud 项目。 点击查看
  3. 在“防火墙规则”页面上,点击创建防火墙规则
  4. 配置以下设置:
    • 名称allow-ingress-from-iap
    • 流量方向入站
    • 目标网络中的所有实例
    • 来源过滤条件IP 地址范围
    • 来源 IP 地址范围35.235.240.0/20
    • 协议和端口:选择 TCP,然后输入 22,3389 以允许 RDP 和 SSH。
  5. 点击创建

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) 角色。

下表显示了您需要授予可信管理员以执行 TCP 转发和相关任务的预定义角色:

任务 角色 更多信息
TCP 转发 受 IAP 保护的隧道用户 (roles/iap.tunnelResourceAccessor) 请参阅授予对项目中所有虚拟机实例的访问权限授予对特定虚拟机的访问权限
通过 SSH 访问 Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1)
OS Login(推荐) 各种 请参阅 为用户帐号配置 OS Login 角色
使用服务账号 Service Account User (roles/iam.serviceAccountUser) 请参阅 serviceAccountUser 角色

如果您要创建仅具有此任务所需特定权限的自定义角色,请参阅权限详细信息

您可以向用户或群组授予对项目中所有虚拟机实例的访问权限,也可以授予对特定虚拟机的访问权限,具体取决于您授予所需角色的方式。

授予对项目中所有虚拟机实例的访问权限

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

控制台

  1. 在 Google Cloud 控制台中打开 IAM 和管理页面。

    打开“IAM 和管理员”页面

    其余步骤将自动显示在 Google Cloud 控制台中。

  2. IAM 和管理页面上,点击添加并配置以下内容:
    • 新主账号:指定您要为其授予访问权限的用户或群组。
    • 选择角色:选择 Cloud IAP > IAP-Secured Tunnel User
  3. (可选)点击添加条件并配置条件:
    • 标题:输入条件的名称。
    • 表达式:输入用户必须满足才能获取 IAP-Secured Tunnel User 角色提供的权限的条件

    例如,以下 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

授予对特定虚拟机的访问权限

如需向用户或群组授予对特定虚拟机的访问权限,您需要授予该虚拟机的 roles/iap.tunnelResourceAccessor 角色。必须针对项目授予其他角色。

控制台

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

    打开 BeyondCorp Enterprise 管理页面

    其余步骤将自动显示在 Google Cloud 控制台中。

  2. 在 IAP 管理页面的 SSH 和 TCP 资源标签页上,选择您要配置的虚拟机实例。
  3. 如果信息面板未显示,请点击显示信息面板
  4. 点击添加主账号并配置以下各项:

    • 新主账号:指定您要为其授予访问权限的用户或群组。
    • 选择角色:选择 Cloud IAP > IAP-Secured Tunnel User
  5. (可选)点击添加条件并配置条件:

    • 标题:输入条件的名称。
    • 表达式:输入用户必须满足才能获取 IAP-Secured Tunnel User 角色提供的权限的条件

    例如,以下 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. 导出以下变量。

    export IAP_BASE_URL=https://iap.googleapis.com/v1/projects/PROJECT_NUMBER/iap_tunnel
    # Replace POLICY_FILE.JSON with the name of JSON file to use for setIamPolicy
    export JSON_NEW_POLICY=POLICY_FILE.JSON
    

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

    curl -i -H "Authorization: Bearer $(gcloud auth print-access-token)" \
         ${IAP_BASE_URL}/zones/ZONE_NAME/instances/INSTANCE_ID or INSTANCE_NAME:getIamPolicy \
         -d ''

  3. 通过修改 IAM 政策 JSON 文件向主帐号授予 iap.tunnelResourceAccessor 角色。

  4. (可选)根据 IAM 条件访问权限级别,仅向满足特定条件的主帐号授予该角色。

    以下是经过修改的 policy.json 文件的示例,该文件向一组虚拟机实例管理员授予 iap.tunnelResourceAccessor 角色,使他们能够访问受 BeyondCorp Enterprise 保护的隧道资源。已添加 IAM 条件,以使用 destination.ipdestination.port IAM 条件使资源仅供虚拟机实例管理员组中专用 IP 地址为 10.0.0.1 且端口为 10.0.0.1 的主账号访问。22它们还必须满足 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
    
  5. 使用 setIamPolicy 方法设置新的 policy.json 文件。

    curl -i -H "Content-Type:application/json" \
              -H "Authorization: Bearer $(gcloud auth print-access-token)" \
              ${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 代理会连接到虚拟机上的主要内部 IPv4 地址 nic0

控制台

如需连接到您的实例,请使用 Google Cloud 控制台中的 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 桌面

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

  1. 在应用中,依次选择文件 > 添加 Google Cloud 项目

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

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

IAP 桌面

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

PuTTY 应用

您可以设置 PuTTY Windows 终端模拟器应用,使其使用 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. 配置以下代理设置:

    • 对于 Proxy type,选择 Local
    • Telnet command, or local proxy command 字段中,输入以下内容:

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

      替换以下内容:

      • PROJECT_ID:虚拟机实例所在项目的项目 ID
      • ZONE:虚拟机实例所在的可用区
    • 对于 Print proxy diagnostics in the terminal window,选择 Only until session starts

  3. 选择类别 Connection > SSH > Auth

  4. 点击 Browse 并粘贴以下文件名,然后点击 Open

    %USERPROFILE%\.ssh\google_compute_engine.ppk
    
  5. 选择类别 Session

  6. 配置以下代理设置:

    • Host name (or IP address) 字段中,输入以下内容:

      USERNAME@INSTANCE_NAME
      

      替换以下内容:

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

  7. 点击保存

  8. 点击 Open 以启动 SSH 会话。

SSH

您可以直接将 ssh 命令与使用 gcloud 启动隧道的 ProxyCommand 选项搭配使用。使用以下命令生成完整的 ssh 命令:

gcloud compute ssh INSTANCE_NAME --dry-run

通过隧道传输 RDP 连接

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

IAP 桌面

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

  1. 在应用中,依次选择文件 > 添加 Google Cloud 项目

  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 连接

您可以使用 gcloud compute start-iap-tunnel 命令分配本地端口,以将 IAP TCP 转发功能用于其他基于 TCP 的协议。该本地端口会将来自本地机器的数据流量以 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 上传带宽,请考虑在安装了 gcloud CLI 的同一台机器上安装 NumPy。

Linux

如需在 Unix 平台中使用 pip 安装 NumPy,请在新的终端实例中运行以下命令:

$(gcloud info --format="value(basic.python_location)") -m pip install numpy
如需了解详情,请参阅:NumPy.org

如果安装 NumPy 后错误消息仍然存在,请完成以下步骤: 运行以下命令以允许 gcloud 访问外部软件包:

export CLOUDSDK_PYTHON_SITEPACKAGES=1

Windows

如需在 Windows 平台中使用 pip 安装 NumPy,请在新的 PowerShell 实例中运行以下命令:

start (gcloud info --format="value(basic.python_location)") "-m pip install numpy"
如需了解详情,请参阅:NumPy.org

如果安装 NumPy 后消息仍然存在,则需要执行另一个步骤。运行以下命令以允许 gcloud 访问外部软件包:

$env:CLOUDSDK_PYTHON_SITEPACKAGES="1"

已知限制

带宽:IAP TCP 转发功能并非为批量转移数据而设计。IAP 保留对滥用此项服务的用户施加速率限制的权利。

连接时长:IAP 会在闲置一小时后自动断开会话。目前,如果隧道断开连接,gcloud compute start-iap-tunnel 会尝试重新建立隧道。

后续步骤