将 Public NAT 与 Compute Engine 搭配使用

本页面演示了一个 Public NAT 网关,该网关为 Compute Engine 虚拟机实例提供网络地址转换服务。在开始之前,请先阅读 Public NAT 概览

前提条件

在设置 Public NAT 之前,您需要执行以下操作。

获取 IAM 权限

通过 roles/compute.networkAdmin 角色,您有权在 Cloud Router 路由器上创建 NAT 网关、预留和分配 NAT IP 地址,以及指定哪些子网的流量应该使用 NAT 网关的网络地址转换。

设置 Google Cloud

开始之前,请先在 Google Cloud 中设置以下内容。

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Install the Google Cloud CLI.
  5. To initialize the gcloud CLI, run the following command:

    gcloud init
  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  7. Make sure that billing is enabled for your Google Cloud project.

  8. Install the Google Cloud CLI.
  9. To initialize the gcloud CLI, run the following command:

    gcloud init

示例

以下是一个端到端示例,演示了一个示例 Public NAT 网关和一个使用 Public NAT 网关的示例 Compute Engine 虚拟机。

第 1 步:创建 VPC 网络和子网

如果您已有网络和子网,则可以跳过此步骤。

控制台

  1. 在 Google Cloud 控制台中,转到 VPC 网络页面。

    转到“VPC 网络”页面

  2. 点击创建 VPC 网络

  3. 输入 custom-network1 作为名称

  4. 子网下,将子网创建模式设置为自定义

  5. 新子网下,输入 subnet-us-east-192 作为名称

  6. 地区中,选择 us-east4

  7. 输入 192.168.1.0/24 作为 IP 地址范围

  8. 点击完成,然后点击创建

gcloud

  1. 在项目中创建新的自定义模式 VPC 网络:

    gcloud compute networks create custom-network1 \
        --subnet-mode custom
  2. 为第一个地区指定子网前缀。在本例中,我们为地区 us-east4 分配了 192.168.1.0/24

    gcloud compute networks subnets create subnet-us-east-192 \
       --network custom-network1 \
       --region us-east4 \
       --range 192.168.1.0/24

Terraform

您可以使用 Terraform 模块创建自定义虚拟私有云 (VPC) 网络和子网。

module "test-vpc-module" {
  source       = "terraform-google-modules/network/google"
  version      = "~> 9.0"
  project_id   = var.project_id # Replace this with your project ID in quotes
  network_name = "custom-network1"
  mtu          = 1460

  subnets = [
    {
      subnet_name   = "subnet-us-east-192"
      subnet_ip     = "192.168.1.0/24"
      subnet_region = "us-east4"
    }
  ]
}

第 2 步:创建没有外部 IP 地址的虚拟机实例

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到“虚拟机实例”页面

  2. 点击创建实例

  3. 为您的实例指定 nat-test-1 作为名称

  4. 地区设置为 us-east4

  5. 区域设置为 us-east4-c

  6. 点击管理、安全、磁盘、网络、单独租用链接。

  7. 点击网络标签页。

  8. 网络接口下,点击虚拟机默认接口所对应的 修改

    1. 网络设置为 custom-network1
    2. 子网设置为 subnet-us-east-192
    3. 外部 IP 设置为 None
    4. 点击完成
  9. 要创建并启动该实例,请点击创建

gcloud

gcloud compute instances create nat-test-1 \
    --image-family debian-9 \
    --image-project debian-cloud \
    --network custom-network1 \
    --subnet subnet-us-east-192 \
    --zone us-east4-c \
    --no-address

Terraform

您可以使用 Terraform 资源创建虚拟机实例。

resource "google_compute_instance" "default" {
  project      = var.project_id
  zone         = "us-east4-c"
  name         = "nat-test-1"
  machine_type = "e2-medium"
  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-9"
    }
  }
  network_interface {
    network    = "custom-network1"
    subnetwork = var.subnet # Replace with a reference or self link to your subnet, in quotes
  }
}

第 3 步:创建一条允许 SSH 连接的防火墙规则

控制台

  1. 在 Google Cloud 控制台中,转到防火墙页面。

    转到“防火墙政策”页面

  2. 点击创建防火墙规则

  3. 输入 allow-ssh 作为名称

  4. 指定 custom-network1 作为网络

  5. 流量方向设置为入站

  6. 对匹配项执行的操作设置为允许

  7. 目标设置为网络中的所有实例

  8. 来源过滤条件设置为 IPv4 范围

  9. 来源 IP 地址范围设置为 35.235.240.0/20

  10. 协议和端口设置为指定的协议和端口

  11. 选中 tcp 复选框,然后输入端口 22

  12. 点击创建

gcloud

gcloud compute firewall-rules create allow-ssh \
    --network custom-network1 \
    --source-ranges 35.235.240.0/20 \
    --allow tcp:22

Terraform

您可以使用 Terraform 资源创建防火墙规则。

resource "google_compute_firewall" "rules" {
  project = var.project_id
  name    = "allow-ssh"
  network = var.network # Replace with a reference or self link to your network, in quotes

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }
  source_ranges = ["35.235.240.0/20"]
}

第 4 步:为您的测试实例创建 IAP SSH 权限

在稍后的步骤中,您将使用 Identity-Aware Proxy (IAP) 连接到您的测试实例。

