在 Compute Engine 上部署 Active Directory 林

Last reviewed 2024-07-11 UTC

本文档介绍了如何按照在 Google Cloud 上运行 Active Directory 的最佳实践中所述的最佳实践在 Compute Engine 上部署 Active Directory 林。

本指南适用于管理员和 DevOps 工程师。它假定您熟悉 Active Directory,并且基本了解 Google Cloud 网络和安全性。

架构

部署包含两个项目:

通过此架构,您可以执行以下操作:

  • 在单独的项目中部署其他 Windows 工作负载,使它们可以使用共享 VPC 网络和 Active Directory 林。
  • 将 Active Directory 林与现有本地林集成,以实现资源林模式

准备工作

如需按照本指南中的说明进行操作,请确保您满足以下条件:

  • 两个子网的子网 CIDR 范围:

    • 域控制器子网。此子网包含域控制器。为域控制器使用专用子网有助于您在管理防火墙规则或分析网络日志时区分域控制器流量与其他服务器流量。

      我们建议使用大小为 /28/29 的子网 CIDR 范围。

    • 资源子网。此子网包含服务器和管理工作站。请使用足以容纳您计划部署的所有服务器的子网 CIDR 范围。

    确保您的子网不与任何本地子网重叠,并留出足够的增长空间。

  • Active Directory 林根域的 DNS 域名和 NetBIOS 域名。如需详细了解如何选择名称,请参阅 Microsoft 命名约定

部署共享网络

在本部分中,您将创建一个新项目并使用它部署共享 VPC 网络。稍后,您将使用此网络部署 Active Directory 域控制器。

创建项目

现在,您将创建一个新项目并使用它部署共享 VPC 网络。

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 启用 Compute Engine and Cloud DNS API。

    启用 API

如需获得部署共享网络所需的权限,请让您的管理员为您授予项目或父级文件夹的以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

删除默认 VPC

默认情况下,Compute Engine 会在您创建的每个新项目中创建默认网络。此网络以自动模式进行配置,这意味着系统为每个区域预先分配一个子网并自动分配 CIDR 范围。

在本部分中,您将此 VPC 网络替换为包含两个子网且使用自定义 CIDR 范围的自定义模式网络。

  1. Google Cloud 控制台中,打开 Cloud Shell

    激活 Cloud Shell

  2. 启动 PowerShell:

    pwsh
    
  3. 配置 gcloud CLI 以使用新项目:

    gcloud config set project PROJECT_ID
    

    PROJECT_ID 替换为您的项目 ID。

  4. 删除与默认 VPC 关联的所有防火墙规则:

    $ProjectId = gcloud config get-value core/project
    & gcloud compute firewall-rules list `
      --filter "network=default" `
      --format "value(name)" |
      % { gcloud compute firewall-rules delete --quiet $_ --project $ProjectId }
    
  5. 删除默认 VPC:

    & gcloud compute networks list --format "value(name)" |
      % { gcloud compute networks delete $_ --quiet }
    

创建一个自定义模式 VPC 网络

现在,您将在 VPC 宿主项目中创建一个自定义模式 VPC 网络。

  1. 在 PowerShell 中,初始化以下变量:

    $VpcName = "VPC_NAME"
    $Region = "REGION"
    $SubnetRangeDomainControllers = "DC_CIDR"
    $SubnetRangeResources = "RESOURCES_CIDR"
    

    请替换以下内容:

    • VPC_NAME:VPC 的名称。
    • REGION:要在其中部署 Active Directory 域控制器的区域。
    • DC_CIDR:用于域控制器子网的子网范围。
    • RESOURCES_CIDR:资源子网的子网范围。

    示例:

    $VpcName = "ad"
    $Region = "us-central1"
    $SubnetRangeDomainControllers = "10.0.0.0/28"
    $SubnetRangeResources = "10.0.1.0/24"
    
  2. 创建 VPC 并将其配置为用作共享 VPC 网络:

    $ProjectId = gcloud config get-value core/project
    & gcloud compute networks create $VpcName --subnet-mode custom
    & gcloud compute shared-vpc enable $ProjectId
    
  3. 创建子网并启用专用 Google 访问通道,以便 Windows 可以在没有连接互联网的情况下激活

    & gcloud compute networks subnets create domain-controllers `
      --network $VpcName `
      --range $SubnetRangeDomainControllers `
      --region $Region `
      --enable-private-ip-google-access
    
    & gcloud compute networks subnets create resources `
      --network $VpcName `
      --range $SubnetRangeResources `
      --region $Region `
      --enable-private-ip-google-access
    

