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 , und warten, bis sie auf den Servern angewendet wird. Wer es eilig hat, kann den Prozess mit dem bewĂ€hrten gpupdate erzwingen, vorzugsweise .
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â
FĂŒr den Benutzer
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: , , .
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. 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
