Delegieren Sie die Verwaltung von RDP-Sitzungen

Delegieren Sie die Verwaltung von RDP-Sitzungen
In der Organisation, in der ich arbeite, ist Remote-Arbeit prinzipiell verboten gewesen. Bis letzte Woche. Nun mussten wir dringend eine Lösung implementieren. Vom Geschäftsbereich – Anpassung der Prozesse an das neue Arbeitsformat, von uns – PKI mit PIN-Codes und Tokens, VPN, detaillierte Protokollierung und vieles mehr.
Neben allem anderen habe ich die Infrastruktur der Remotearbeitsplätze, auch bekannt als Terminaldienste, eingerichtet. Wir haben mehrere RDS-Implementierungen in verschiedenen Rechenzentren. Eine der Aufgaben bestand darin, den Kollegen aus angrenzenden IT-Abteilungen zu ermöglichen, sich in interaktiven Sitzungen mit den Benutzersitzungen zu verbinden. Wie bekannt, gibt es dafür einen Standardmechanismus für RDS Shadow und der einfachste Weg, ihn zu delegieren, ist, lokale Administratorrechte auf den RDS-Servern zu gewähren.
Ich respektiere und schätze meine Kollegen, bin aber sehr großzügig bei der Vergabe von Administratorrechten. 🙂 Diejenigen, die meine Meinung teilen, lade ich unter den Cut ein.

Nun, die Aufgabe ist klar, jetzt – zum Geschäft.

Schritt 1

Lassen Sie uns in Active Directory eine Sicherheitsgruppe erstellen RDP_Operators und die Konten der Benutzer hinzufügen, denen wir die Rechte delegieren wollen:

$Users = @(
    "UserLogin1",
    "UserLogin2",
    "UserLogin3"
)
$Group = "RDP_Operators"
New-ADGroup -Name $Group -GroupCategory Security -GroupScope DomainLocal
Add-ADGroupMember -Identity $Group -Members $Users

Wenn Sie mehrere AD-Standorte haben, warten Sie, bevor Sie zum nächsten Schritt übergehen, bis diese auf alle Domain-Controller repliziert wurde. Normalerweise dauert dies nicht länger als 15 Minuten.

Schritt 2

Wir gewähren der Gruppe Rechte für die Verwaltung von Terminalsitzungen auf jedem der RDSH-Server:

Set-RDSPermissions.ps1