部署子网和防火墙规则

现在,您将创建防火墙规则,以允许在 VPC 内进行 Active Directory 通信。

  1. 允许通过 Cloud IAP TCP 转发与所有虚拟机实例建立 RDP 连接:

    & gcloud compute firewall-rules create allow-rdp-ingress-from-iap `
      --direction INGRESS `
      --action allow `
      --rules tcp:3389 `
      --enable-logging `
      --source-ranges 35.235.240.0/20 `
      --network $VpcName `
      --priority 10000
    
  2. 允许从 Cloud DNS 到域控制器的 DNS 查询。

    & gcloud compute firewall-rules create allow-dns-ingress-from-clouddns `
      --direction INGRESS `
      --action=allow `
      --rules udp:53,tcp:53 `
      --enable-logging `
      --source-ranges 35.199.192.0/19 `
      --target-tags ad-domaincontroller `
      --network $VpcName `
      --priority 10000
    

    要使专用 DNS 转发可用区正常工作,必须使用此防火墙规则。

  3. 允许在域控制器之间复制 Active Directory:

    & gcloud compute firewall-rules create allow-replication-between-addc `
      --direction INGRESS `
      --action allow `
      --rules "icmp,tcp:53,udp:53,tcp:88,udp:88,udp:123,tcp:135,tcp:389,udp:389,tcp:445,udp:445,tcp:49152-65535" `
      --enable-logging `
      --source-tags ad-domaincontroller `
      --target-tags ad-domaincontroller `
      --network $VpcName `
      --priority 10000
    
  4. 允许 Active Directory 从资源子网中的虚拟机登录域控制器:

    & gcloud compute firewall-rules create allow-logon-ingress-to-addc `
      --direction INGRESS `
      --action allow `
      --rules "icmp,tcp:53,udp:53,tcp:88,udp:88,udp:123,tcp:135,tcp:389,udp:389,tcp:445,udp:445,tcp:464,udp:464,tcp:3268,udp:3268,tcp:9389,tcp:49152-65535" `
      --enable-logging `
      --source-ranges $SubnetRangeResources `
      --target-tags ad-domaincontroller `
      --network $VpcName `
      --priority 10000
    
  5. 如果您计划配置安全 LDAP,请允许从资源子网中的虚拟机建立到域控制器的安全 LDAP 连接:

    & gcloud compute firewall-rules create allow-ldaps-ingress-to-addc `
      --direction INGRESS `
      --action allow `
      --rules tcp:636 `
      --enable-logging `
      --source-ranges $SubnetRangeResources `
      --target-tags ad-domaincontroller `
      --network $VpcName `
      --priority 10000
    

    只有在您计划配置安全 LDAP 时,才需要此防火墙规则。

  6. (可选)创建一个防火墙规则,用于记录所有失败的访问尝试。这些日志对于诊断连接问题非常有用,但可能会生成大量日志数据。

    & gcloud compute firewall-rules create deny-ingress-from-all `
      --direction INGRESS `
      --action deny `
      --rules tcp:0-65535,udp:0-65535 `
      --enable-logging `
      --source-ranges 0.0.0.0/0 `
      --network $VpcName `
      --priority 65000
    

部署 Active Directory 林

在本部分中,您将创建一个新的服务项目,并将其附加到您之前创建的共享 VPC 宿主项目。然后,您可以使用该服务项目部署一个包含两个域控制器的新 Active Directory 林。

创建项目

现在,您可以创建一个新项目并使用它来部署 Active Directory 域控制器虚拟机。

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 启用 Compute Engine and Secret Manager API。

    启用 API

如需获得部署 Active Directory 林所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

准备配置

