使用 Azure 门户为 Bastion 配置 Kerberos 身份验证

本文介绍如何将 Azure Bastion 配置为使用 Kerberos 身份验证。 Kerberos 身份验证可与基本和标准 Bastion SKU 配合使用。 有关 Kerberos 身份验证的详细信息,请参阅 Kerberos 身份验证概述。 有关 Azure Bastion 的详细信息,请参阅什么是 Azure Bastion?

注意事项

  • 只能在 Azure 门户中为 Azure Bastion 配置 Kerberos 设置,而不能在本机客户端中配置。
  • Kerberos 目前不支持从本地迁移到 Azure 的 VM。 
  • Kerberos 目前不支持跨领域身份验证。
  • 域控制器必须为堡垒主机部署的同一 VNET 中的 Azure 托管虚拟机。
  • Kerberos 目前不支持对 DNS 服务器进行更改。 对 DNS 服务器进行任何更改后,需要删除再重新创建 Bastion 资源。
  • 如果添加其他域控制器 (DC),Bastion 将仅识别第一个 DC。
  • 如果为不同的域添加了其他 DC,则添加的域无法成功通过 Kerberos 进行身份验证。

先决条件

更新 VNet DNS 服务器

本部分中的以下步骤可帮助你更新虚拟网络以指定自定义 DNS 设置。

  1. 登录到 Azure 门户
  2. 转到要为其部署 Bastion 资源的虚拟网络。
  3. 转到 VNet 的“DNS 服务器”页并选择“自定义”。 添加 Azure 托管的域控制器的 IP 地址并选择“保存”。

部署 Bastion

  1. 使用教程:使用手动配置设置部署 Bastion 中的步骤开始配置 Bastion 部署。 在“基本信息”选项卡上配置设置。然后,在页面顶部,单击“高级”转到高级选项卡。

  2. 在“高级”选项卡上,选择“Kerberos”。

    Screenshot of select bastion features.

  3. 在页面底部,选择“查看 + 创建”,然后选择“创建”,将 Bastion 部署到虚拟网络。

  4. 部署完成后,可以使用 Bastion 登录到任何可访问的、已加入到在前面步骤中指定的自定义 DNS 的 Windows VM。

修改现有的 Bastion 部署

本部分中的以下步骤可帮助你修改虚拟网络和现有的 Bastion 部署以进行 Kerberos 身份验证。

  1. 更新虚拟网络的 DNS 设置
  2. 转到 Bastion 部署的门户页并选择“配置”。
  3. 在“配置”页上,依次选择“Kerberos 身份验证”、“应用”。
  4. Bastion 将使用新的配置设置进行更新。

验证 Bastion 是否使用 Kerberos

注意

必须使用用户主体名称 (UPN) 才能使用 Kerberos 登录。

在 Bastion 资源上启用 Kerberos 后,可以验证该资源是否确实在使用 Kerberos 向已加入域的目标 VM 进行身份验证。

  1. 登录到目标 VM(通过或不通过 Bastion)。 在任务栏中搜索“编辑组策略”并打开“本地组策略编辑器”。

  2. 选择“计算机配置”>“Windows 设置”>“安全设置”>“本地策略”>“安全选项”。

  3. 找到策略“网络安全: 限制 NTLM: 传入 NTLM 流量”并将其设置为“拒绝所有域帐户”。 由于在禁用 Kerberos 时 Bastion 会使用 NTLM 进行身份验证,因此,此设置可确保将来在 VM 上尝试登录时基于 NTLM 的身份验证不会成功。

  4. 结束 VM 会话。

  5. 使用 Bastion 再次连接到目标 VM。 登录应该成功,这表明 Bastion 已使用 Kerberos(而不是 NTLM)进行身份验证。

    注意

    若要防止故障回复到 NTLM,请确保遵循前面的步骤。 启用 Kerberos(不遵循过程)不会阻止故障回复到 NTLM。

快速入门:使用 Kerberos 设置 Bastion - 资源管理器模板

