設定虛擬子網路的加密

適用於:Windows Server 2022、Windows Server 2019、Windows Server 2016、Azure Stack HCI、版本 21H2 和 20H2

虛擬網路加密可讓虛擬網路流量在彼此於標示為「加密已啟用」的子網路內通訊的 VM 之間進行加密。 這項功能也利用虛擬子網路上的資料包傳輸層安全性 (DTLS) 來加密封包。 DTLS 提供保護以防止任何可存取實體網路的人進行竊聽、竄改和偽造。

虛擬網路加密需要:

  • 安裝在每個已啟用 SDN 的 Hyper-V 主機上的加密憑證。
  • 網路控制站中的認證物件,參考該憑證的指紋。
  • 每個虛擬網路上的設定都包含需要加密的子網路。

在子網路上啟用加密之後,除了可能也會進行的任何應用層級加密之外,該子網路內的所有網路流量都會自動加密。 即使標示為加密,子網路之間的流量也會自動傳送未加密。 任何跨越虛擬網路界限的流量也會未經加密傳送。

注意

與同一個子網路上的另一個 VM 通訊時,無論它是目前連接還是稍後連接,流量都會自動加密。

提示

如果您必須限制應用程式只在加密的子網路上通訊,則只能使用存取控制清單 (ACL) 來允許目前子網路內的通訊。 如需詳細資訊,請參閱使用存取控制清單 (ACL) 來管理資料中心網路流量

步驟 1:建立加密憑證

每台主機都必須安裝加密憑證。 您可以針對所有租用戶使用相同的憑證,或針對每個租用戶產生一個唯一的憑證。

  1. 產生憑證

    $subjectName = "EncryptedVirtualNetworks"
    $cryptographicProviderName = "Microsoft Base Cryptographic Provider v1.0";
    [int] $privateKeyLength = 1024;
    $sslServerOidString = "1.3.6.1.5.5.7.3.1";
    $sslClientOidString = "1.3.6.1.5.5.7.3.2";
    [int] $validityPeriodInYear = 5;
    
    $name = new-object -com "X509Enrollment.CX500DistinguishedName.1"
    $name.Encode("CN=" + $SubjectName, 0)
    
    #Generate Key
    $key = new-object -com "X509Enrollment.CX509PrivateKey.1"
    $key.ProviderName = $cryptographicProviderName
    $key.KeySpec = 1 #X509KeySpec.XCN_AT_KEYEXCHANGE
    $key.Length = $privateKeyLength
    $key.MachineContext = 1
    $key.ExportPolicy = 0x2 #X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_FLAG
    $key.Create()
    
    #Configure Eku
    $serverauthoid = new-object -com "X509Enrollment.CObjectId.1"
    $serverauthoid.InitializeFromValue($sslServerOidString)
    $clientauthoid = new-object -com "X509Enrollment.CObjectId.1"
    $clientauthoid.InitializeFromValue($sslClientOidString)
    $ekuoids = new-object -com "X509Enrollment.CObjectIds.1"
    $ekuoids.add($serverauthoid)
    $ekuoids.add($clientauthoid)
    $ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
    $ekuext.InitializeEncode($ekuoids)
    
    # Set the hash algorithm to sha512 instead of the default sha1
    $hashAlgorithmObject = New-Object -ComObject X509Enrollment.CObjectId
    $hashAlgorithmObject.InitializeFromAlgorithmName( $ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, $ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, $AlgorithmFlags.AlgorithmFlagsNone, "SHA512")
    
    
    #Request Certificate
    $cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1"
    
    $cert.InitializeFromPrivateKey(2, $key, "")
    $cert.Subject = $name
    $cert.Issuer = $cert.Subject
    $cert.NotBefore = (get-date).ToUniversalTime()
    $cert.NotAfter = $cert.NotBefore.AddYears($validityPeriodInYear);
    $cert.X509Extensions.Add($ekuext)
    $cert.HashAlgorithm = $hashAlgorithmObject
    $cert.Encode()
    
    $enrollment = new-object -com "X509Enrollment.CX509Enrollment.1"
    $enrollment.InitializeFromRequest($cert)
    $certdata = $enrollment.CreateRequest(0)
    $enrollment.InstallResponse(2, $certdata, 0, "")
    

    執行指令碼之後,一個新的憑證出現在 My 存放區中:

    PS D:\> dir cert:\\localmachine\my
    PSParentPath: Microsoft.PowerShell.Security\Certificate::localmachine\my
    
    Thumbprint                                Subject
    ----------                                -------
    84857CBBE7A1C851A80AE22391EB2C39BF820CE7  CN=MyNetwork
    5EFF2CE51EACA82408572A56AE1A9BCC7E0843C6  CN=EncryptedVirtualNetworks
    
  2. 將該憑證匯出到一個檔案中。

    您需要該憑證的兩份副本,一份具有私鑰,一份沒有。

    $subjectName = "EncryptedVirtualNetworks"
    $cert = Get-ChildItem cert:\localmachine\my | ? {$_.Subject -eq "CN=$subjectName"}
    [System.io.file]::WriteAllBytes("c:\$subjectName.pfx", $cert.Export("PFX", "secret"))
    Export-Certificate -Type CERT -FilePath "c:\$subjectName.cer" -cert $cert
    
  3. 在每台 Hyper-v 主機上安裝憑證

    PS C:\> dir c:\$subjectname.*
    
    Directory: C:\
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        9/22/2017   4:54 PM            543 EncryptedVirtualNetworks.cer
    -a----        9/22/2017   4:54 PM           1706 EncryptedVirtualNetworks.pfx
    
  4. 在 Hyper-V 主機上安裝

    $server = "Server01"
    
    $subjectname = "EncryptedVirtualNetworks"
    copy c:\$SubjectName.* \\$server\c$
    invoke-command -computername $server -ArgumentList $subjectname,"secret" {
        param (
            [string] $SubjectName,
            [string] $Secret
        )
        $certFullPath = "c:\$SubjectName.cer"
    
        # create a representation of the certificate file
        $certificate = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
        $certificate.import($certFullPath)
    
        # import into the store
        $store = new-object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine")
        $store.open("MaxAllowed")
        $store.add($certificate)
        $store.close()
    
        $certFullPath = "c:\$SubjectName.pfx"
        $certificate = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
        $certificate.import($certFullPath, $Secret, "MachineKeySet,PersistKeySet")
    
        # import into the store
        $store = new-object System.Security.Cryptography.X509Certificates.X509Store("My", "LocalMachine")
        $store.open("MaxAllowed")
        $store.add($certificate)
        $store.close()
    
        # Important: Remove the certificate files when finished
        remove-item C:\$SubjectName.cer
        remove-item C:\$SubjectName.pfx
    }
    
  5. 針對您環境中的每台伺服器重複執行。

    針對每台伺服器重複執行之後,您應該在每台 Hyper-V 主機的 Root 和 My 存放區中安裝了憑證。

  6. 確認安裝憑證。

    藉由檢查 My 和 Root 憑證存放區的內容來確認憑證:

    PS C:\> enter-pssession Server1
    
    [Server1]: PS C:\> get-childitem cert://localmachine/my,cert://localmachine/root | ? {$_.Subject -eq "CN=EncryptedVirtualNetworks"}
    
    PSParentPath: Microsoft.PowerShell.Security\Certificate::localmachine\my
    
    Thumbprint                                Subject
    ----------                                -------
    5EFF2CE51EACA82408572A56AE1A9BCC7E0843C6  CN=EncryptedVirtualNetworks
    
    PSParentPath: Microsoft.PowerShell.Security\Certificate::localmachine\root
    
    Thumbprint                                Subject
    ----------                                -------
    5EFF2CE51EACA82408572A56AE1A9BCC7E0843C6  CN=EncryptedVirtualNetworks
    
  7. 記下指紋 (Thumbprint)。

    您必須記下指紋,因為您需要它以在網路控制站中建立憑證認證物件。