下一步是为 Active Directory 部署准备配置。

  1. 如果您之前关闭了 PowerShell 会话,请打开 Cloud Shell

    激活 Cloud Shell

  2. 启动 PowerShell:

    pwsh
    
  3. 配置 gcloud CLI 以使用新项目:

    gcloud config set project DC_PROJECT_ID
    

    DC_PROJECT_ID 替换为您的项目 ID。

  4. 使用 PowerShell 创建以下变量:

    $AdDnsDomain = "DNS_DOMAIN"
    $AdNetbiosDomain = "NETBIOS_DOMAIN"
    $VpcProjectId = "VPCHOST_PROJECT_ID"
    $VpcName = "VPC_NAME"
    $Region = "REGION"
    $Zones = "REGION-a", "REGION-b"
    

    请替换以下内容:

    • DNS_DOMAIN:Active Directory 林的林根域名,例如 cloud.example.com
    • NETBIOS_DOMAIN:林根域的 NetBIOS 域名,例如 CLOUD
    • VPCHOST_PROJECT_ID:您之前创建的 VPC 宿主项目的项目 ID。
    • VPC_NAME:您之前创建的共享 VPC 网络的名称。
    • REGION:要在其中部署 Active Directory 域控制器的区域。请注意,可用区的名称基于您指定的区域的名称。您可以随时扩展 VPC 和网域以覆盖其他区域。

    示例:

    $AdDnsDomain = "cloud.example.com"
    $AdNetbiosDomain = "CLOUD"
    $VpcProjectId = "vpc-project-123"
    $VpcName = "ad"
    $Region = "us-west1"
    $Zones = "us-west1-a", "us-west1-b"
    

创建专用 DNS 转发可用区

现在,您将为域控制器预留两个静态 IP 地址,并创建一个专用 DNS 转发可用区,以将 Active Directory 域的所有 DNS 查询转发到这些 IP 地址。

  1. 将项目连接到共享 VPC 网络:

    $ProjectId = gcloud config get-value core/project
    & gcloud compute shared-vpc associated-projects add $ProjectId --host-project $VpcProjectId
    
  2. 在域控制器子网中预留两个静态内部 IP 地址:

    $AddressOfDc1 = gcloud compute addresses create dc-1 `
      --region $Region `
      --subnet "projects/$VpcProjectId/regions/$Region/subnetworks/domain-controllers" `
      --format value`(address`)
    $AddressOfDc2 = gcloud compute addresses create dc-2 `
      --region $Region `
      --subnet "projects/$VpcProjectId/regions/$Region/subnetworks/domain-controllers" `
      --format value`(address`)
    
  3. 在 VPC 宿主项目中创建 Cloud DNS 专用转发可用区,并将可用区配置为将 DNS 查询转发到两个预留的 IP 地址:

    & gcloud dns managed-zones create $AdDnsDomain.Replace(".", "-") `
      --project $VpcProjectId `
      --dns-name $AdDnsDomain `
      --description "Active Directory forwarding zone" `
      --networks $VpcName `
      --visibility private `
      --forwarding-targets "$AddressOfDc1,$AddressOfDc2"
    

创建 DSRM 密码

