配置虚拟子网的加密
虚拟网络加密允许对在标记为“启用加密”的子网内相互通信的 VM 之间的虚拟网络流量进行加密。 它还利用虚拟子网上的数据报传输层安全性 (DTLS) 来加密数据包。 DTLS 可以防止能够访问物理网络的任何人进行窃听、篡改和伪造。
虚拟网络加密需要以下各项:
- 在每个已启用 SDN 的 Hyper-V 主机上安装的加密证书。
- 网络控制器中引用该证书指纹的凭据对象。
- 每个虚拟网络(包含需要加密的子网)上的配置。
在子网上启用加密后,除了可能进行的任何应用程序级加密外,该子网中的所有网络流量也会自动加密。 跨子网的流量,即使标记为加密,也会自动以未加密的方式发送。 任何跨越虚拟网络边界的流量也会以未加密的方式发送。
注意
与同一子网上的另一个 VM 通信时,无论是当前连接还是稍后连接,流量都会自动加密。
提示
如果必须将应用程序限制为仅在加密子网上通信,则可以仅使用访问控制列表 (ACL) 以允许在当前子网内进行通信。 有关详细信息,请参阅使用访问控制列表 (ACL) 管理数据中心网络流量。
第 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, "")
运行脚本后,“我的存储”中将显示新证书:
PS D:\> dir cert:\\localmachine\my PSParentPath: Microsoft.PowerShell.Security\Certificate::localmachine\my Thumbprint Subject ---------- ------- 84857CBBE7A1C851A80AE22391EB2C39BF820CE7 CN=MyNetwork 5EFF2CE51EACA82408572A56AE1A9BCC7E0843C6 CN=EncryptedVirtualNetworks
将证书导出为文件。
你需要证书的两个副本,一个包含私钥,一个没有私钥。
$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
在每个 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
在 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 }
对环境中每个服务器都重复上述步骤。
对每个服务器都重复操作后,应在每个 Hyper-V 主机的根和“我的存储”中都安装一个证书。
验证证书的安装。
通过检查“我的存储”和根证书存储的内容来验证证书:
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
记下指纹。
必须记下指纹,因为需要指纹才能在网络控制器中创建证书凭据对象。
第 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 通信时,无论是当前连接还是稍后连接,流量都会自动加密。
从网络控制器检索虚拟网络和凭据对象:
$vnet = Get-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId "MyNetwork" $certcred = Get-NetworkControllerCredential -ConnectionUri $uri -ResourceId "EncryptedNetworkCertificate"
添加对证书凭据的引用,并在单个子网上启用加密:
$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
将更新的虚拟网络对象放入网络控制器:
New-NetworkControllerVirtualNetwork -ConnectionUri $uri -ResourceId $vnet.ResourceId -Properties $vnet.Properties -force
祝贺!* 完成这些步骤后,即告完成。