Permitir conexão RDP por meio do servidor Gateway RD por meio de vários URLs

0

Eu tenho um servidor RD Gateway acessível externamente que é usado para obter acesso a um grupo de servidores. Atualmente, ele usa um certificado autoassinado usando o FQDN externo, ou seja, MyServer.PrimaryLocation.Provider.com , e isso funciona como um tratamento enquanto o sistema está hospedado no local principal.

O problema ocorre quando precisamos fazer failover para DR, quando não conseguimos migrar o FQDN associado ao servidor. Isso nos deixa com um novo FQDN de MyServer.SecondaryLocation.Provider.com .

Estou procurando uma maneira de oferecer suporte a conexões por meio de URLs sem a necessidade de alterar certificados, o que seria frustrante para os usuários e, infelizmente, necessário devido à natureza auto-assinada dos certificados (obviamente, não proprietário do domínio 'Provider.com' e, portanto, não pode comprar certificados de CA externos.

Qualquer ajuda muito apreciada.

    
por AndyHerb 27.06.2017 / 15:58

1 resposta

1

Acontece que é possível entregar isso usando um certificado com entradas SAN (Subject Alternative Name). Para quem estiver interessado, aqui está o PowerShell para fazer isso:

<#
.Synopsis
   Creates a new Certificate for an RD Gateway Server
.DESCRIPTION
   Creates a self-signed Certificate and associates it with the local RD Gateway Server
.EXAMPLE
   New-RDGCertificate -SubjectName 
'CN=MyServer.PrimaryLocation.Provider.com'

   Creates a new self-signed certificate which can be used to to authenticate incoming RD Gateway traffic 
   to the DNS name MyServer.PrimaryLocation.Provider.com
.EXAMPLE
   [string[]] $SAN = "MyServer.SecondaryLocation.Provider.com"
   $SAN += "MyServer.TertiaryLocation.Provider.com"
   $SAN += "MyServer.local"

   New-RDGCertificate -SubjectName 
'CN=MyServer.PrimaryLocation.Provider.com' -SAN $SAN

   Creates a new self-signed certificate which can be used to to authenticate incoming RD Gateway traffic 
   to the following DNS names:
   1) MyServer.PrimaryLocation.Provider.com
   2) MyServer.SecondaryLocation.Provider.com
   3) MyServer.TertiaryLocation.Provider.com
   4) MyServer.local
#>
function New-RDGCertificate
{
    [CmdletBinding()]
    Param
    (
        # Name of the certificate to create
        [Parameter(Mandatory=$true)]
        [string]$SubjectName,

        # Subject-alternative name(s) to add to the certificate
        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [string[]]$SAN
    )

    Write-Verbose "Creating Certificate: $SubjectName"
    $Name = New-Object -Com 'X509Enrollment.CX500DistinguishedName.1'
    $Name.Encode($SubjectName, 0)

    $Key = New-Object -Com 'X509Enrollment.CX509PrivateKey.1'
    $Key.ProviderName = 'Microsoft RSA SChannel Cryptographic Provider'
    $Key.KeySpec = 1
    $Key.Length = 1024
    $Key.SecurityDescriptor = 'D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)'
    $Key.MachineContext = 1
    $Key.Create()

    $ServerAuthoID = New-Object -Com 'X509Enrollment.CObjectId.1'
    $ServerAuthoID.InitializeFromValue('1.3.6.1.5.5.7.3.1')
    $ekuoids = New-Object -Com 'X509Enrollment.CObjectIds.1'
    $ekuoids.add($ServerAuthoID)
    $ekuext = New-Object -Com 'X509Enrollment.CX509ExtensionEnhancedKeyUsage.1'
    $ekuext.InitializeEncode($ekuoids)

    $Cert = New-Object -Com 'X509Enrollment.CX509CertificateRequestCertificate.1'
    $Cert.InitializeFromPrivateKey(2, $Key, '')
    $Cert.Subject = $Name
    $Cert.Issuer = $Cert.Subject
    $Cert.NotBefore = (Get-Date).AddHours(-2)
    $Cert.NotAfter = $Cert.NotBefore.AddDays(2998)

    #SAN 
    if ($SAN) {
        $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames

        foreach ($AN in $SAN) {
            # Instantiate a IAlternativeName object
            $AltName = New-Object -ComObject X509Enrollment.CAlternativeName

            # Initialize the object by using current element
            $AltName.InitializeFromString(0x3,$AN)

        # Add created object to an object of collection of IAlternativeNames
        $IAlternativeNames.Add($AltName)
    }
    $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames 
    $SubjectAlternativeName.InitializeEncode($IAlternativeNames) 
    $Cert.X509Extensions.Add($SubjectAlternativeName)
    }

    $Cert.X509Extensions.Add($ekuext)
    $Cert.Encode()

    $Enrollment = New-Object -Com 'X509Enrollment.CX509Enrollment.1'
    $Enrollment.InitializeFromRequest($Cert)
    $CertData = $Enrollment.CreateRequest(0)
    $Enrollment.InstallResponse(2, $CertData, 0, '')
}

<#
.Synopsis
   Searches certificate store for a given Subject Name, returning the Certificate
.DESCRIPTION
   Searches through the LocalMachine or CurrentUser store location for a certificate whose Subject Name matches the given value
.EXAMPLE
   Find-RDSCertificate -SubjectName "CN=MyDNS.com"

   This will search the LocalMachine\My store for a certificate whose Subject Name matches MyDNS.com.
   It returns the certificate or $Null, based on whether or not a matching certificate is found.

.EXAMPLE
   Find-RDSCertificate -SubjectName "CN=MyOtherDNS.com" -Store "TrustedPublisher" -Location "CurrentUser"

   This will search the CurrentUser\TrustedPublisher store for a certificate whose Subject Name matches MyDNSOther.com.
   It returns the certificate or $Null, based on whether or not a matching certificate is found.
#>
function Find-RDSCertificate
{
    [CmdletBinding()]
    Param
    (
        # Name of the certificate to search for
        [Parameter(Mandatory=$true)]
        $SubjectName,

        # Certificate store to search in
        [Parameter(Mandatory=$false)]
        [ValidateSet("AddressBook", "AuthRoot", "CertificateAuthority", "Disallowed", "My", "Root", "TrustedPeople", "TrustedPublisher")]
        $Store = "My",

        # Location to search in
        [Parameter(Mandatory=$false)]
        [ValidateSet("LocalMachine", "CurrentUser")]
        $Location = "LocalMachine"
    )

    $CertStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($Store,$Location)
    $CertStore.Open('ReadOnly')

    $CertStore.Certificates | where {$_.Subject -Eq $SubjectName}
}

Import-Module RemoteDesktopServices

$RDGCertificateSubject = 'CN=MyServer.PrimaryLocation.Provider.com'
[string[]] $SAN = 'MyServer.SecondaryLocation.Provider.com'
$SAN += 'MyServer.TertiaryLocation.Provider.com'
$SAN += 'MyServer.local'
New-RDGCertificate -SubjectName $RDGCertificateSubject -SAN $SAN

$Cert = Find-RDSCertificate -SubjectName $RDGCertificateSubject
#Apply cert
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Cert.Thumbprint
    
por 27.06.2017 / 17:31