步驟 2:建立憑證憑據

在連接到網路控制站的每台 Hyper-V 主機上安裝憑證之後,您現在必須設定網路控制站來使用它。 為此,您必須建立一個認證物件,其中包含來自安裝了網路控制站 PowerShell 模組的機器的憑證指紋。

///Replace with the thumbprint from your certificate
$thumbprint = "5EFF2CE51EACA82408572A56AE1A9BCC7E0843C6"

$uri = "https://nc.contoso.com"

///Replace with your Network Controller URI
Import-module networkcontroller

$credproperties = new-object Microsoft.Windows.NetworkController.CredentialProperties
$credproperties.Type = "X509Certificate"
$credproperties.Value = $thumbprint
New-networkcontrollercredential -connectionuri $uri -resourceid "EncryptedNetworkCertificate" -properties $credproperties -force

提示

您可以針對每個加密的虛擬網路重複使用此認證,也可以為每個租用戶部署及使用唯一的憑證。

步驟 3:設置加密的虛擬網路

此步驟假設您已建立一個名為 "My Network" 的虛擬網路,且它至少包含一個虛擬子網路。 如需建立虛擬網路的詳細資訊,請參閱建立、刪除或更新租用戶虛擬網路

注意

與同一個子網路上的另一個 VM 通訊時,無論它是目前連接還是稍後連接,流量都會自動加密。

  1. 從網路控制站中擷取虛擬網路和認證物件:

    $vnet = Get-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId "MyNetwork"
    $certcred = Get-NetworkControllerCredential -ConnectionUri $uri -ResourceId "EncryptedNetworkCertificate"
    
  2. 新增憑證認證的參考並在各個子網路上啟用加密:

    $vnet.properties.EncryptionCredential = $certcred
    
    # Replace the Subnets index with the value corresponding to the subnet you want encrypted.
    # Repeat for each subnet where encryption is needed
    $vnet.properties.Subnets[0].properties.EncryptionEnabled = $true
    
  3. 將更新後的虛擬網路物件放入網路控制站中:

    New-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId $vnet.ResourceId -Properties $vnet.Properties -force
    

恭喜!* 完成這些步驟之後,您就完成了。