现在,您将定义目录服务恢复模式 (DSRM) 密码并将其存储在 Secret Manager 中。然后,向域控制器虚拟机授予对此 Secret 的临时访问权限,以便它们可以使用它来部署 Active Directory 林。

  1. 生成一个随机密码并将其存储在 Secret Manager Secret 中:

    # Generate a random password.
    $DsrmPassword = [Guid]::NewGuid().ToString()+"-"+[Guid]::NewGuid().ToString()
    
    $TempFile = New-TemporaryFile
    Set-Content $TempFile "$DsrmPassword" -NoNewLine
    & gcloud secrets create ad-password --data-file $TempFile
    Remove-Item $TempFile
    
  2. 为域控制器虚拟机实例创建服务账号:

    $DcServiceAccount = gcloud iam service-accounts create ad-domaincontroller `
      --display-name "AD Domain Controller" `
      --format "value(email)"
    
  3. 向服务账号授予在接下来一小时内读取 Secret 的权限:

    $Expiry = [DateTime]::UtcNow.AddHours(1).ToString("o")
    & gcloud secrets add-iam-policy-binding ad-password `
      --member=serviceAccount:$($DcServiceAccount) `
      --role=roles/secretmanager.secretAccessor `
      --condition="title=Expires after 1h,expression=request.time < timestamp('$Expiry')"
    

部署域控制器

现在,您将部署两个虚拟机实例并创建新的 Active Directory 林和域。如需最大限度地减少手动步骤的数量,请使用启动脚本

  1. 在 PowerShell 中运行以下命令,以生成启动脚本:

    '
    $ErrorActionPreference = "Stop"
    
    #
    # Only run the script if the VM is not a domain controller already.
    #
    if ((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType -eq 2) {
        exit
    }
    
    #
    # Read configuration from metadata.
    #
    Import-Module "${Env:ProgramFiles}\Google\Compute Engine\sysprep\gce_base.psm1"
    
    $ActiveDirectoryDnsDomain     = Get-MetaData -Property "attributes/ActiveDirectoryDnsDomain" -instance_only
    $ActiveDirectoryNetbiosDomain = Get-MetaData -Property "attributes/ActiveDirectoryNetbiosDomain" -instance_only
    $ActiveDirectoryFirstDc       = Get-MetaData -Property "attributes/ActiveDirectoryFirstDc" -instance_only
    $ProjectId                    = Get-MetaData -Property "project-id" -project_only
    $Hostname                     = Get-MetaData -Property "hostname" -instance_only
    $AccessToken                  = (Get-MetaData -Property "service-accounts/default/token" | ConvertFrom-Json).access_token
    
    #
    # Read the DSRM password from secret manager.
    #
    $Secret = (Invoke-RestMethod `
        -Headers @{
            "Metadata-Flavor" = "Google";
            "x-goog-user-project" = $ProjectId;
            "Authorization" = "Bearer $AccessToken"} `
        -Uri "https://secretmanager.googleapis.com/v1/projects/$ProjectId/secrets/ad-password/versions/latest:access")
    $DsrmPassword = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Secret.payload.data))
    $DsrmPassword = ConvertTo-SecureString -AsPlainText $DsrmPassword -force
    
    #
    # Promote.
    #
    Write-Host "Setting administrator password..."
    Set-LocalUser -Name Administrator -Password $DsrmPassword
    
    if ($ActiveDirectoryFirstDc -eq $env:COMPUTERNAME) {
        Write-Host "Creating a new forest $ActiveDirectoryDnsDomain ($ActiveDirectoryNetbiosDomain)..."
        Install-ADDSForest `
            -DomainName $ActiveDirectoryDnsDomain `
            -DomainNetbiosName $DomainNetbiosName `
            -SafeModeAdministratorPassword $DsrmPassword `
            -DomainMode Win2008R2 `
            -ForestMode Win2008R2 `
            -InstallDns `
            -CreateDnsDelegation:$False `
            -NoRebootOnCompletion:$True `
            -Confirm:$false
    }
    else {
        do {
            Write-Host "Waiting for domain to become available..."
            Start-Sleep -s 60
            & ipconfig /flushdns | Out-Null
            & nltest /dsgetdc:$ActiveDirectoryDnsDomain | Out-Null
        } while ($LASTEXITCODE -ne 0)
    
        Write-Host "Adding DC to $ActiveDirectoryDnsDomain ($ActiveDirectoryNetbiosDomain)..."
        Install-ADDSDomainController `
            -DomainName $ActiveDirectoryDnsDomain `
            -SafeModeAdministratorPassword $DsrmPassword `
            -InstallDns `
            -Credential (New-Object System.Management.Automation.PSCredential ("Administrator@$ActiveDirectoryDnsDomain", $DsrmPassword)) `
            -NoRebootOnCompletion:$true  `
            -Confirm:$false
    }
    
    #
    # Configure DNS.
    #
    Write-Host "Configuring DNS settings..."
    Get-Netadapter| Disable-NetAdapterBinding -ComponentID ms_tcpip6
    Set-DnsClientServerAddress  `
        -InterfaceIndex (Get-NetAdapter -Name Ethernet).InterfaceIndex `
        -ServerAddresses 127.0.0.1
    
    #
    # Enable LSA protection.
    #
    New-ItemProperty `
        -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
        -Name "RunAsPPL" `
        -Value 1 `
        -PropertyType DWord
    
    Write-Host "Restarting to apply all settings..."
    Restart-Computer
    ' | Out-File dc-startup.ps1 -Encoding ASCII
    

    该脚本将执行以下操作:

    • 从 Secret Manager 读取 DSRM 密码。
    • 将虚拟机提升为域控制器。
    • 配置 DNS 设置,以便每个域控制器使用环回地址作为 DNS 服务器。
    • 停用 IPv6。
    • 启用 LSA 保护
  2. 为第一个域控制器创建一个虚拟机实例:

    $Subnet = "projects/$VpcProjectId/regions/$Region/subnetworks/domain-controllers"
    $Metadata = `
      "ActiveDirectoryDnsDomain=$AdDnsDomain",
      "ActiveDirectoryNetbiosDomain=$AdNetbiosDomain",
      "ActiveDirectoryFirstDc=dc-1",
      "sysprep-specialize-script-ps1=Install-WindowsFeature AD-Domain-Services; Install-WindowsFeature DNS",
      "disable-account-manager=true" -join ","
    
    & gcloud compute instances create dc-1  `
      --image-family windows-2022 `
      --image-project windows-cloud `
      --machine-type n2-standard-8 `
      --tags ad-domaincontroller `
      --metadata "$Metadata" `
      --metadata-from-file windows-startup-script-ps1=dc-startup.ps1 `
      --no-address `
      --network-interface "no-address,private-network-ip=$AddressOfDc1,subnet=$Subnet" `
      --service-account $DcServiceAccount `
      --scopes cloud-platform `
      --zone $Zones[0] `
      --shielded-integrity-monitoring `
      --shielded-secure-boot `
      --shielded-vtpm `
      --deletion-protection
    

    此命令执行以下操作:

    • 创建一个安全强化型 Windows Server 2022 虚拟机。
    • ad-domaincontroller 服务账号分配给该虚拟机,以便它可以访问 DSRM 密码。
    • 配置客机代理以停用账号管理器。如需详细了解如何配置客机代理,请参阅启用和停用 Windows 实例功能
    • 让虚拟机在 sysprep 专用化阶段安装 Windows 功能 AD-Domain-ServicesDNS
    • 让虚拟机运行您之前创建的启动脚本。
  3. 为第二个网域控制器创建另一个虚拟机实例,并将其放置在其他可用区中:

    & gcloud compute instances create dc-2  `
      --image-family windows-2022 `
      --image-project windows-cloud `
      --machine-type n2-standard-8 `
      --tags ad-domaincontroller `
      --metadata "$Metadata" `
      --metadata-from-file windows-startup-script-ps1=dc-startup.ps1 `
      --no-address `
      --network-interface "no-address,private-network-ip=$AddressOfDc2,subnet=$Subnet" `
      --service-account $DcServiceAccount `
      --scopes cloud-platform `
      --zone $Zones[1] `
      --shielded-integrity-monitoring `
      --shielded-secure-boot `
      --shielded-vtpm `
      --deletion-protection
    
  4. 通过查看第一个域控制器的串行端口输出来监控其初始化过程:

    & gcloud compute instances tail-serial-port-output dc-1 --zone $Zones[0]
    

    等待大约 10 分钟,直到您看到消息 Restarting to apply all settings...,然后按 Ctrl+C

  5. 通过查看第二个域控制器的串行端口输出来监控其初始化过程:

    & gcloud compute instances tail-serial-port-output dc-2 --zone $Zones[1]
    

    等待大约 10 分钟,直到您看到消息 Restarting to apply all settings...,然后按 Ctrl+C

Active Directory 林和域现已可供使用。

连接到域控制器

现在,您可以通过连接到其中一个域控制器来自定义 Active Directory 林。

  1. 在 PowerShell 中,访问 Administrator 用户的密码:

    gcloud secrets versions access latest --secret ad-password
    
  2. 使用 RDP 连接到 dc-1,然后以 Administrator 用户身份登录。

    由于虚拟机实例没有公共 IP 地址,因此您必须通过 Identity-Aware Proxy TCP 转发进行连接。

后续步骤