控制台

  1. 在 Google Cloud 控制台中,转到 Identity-Aware Proxy 页面。

    转到 Identity-Aware Proxy 页面

  2. 选择 SSH 和 TCP 资源标签页。

  3. 要更新成员对资源的权限,请选中所有隧道资源 > us-east4-c > nat-test-1 旁边的复选框。

  4. 在右侧窗格中,点击添加成员

  5. 要向用户、群组或服务账号授予资源访问权限,请在新成员字段中指定其电子邮件地址。

    如果您只是测试此功能,则可以输入自己的电子邮件地址。

  6. 要通过 Cloud IAP 的 TCP 转发功能向成员授予资源访问权限,请在角色下拉列表中选择 Cloud IAP > 受 IAP 保护的隧道用户

  7. 点击保存

gcloud

此命令使用 IAP 向项目中的所有虚拟机实例授予 SSH 访问权限。如果要使用 IAP 向单个虚拟机授予 SSH 访问权限,请按照 Google Cloud 控制台说明操作。

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member=MEMBER_INFO \
    --role=roles/iap.tunnelResourceAccessor

替换以下内容:

  • PROJECT_ID:您的项目 ID
  • MEMBER_INFO:以英文逗号分隔的成员 type:email 对列表。示例:
    • 针对个人用户:user:test-user@example.com
    • 对于群组:group:admins@example.com
    • 对于服务账号:serviceAccount:test123@example.domain.com

Terraform

您可以使用 Terraform 资源为您的测试实例创建 IAP SSH 权限。

resource "google_project_iam_member" "project" {
  project = var.project_id
  role    = "roles/iap.tunnelResourceAccessor"
  member  = "serviceAccount:test123@example.domain.com"
}

第 5 步:登录到 nat-test-1 并确认其无法连接到互联网

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到“虚拟机实例”页面

  2. 对于 nat-test-1,请在连接列中,点击 SSH 下拉箭头,然后选择在浏览器窗口中打开

  3. 在虚拟机的命令提示符下,输入 curl example.com,然后按 Enter 键。

    您应该不会获得任何结果。否则,您可能使用外部 IP 地址创建了 nat-test-1,或者可能存在其他问题。如需排查问题,请参阅虚拟机无需 Cloud NAT 即可意外访问互联网

    如需结束该命令,您可能需要输入 Ctrl+C

gcloud

  1. 向本地主机添加 Compute Engine SSH 密钥:

    ssh-add ~/.ssh/google_compute_engine
    
  2. 连接到 nat-test-1 并运行命令:

    gcloud compute ssh nat-test-1 \
        --zone us-east4-c \
        --command "curl example.com" \
        --tunnel-through-iap

    您应该不会获得任何结果。否则,您可能使用外部 IP 地址创建了 nat-test-1,或者可能存在其他问题。如需排查问题,请参阅虚拟机无需 Cloud NAT 即可意外访问互联网

    如需结束该命令,您可能需要输入 Ctrl+C

第 6 步:使用 Cloud Router 创建 NAT 配置

您必须在与使用 Public NAT 的实例相同的区域中创建 Cloud Router 路由器。Cloud Router 路由器仅用于在虚拟机上放置 NAT 信息。它不是实际 NAT 网关的一部分。

此配置允许该地区中的所有实例将 Public NAT 用于所有主要和别名 IP 地址范围。此外,它还为 NAT 网关自动分配外部 IP 地址。如需了解更多选项,请参阅 Google Cloud CLI 文档。

控制台

  1. 在 Google Cloud 控制台中,转到 Cloud NAT 页面。

    转到“Cloud NAT”页面

  2. 点击开始使用创建 NAT 网关

  3. 输入 nat-config 作为网关名称

  4. VPC 网络设置为 custom-network1

  5. 地区设置为 us-east4

  6. Cloud Router 下,选择创建新路由器

    1. 输入 nat-router 作为名称
    2. 点击创建
  7. 点击创建

gcloud

  1. 创建 Cloud Router 路由器:

    gcloud compute routers create nat-router \
        --network custom-network1 \
        --region us-east4
  2. 向路由器添加配置:

    gcloud compute routers nats create nat-config \
        --router-region us-east4 \
        --router nat-router \
        --nat-all-subnet-ip-ranges \
        --auto-allocate-nat-external-ips

Terraform

您可以使用 Terraform 资源创建 Cloud Router 路由器。

resource "google_compute_router" "router" {
  project = var.project_id
  name    = "nat-router"
  network = var.network
  region  = "us-east4"
}

您可以使用 Terraform 模块创建 NAT 配置。

module "cloud-nat" {
  source  = "terraform-google-modules/cloud-nat/google"
  version = "~> 5.0"

  project_id                         = var.project_id
  region                             = "us-east4"
  router                             = google_compute_router.router.name
  name                               = "nat-config"
  source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}

第 7 步:尝试再次连接到互联网

NAT 配置最多可能需要 3 分钟才能传播到虚拟机,因此请至少等待一分钟再尝试访问互联网。

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到“虚拟机实例”页面

  2. 对于 nat-test-1,请在连接列中,点击 SSH 下拉箭头,然后选择在浏览器窗口中打开

  3. 在虚拟机的命令提示符下,输入 curl example.com,然后按 Enter 键。

gcloud

连接到 nat-test-1 并运行命令:

gcloud compute ssh nat-test-1 \
    --zone us-east4-c \
    --command "curl example.com" \
    --tunnel-through-iap

您会看到包含以下内容的输出:


<html>
<head>
<title>Example Domain</title>
...
...
...
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is established to be used for illustrative examples in documents. You can use this
    domain in examples without prior coordination or asking for permission.</p>
    <p><a href="http://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>

后续步骤