查看模板

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "defaultValue": "[resourceGroup().location]",
      "type": "string"
    },
    "defaultNsgName": {
      "type": "string",
      "defaultValue": "Default-nsg"
    },
    "VnetName": {
      "type": "string",
      "defaultValue": "myVnet"
    },
    "ClientVMName": {
      "defaultValue": "Client-vm",
      "type": "string"
    },
    "ServerVMName": {
      "defaultValue": "Server-vm",
      "type": "string"
    },
    "vmsize": {
      "defaultValue": "Standard_DS1_v2",
      "type": "string",
      "metadata": {
        "description": "VM SKU to deploy"
      }
    },
    "ServerVMUsername": {
      "type": "string",
      "defaultValue": "serveruser",
      "metadata": {
        "description": "Admin username on all VMs."
      }
    },
    "ServerVMPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Admin password on all VMs."
      }
    },
    "SafeModeAdministratorPassword": {
      "type": "securestring",
      "metadata": {
        "description": "See https://learn.microsoft.com/powershell/module/addsdeployment/install-addsdomaincontroller?view=windowsserver2022-ps#-safemodeadministratorpassword"
      }
    },
    "ClientVMUsername": {
      "type": "string",
      "defaultValue": "clientuser",
      "metadata": {
        "description": "username on ClientVM."
      }
    },
    "ClientVMPassword": {
      "type": "securestring",
      "metadata": {
        "description": "password on ClientVM."
      }
    },
    "ServerVmImage": {
      "type": "object",
      "defaultValue": {
        "offer": "WindowsServer",
        "publisher": "MicrosoftWindowsServer",
        "sku": "2019-Datacenter",
        "version": "latest"
      }
    },
    "ClientVmImage": {
      "type": "object",
      "defaultValue": {
        "offer": "Windows",
        "publisher": "microsoftvisualstudio",
        "sku": "Windows-10-N-x64",
        "version": "latest"
      }
    },
    "publicIPAllocationMethod": {
      "type": "string",
      "defaultValue": "Static"
    },
    "BastionName": {
      "defaultValue": "Bastion",
      "type": "string"
    },
    "BastionPublicIPName": {
        "defaultValue": "Bastion-ip",
        "type": "string"
    }
  },
  "variables": {
    "DefaultSubnetId": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/default')]",
    "ClientVMSubnetId": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/clientvm-subnet')]",
    "DNSServerIpAddress": "10.16.0.4",
    "ClientVMPrivateIpAddress": "10.16.1.4"
  },
  "resources": [
    {
      "apiVersion": "2020-03-01",
      "name": "[parameters('VnetName')]",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "[parameters('location')]",
      "properties": {
        "dhcpOptions": {
          "dnsServers": [ "[variables('DNSServerIpAddress')]" ]
        },
        "subnets": [
          {
            "name": "default",
            "properties": {
              "addressPrefix": "10.16.0.0/24"
            }
          },
          {
            "name": "clientvm-subnet",
            "properties": {
              "addressPrefix": "10.16.1.0/24"
            }
          },
          {
            "name": "AzureBastionSubnet",
            "properties": {
              "addressPrefix": "10.16.2.0/24"
            }
          }
        ],
        "addressSpace": {
          "addressPrefixes": [
            "10.16.0.0/16"
          ]
        }
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2018-10-01",
      "name": "[concat(parameters('ServerVMName'), 'Nic')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "[concat(parameters('ServerVMName'), 'NicIpConfig')]",
            "properties": {
              "privateIPAllocationMethod": "Static",
              "privateIPAddress": "[variables('DNSServerIpAddress')]",
              "subnet": {
                "id": "[variables('DefaultSubnetId')]"
              }
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2020-06-01",
      "name": "[parameters('ServerVMName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Network/networkInterfaces/', parameters('ServerVMName'), 'Nic')]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "AdminUsername": "[parameters('ServerVMUsername')]",
          "AdminPassword": "[parameters('ServerVMPassword')]",
          "computerName": "[parameters('ServerVMName')]"
        },
        "storageProfile": {
          "imageReference": "[parameters('ServerVmImage')]",
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "Standard_LRS"
            }
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[ResourceId('Microsoft.Network/networkInterfaces/', concat(parameters('ServerVMName'), 'Nic'))]"
            }
          ]
        }
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "apiVersion": "2021-04-01",
      "name": "[concat(parameters('ServerVMName'),'/', 'PromoteToDomainController')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/',parameters('ServerVMName'))]"
      ],
      "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.7",
        "autoUpgradeMinorVersion": true,
        "settings": {
          "commandToExecute": "[concat('powershell.exe -Command \"Install-windowsfeature AD-domain-services; Import-Module ADDSDeployment;$Secure_String_Pwd = ConvertTo-SecureString ',parameters('SafeModeAdministratorPassword'),' -AsPlainText -Force; Install-ADDSForest -DomainName \"bastionkrb.test\" -SafeModeAdministratorPassword $Secure_String_Pwd -Force:$true')]"
          }
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2018-10-01",
      "name": "[concat(parameters('ClientVMName'), 'Nic')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]",
        "[concat('Microsoft.Compute/virtualMachines/', parameters('ServerVMName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "[concat(parameters('ClientVMName'), 'NicIpConfig')]",
            "properties": {
              "privateIPAllocationMethod": "Static",
              "privateIPAddress": "[variables('ClientVMPrivateIpAddress')]",
              "subnet": {
                "id": "[variables('ClientVMSubnetId')]"
              }
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2020-06-01",
      "name": "[parameters('ClientVMName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Network/networkInterfaces/', parameters('ClientVMName'), 'Nic')]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "AdminUsername": "[parameters('ClientVMUsername')]",
          "AdminPassword": "[parameters('ClientVMPassword')]",
          "computerName": "[parameters('ClientVMName')]"
        },
        "storageProfile": {
          "imageReference": "[parameters('ClientVmImage')]",
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "Standard_LRS"
            }
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[ResourceId('Microsoft.Network/networkInterfaces/', concat(parameters('ClientVMName'), 'Nic'))]"
            }
          ]
        }
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "apiVersion": "2021-04-01",
      "name": "[concat(parameters('ClientVMName'),'/', 'DomainJoin')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/',parameters('ClientVMName'))]",
        "[concat('Microsoft.Compute/virtualMachines/', parameters('ServerVMName'),'/extensions/', 'PromoteToDomainController')]",
        "[concat('Microsoft.Network/bastionHosts/', parameters('BastionName'))]"
      ],
      "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.7",
        "autoUpgradeMinorVersion": true,
        "settings": {
          "commandToExecute": "[concat('powershell.exe -Command Set-ItemProperty -Path HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0\\ -Name RestrictReceivingNTLMTraffic -Value 1; $Pass= ConvertTo-SecureString -String ',parameters('ServerVMPassword'),' -AsPlainText -Force; $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList \"AD\\serveruser\", $Pass; do { try { $joined = add-computer -computername Client-vm -domainname bastionkrb.test -credential $Credential -passthru -restart -force; } catch {}} while ($joined.HasSucceeded -ne $true)')]"
          }
      }
    },
    {
      "apiVersion": "2020-11-01",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[parameters('BastionPublicIPName')]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard"
      },
      "properties": {
        "publicIPAllocationMethod": "Static"
      },
      "tags": {}
    },
    {
        "type": "Microsoft.Network/bastionHosts",
        "apiVersion": "2020-11-01",
        "name": "[parameters('BastionName')]",
        "location": "[resourceGroup().location]",
        "dependsOn": [
            "[concat('Microsoft.Network/virtualNetworks/', parameters('VnetName'))]",
            "[concat('Microsoft.Network/publicIpAddresses/', parameters('BastionPublicIPName'))]"
        ],
        "sku": {
            "name": "Standard"
        },
        "properties": {
            "enableKerberos": "true",
            "ipConfigurations": [
                {
                    "name": "IpConf",
                    "properties": {
                        "privateIPAllocationMethod": "Dynamic",
                        "publicIPAddress": {
                            "id": "[resourceId('Microsoft.Network/publicIpAddresses', parameters('BastionPublicIPName'))]"
                        },
                        "subnet": {
                            "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', parameters('VnetName')), '/subnets/AzureBastionSubnet')]"
                        }
                    }
                }
            ]
        }
    }
  ]
}

该模板中已定义了以下资源:

  • 部署以下 Azure 资源:
  • 将 VNet 的 DNS 服务器指向 ServerVM(域控制器)的专用 IP 地址。
  • 在 ServerVM 上运行自定义脚本扩展,将其提升到域名为 bastionkrb.test 的域控制器。
  • 在 ClientVM 上运行自定义脚本扩展,使之执行以下操作:
    • 限制 NTLM:传入 NTLM 流量 = 拒绝所有域帐户(目的是确保 Kerberos 用于身份验证)。
    • 域加入 bastionkrb.test 域。

部署模板

若要设置 Kerberos,请通过运行以下 PowerShell cmd 来部署前面的 ARM 模板:

New-AzResourceGroupDeployment -ResourceGroupName <your-rg-name> -TemplateFile "<path-to-template>\KerberosDeployment.json"`

查看已部署的资源

现在,使用带有 Kerberos 身份验证的 Bastion 登录到 ClientVM:

  • 凭据:用户名 = serveruser@bastionkrb.test,密码 = <password-entered-during-deployment>

后续步骤

有关 Azure Bastion 的详细信息,请参阅什么是 Azure Bastion?