Στον οργανισμό όπου εργάζομαι, η εξ αποστάσεως εργασία απαγορεύεται καταρχήν. ήταν. Μέχρι την περασμένη εβδομάδα. Τώρα έπρεπε να εφαρμόσω επειγόντως μια λύση. Από επιχείρηση - προσαρμογή διαδικασιών σε νέα μορφή εργασίας, από εμάς - PKI με κωδικούς pin και μάρκες, VPN, αναλυτική καταγραφή και πολλά άλλα.
Μεταξύ άλλων, συμμετείχα στη ρύθμιση της υποδομής απομακρυσμένης επιφάνειας εργασίας, γνωστή και ως Terminal Services. Έχουμε πολλές αναπτύξεις RDS σε διαφορετικά κέντρα δεδομένων. Ένας από τους στόχους ήταν να δοθεί η δυνατότητα σε συναδέλφους από σχετικά τμήματα πληροφορικής να συνδέονται με συνεδρίες χρηστών διαδραστικά. Όπως γνωρίζετε, υπάρχει ένας κανονικός μηχανισμός RDS Shadow για αυτό και ο ευκολότερος τρόπος για να τον εκχωρήσετε είναι να εκχωρήσετε δικαιώματα τοπικού διαχειριστή σε διακομιστές RDS.
Σέβομαι και εκτιμώ τους συναδέλφους μου, αλλά είμαι πολύ άπληστος για τη διανομή των δικαιωμάτων διαχειριστή. 🙂 Όσοι συμφωνείτε μαζί μου, παρακαλώ κάτω από γάτα.
Λοιπόν, το καθήκον είναι ξεκάθαρο, τώρα - στην επιχείρηση.
Βήμα 1
Δημιουργήστε μια ομάδα ασφαλείας στην υπηρεσία καταλόγου Active Directory RDP_Operators και να συμπεριλάβει σε αυτό τους λογαριασμούς των χρηστών στους οποίους θέλουμε να εκχωρήσουμε δικαιώματα:
$Users = @(
"UserLogin1",
"UserLogin2",
"UserLogin3"
)
$Group = "RDP_Operators"
New-ADGroup -Name $Group -GroupCategory Security -GroupScope DomainLocal
Add-ADGroupMember -Identity $Group -Members $Users
Εάν έχετε πολλούς ιστότοπους AD, τότε προτού προχωρήσετε στο επόμενο βήμα, πρέπει να περιμένετε μέχρι να αντιγραφεί σε όλους τους ελεγκτές τομέα. Αυτό συνήθως δεν διαρκεί περισσότερο από 15 λεπτά.
Βήμα 2
Ας δώσουμε στην ομάδα τα δικαιώματα για τη διαχείριση περιόδων σύνδεσης τερματικού σε καθέναν από τους διακομιστές RDSH:
Set-RDSPermissions.ps1
$Group = "RDP_Operators"
$Servers = @(
"RDSHost01",
"RDSHost02",
"RDSHost03"
)
ForEach ($Server in $Servers) {
#Делегируем право на теневые сессии
$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 = "успешно"
If ($retVal.ReturnValue -ne 0) {
$opstatus = "ошибка"
}
Write-Host ("Делегирование прав на теневое подключение группе " +
$Group + " на сервере " + $Server + ": " + $opstatus + "`r`n")
}
}
}
Βήμα 3
Προσθέστε μια ομάδα σε μια τοπική ομάδα Χρήστες απομακρυσμένης επιφάνειας εργασίας σε καθέναν από τους διακομιστές RDSH. Εάν οι διακομιστές σας συνδυάζονται σε συλλογές περιόδων σύνδεσης, τότε το κάνουμε αυτό σε επίπεδο συλλογής:
$Group = "RDP_Operators"
$CollectionName = "MyRDSCollection"
[String[]]$CurrentCollectionGroups = @(Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup).UserGroup
Set-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup ($CurrentCollectionGroups + $Group)
Για μεμονωμένους διακομιστές, χρησιμοποιήστε , περιμένοντας να εφαρμοστεί στους διακομιστές. Για όσους είναι πολύ τεμπέληδες να περιμένουν, μπορείτε να αναγκάσετε τη διαδικασία με το παλιό καλό gpupdate, κατά προτίμηση .
Βήμα 4
Ας ετοιμάσουμε το ακόλουθο σενάριο PS για "διαχειριστές":
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 "Введите логин пользователя"
Write-Host "Поиск RDP-сессий пользователя на серверах..."
$SessionList = @()
ForEach ($Server in $Servers) {
$TargetSession = $null
Write-Host " Опрос сервера $Server"
Try {
$TargetSession = Get-LoggedOnUser -ComputerName $Server | Where-Object {$_.UserName -eq $UserLogin}
}
Catch {
Write-Host "Ошибка: " $Error[0].Exception.Message -ForegroundColor Red
Continue
}
If ($TargetSession) {
Write-Host " Найдена сессия с ID $($TargetSession.ID) на сервере $Server" -ForegroundColor Yellow
Write-Host " Что будем делать?"
Write-Host " 1 - подключиться к сессии"
Write-Host " 2 - завершить сессию"
Write-Host " 0 - ничего"
$Action = Read-Host -Prompt "Введите действие"
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 " сессий не найдено"
}
}
Για να διευκολύνουμε την εκτέλεση του σεναρίου PS, θα δημιουργήσουμε ένα κέλυφος για αυτό με τη μορφή ενός αρχείου cmd με το ίδιο όνομα με το σενάριο PS:
RDSManagement.cmd
@ECHO OFF
powershell -NoLogo -ExecutionPolicy Bypass -File "%~d0%~p0%~n0.ps1" %*
Βάζουμε και τα δύο αρχεία σε ένα φάκελο που θα είναι διαθέσιμος στους «διαχειριστές» και τους ζητάμε να ξανασυνδεθούν. Τώρα, εκτελώντας το αρχείο cmd, θα μπορούν να συνδεθούν με τις συνεδρίες άλλων χρηστών σε λειτουργία RDS Shadow και να τους αναγκάσουν να αποσυνδεθούν (είναι χρήσιμο όταν ο χρήστης δεν μπορεί να τερματίσει μόνος του τη συνεδρία "hung").
Μοιάζει κάπως έτσι:
για τον "διευθυντή"
Για τον χρήστη
Μερικές τελευταίες παρατηρήσεις
Απόχρωση 1. Εάν η περίοδος λειτουργίας του χρήστη στον οποίο προσπαθούμε να αποκτήσουμε τον έλεγχο ξεκίνησε πριν από την εκτέλεση του σεναρίου Set-RDSPermissions.ps1 στον διακομιστή, τότε ο "διαχειριστής" θα λάβει ένα σφάλμα πρόσβασης. Η λύση εδώ είναι προφανής: περιμένετε να επανασυνδεθεί ο διαχειριζόμενος χρήστης.
Απόχρωση 2. Μετά από αρκετές ημέρες εργασίας με το RDP Shadow, παρατήρησαν ένα ενδιαφέρον είτε ένα σφάλμα είτε ένα χαρακτηριστικό: μετά το τέλος της περιόδου λειτουργίας σκιάς, ο χρήστης στον οποίο συνδέθηκαν εξαφανίζει τη γραμμή γλώσσας στο δίσκο και για να την επιστρέψει, ο χρήστης πρέπει να συνδεθεί ξανά. Όπως αποδεικνύεται, δεν είμαστε μόνοι: , , .
Αυτό είναι όλο. Εύχομαι υγεία σε εσάς και τους διακομιστές σας. Όπως πάντα, περιμένω τα σχόλιά σας στα σχόλια και σας ζητώ να συμμετάσχετε σε μια σύντομη έρευνα παρακάτω.
πηγές
Μόνο εγγεγραμμένοι χρήστες μπορούν να συμμετάσχουν στην έρευνα. , Σας παρακαλούμε.
Τι χρησιμοποιείς?
8,1%AMMYY Διαχειριστής 5
17,7%AnyDesk11
9,7%DameWare6
24,2%Radmin15
14,5%RDS Shadow9
1,6%Quick Assist / Windows Remote Assistance1
38,7%TeamViewer24
32,3%VNC20
32,3%άλλα20
3,2%LiteManager2
Ψήφισαν 62 χρήστες. 22 χρήστες απείχαν.
Πηγή: www.habr.com