$Group = "RDP_Operators"
$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)
ForEach ($Server in $Servers) {
    #Delegieren Sie das Recht auf Schatten-Sitzungen
    $WMIHandles = Get-WmiObject `
        -Class "Win32_TSPermissionsSetting" `
        -Namespace "rootCIMV2terminalservices" `
        -ComputerName $Server `
        -Authentication PacketPrivacy `
        -Impersonation Impersonate
    ForEach($WMIHandle in $WMIHandles)
    {
        If ($WMIHandle.TerminalName -eq "RDP-Tcp")
        {
        $retVal = $WMIHandle.AddAccount($Group, 2)
        $opstatus = "erfolgreich"
        If ($retVal.ReturnValue -ne 0) {
            $opstatus = "Fehler"
        }
        Write-Host ("Delegierung der Rechte für die Schattenverbindung an die Gruppe " +
            $Group + " auf dem Server " + $Server + ": " + $opstatus + "`r`n")
        }
    }
}

Schritt 3

Fügen wir die Gruppe zur lokalen Gruppe hinzu Remotebenutzer auf jedem der RDSH-Server. Wenn Ihre Server in einer Sitzungssammlung zusammengefasst sind, erfolgt dies auf der Ebene der Sammlung:

$Group = "RDP_Operators"
$CollectionName = "MyRDSCollection"
[String[]]$CurrentCollectionGroups = @(Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup).UserGroup
Set-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup ($CurrentCollectionGroups + $Group)

Für einzelne Server verwenden wir Gruppenrichtlinien, und warten, bis sie auf den Servern angewendet wird. Wer es eilig hat, kann den Prozess mit dem bewährten gpupdate erzwingen, vorzugsweise zentralisiert.

Schritt 4

Wir bereiten für die „Verwalter“ ein solches PS-Skript vor:

RDSManagement.ps1

$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)

function Invoke-RDPSessionLogoff {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName,
        [parameter(Mandatory=$true, Position=1)][String]$SessionID
    )
    $ErrorActionPreference = "Stop"
    logoff $SessionID /server:$ComputerName /v 2>&1
}

function Invoke-RDPShadowSession {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName,
        [parameter(Mandatory=$true, Position=1)][String]$SessionID
    )
    $ErrorActionPreference = "Stop"
    mstsc /shadow:$SessionID /v:$ComputerName /control 2>&1
}

Function Get-LoggedOnUser {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName="localhost"
    )
    $ErrorActionPreference = "Stop"
    Test-Connection $ComputerName -Count 1 | Out-Null
    quser /server:$ComputerName 2>&1 | Select-Object -Skip 1 | ForEach-Object {
        $CurrentLine = $_.Trim() -Replace "s+"," " -Split "s"
        $HashProps = @{
            UserName = $CurrentLine[0]
            ComputerName = $ComputerName
        }
        If ($CurrentLine[2] -eq "Disc") {
            $HashProps.SessionName = $null
            $HashProps.Id = $CurrentLine[1]
            $HashProps.State = $CurrentLine[2]
            $HashProps.IdleTime = $CurrentLine[3]
            $HashProps.LogonTime = $CurrentLine[4..6] -join " "
            $HashProps.LogonTime = $CurrentLine[4..($CurrentLine.GetUpperBound(0))] -join " "
        }
        else {
            $HashProps.SessionName = $CurrentLine[1]
            $HashProps.Id = $CurrentLine[2]
            $HashProps.State = $CurrentLine[3]
            $HashProps.IdleTime = $CurrentLine[4]
            $HashProps.LogonTime = $CurrentLine[5..($CurrentLine.GetUpperBound(0))] -join " "
        }
        New-Object -TypeName PSCustomObject -Property $HashProps |
        Select-Object -Property UserName, ComputerName, SessionName, Id, State, IdleTime, LogonTime
    }
}

$UserLogin = Read-Host -Prompt "Bitte geben Sie den Benutzernamen ein"
Write-Host "Suche nach RDP-Sitzungen des Benutzers auf den Servern..."
$SessionList = @()
ForEach ($Server in $Servers) {
    $TargetSession = $null
    Write-Host "  Abfrage des Servers $Server"
    Try {
        $TargetSession = Get-LoggedOnUser -ComputerName $Server | Where-Object {$_.UserName -eq $UserLogin}
    }
    Catch {
        Write-Host "Fehler: " $Error[0].Exception.Message -ForegroundColor Red
        Continue
    }
    If ($TargetSession) {
        Write-Host "    Sitzung mit ID $($TargetSession.ID) auf dem Server $Server gefunden" -ForegroundColor Yellow
        Write-Host "    Was möchten Sie tun?"
        Write-Host "      1 - Mit Sitzung verbinden"
        Write-Host "      2 - Sitzung beenden"
        Write-Host "      0 - Nichts"
        $Action = Read-Host -Prompt "Bitte Aktion eingeben"
        If ($Action -eq "1") {
            Invoke-RDPShadowSession -ComputerName $Server -SessionID $TargetSession.ID
        }
        ElseIf ($Action -eq "2") {
            Invoke-RDPSessionLogoff -ComputerName $Server -SessionID $TargetSession.ID
        }
        Break
    }
    Else {
        Write-Host "    Keine Sitzungen gefunden"
    }
}

Um das PS-Skript bequem auszuführen, erstellen wir eine Batch-Datei mit dem gleichen Namen wie das PS-Skript:

RDSManagement.cmd

@ECHO OFF
powershell -NoLogo -ExecutionPolicy Bypass -File "%~d0%~p0%~n0.ps1" %*

Wir legen beide Dateien in einen Ordner, der für die ‚Manager‘ zugänglich ist, und bitten sie, sich erneut anzumelden. Jetzt können sie, indem sie die Batch-Datei ausführen, sich in die Sitzungen anderer Benutzer im RDS Shadow-Modus verbinden und diese zwangsweise abmelden (was nützlich sein kann, wenn ein Benutzer seine ‚hängende‘ Sitzung nicht selbst beenden kann).

So sieht das aus:

Für den ‚Manager‘Delegieren Sie die Verwaltung von RDP-Sitzungen

Für den BenutzerDelegieren Sie die Verwaltung von RDP-Sitzungen

Ein paar abschließende Anmerkungen

Hinweis 1. Wenn die Sitzung des Benutzers, auf die wir zugreifen möchten, gestartet wurde, bevor das Skript Set-RDSPermissions.ps1 auf dem Server ausgeführt wurde, erhält der ‚Manager‘ einen Zugriffsfehler. Die Lösung ist klar: Warten, bis der verwaltete Benutzer sich erneut anmeldet.

Hinweis 2. Nach einigen Tagen mit RDP Shadow haben wir einen interessanten Bug oder vielleicht ein Feature festgestellt: Nach dem Beenden der Shadow-Sitzung des Benutzers, zu dem wir verbunden waren, verschwindet die Sprachanzeige im Tray, und um sie zurückzubekommen, muss der Benutzer sich erneut anmelden. Wie sich herausstellte, sind wir nicht allein: eins, zwei, drei.

Das war's. Ich wünsche Ihnen und Ihren Servern Gesundheit. Wie immer freue ich mich über Ihr Feedback in den Kommentaren und bitte Sie, an der kurzen Umfrage unten teilzunehmen.

Quellen

Nur registrierte Benutzer können an der Umfrage teilnehmen. Bitte melden Sie sich an.Sind Sie an Contour interessiert?

Was verwenden Sie?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Schnelle Unterstützung / Windows-Remotehilfe1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%Sonstiges20

  • 3,2%LiteManager2

62 Benutzer haben abgestimmt. 22 Benutzer haben sich enthalten.

Quelle: habr.com

Erwerben Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster