Delegăm gestionarea sesiunilor RDP

Delegăm gestionarea sesiunilor RDP
În organizația în care lucrez, munca de la distanță era interzisă în principiu. A fost. Până săptămâna trecută. Acum a fost necesar să implementăm urgent o soluție. Din partea afacerii — adaptarea proceselor la noul format de lucru, din partea noastră — PKI cu coduri pin și token-uri, VPN, logare detaliată și multe alte lucruri.
Pe lângă toate acestea, m-am ocupat de configurarea infrastructurii pentru birourile de la distanță, adică a serviciului de terminale. Avem câteva desfășurări RDS în diferite centre de date. Una dintre sarcini a fost să le oferim colegilor din departamentele adiacente IT posibilitatea de a se conecta la sesiuni de utilizator în mod interactiv. Așa cum se știe, pentru aceasta există mecanismul standard RDS Shadow, iar cea mai simplă modalitate de a-l delega este să acordăm drepturi de administrator local pe serverele RDS.
Îi respect și îi apreciez pe colegii mei, dar sunt foarte zgârcit cu acordarea drepturilor de administrator. 🙂 Cei care sunt de acord cu mine sunt rugați să citească mai departe.

Ei bine, sarcina este clară, acum — la treabă.

Pasul 1

Să creăm un grup de securitate în Active Directory RDP_Operators și să includem în el conturile utilizatorilor căror dorim să le delegăm drepturile:

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

Dacă aveți mai multe site-uri AD, înainte de a trece la pasul următor, trebuie să așteptați până când va fi replicat pe toate controlerele domeniului. De obicei, acest lucru durează nu mai mult de 15 minute.

Pasul 2

Să dăm grupului drepturi de gestionare a sesiunilor terminale pe fiecare dintre serverele RDSH:

Set-RDSPermissions.ps1

$Group = "RDP_Operators"
$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)
ForEach ($Server in $Servers) {
    #Delegăm dreptul la sesiuni shadow
    $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 = "reușit"
        If ($retVal.ReturnValue -ne 0) {
            $opstatus = "eroare"
        }
        Write-Host ("Delegarea drepturilor pentru conectarea shadow a grupului " +
            $Group + " pe serverul " + $Server + ": " + $opstatus + "`r`n")
        }
    }
}

Pasul 3

Să adăugăm grupul în grupul local Utilizatori de birou la distanță pe fiecare dintre serverele RDSH. Dacă aveți servere grupate în colecții de sesiuni, faceți acest lucru la nivelul colecției:

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

Pentru serverele individuale, se utilizează politica de grup, așteptând ca aceasta să se aplice pe servere. Cei care nu au răbdare pot forța procesul cu ajutorul vechiului și bunului gpupdate, de preferat centrizat.

Pasul 4

Să pregătim pentru „manageri” un astfel de script 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 "Introduceți numele utilizatorului"
Write-Host "Căutare sesiuni RDP pentru utilizator pe servere..."
$SessionList = @()
ForEach ($Server in $Servers) {
    $TargetSession = $null
    Write-Host "  Interogare server $Server"
    Try {
        $TargetSession = Get-LoggedOnUser -ComputerName $Server | Where-Object {$_.UserName -eq $UserLogin}
    }
    Catch {
        Write-Host "Eroare: " $Error[0].Exception.Message -ForegroundColor Red
        Continue
    }
    If ($TargetSession) {
        Write-Host "    Sesiune găsită cu ID $($TargetSession.ID) pe serverul $Server" -ForegroundColor Yellow
        Write-Host "    Ce dorim să facem?"
        Write-Host "      1 - conectați-vă la sesiune"
        Write-Host "      2 - terminați sesiunea"
        Write-Host "      0 - nimic"
        $Action = Read-Host -Prompt "Introduceți acțiunea"
        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 "    nu au fost găsite sesiuni"
    }
}

Pentru a lansa scriptul PS mai ușor, vom crea o wrapper sub formă de fișier cmd cu același nume ca și scriptul PS:

RDSManagement.cmd

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

Încărcăm ambele fișiere în folderul accesibil «administratorilor» și le cerem să se reconecteze. Acum, rulând fișierul cmd, ei vor putea accesa sesiunile altor utilizatori în modul RDS Shadow și le pot deconecta forțat (util când utilizatorul nu poate finaliza singur o sesiune «înghețată»).

Arată cam așa:

Pentru «administrator»Delegăm gestionarea sesiunilor RDP

Pentru utilizatorDelegăm gestionarea sesiunilor RDP

Câteva observații finale

Nuansă 1. Dacă sesiunea utilizatorului la care încercăm să obținem control a fost inițiată înainte de a rula scriptul Set-RDSPermissions.ps1 pe server, atunci «administratorul» va primi o eroare de acces. Soluția este evidentă: așteptați până când utilizatorul gestionat se reconectează.

Nuansă 2. După câteva zile de lucru cu RDP Shadow, am observat un bug sau poate o caracteristică interesantă: după terminarea sesiunii shadow la utilizatorul la care ne-am conectat, dispare bara de limbă din sistemul de sistem, iar pentru a o restabili, utilizatorul trebuie să se reconecteze. Se pare că nu suntem singurii: unu, doi, trei.

Asta e tot. Vă doresc sănătate dumneavoastră și serverelor dumneavoastră. Ca de obicei, aștept feedback în comentarii și vă rog să completați un scurt sondaj mai jos.

Surse

Numai utilizatorii înregistrați pot participa la sondaj. Conectați-vă, vă rugăm.

Ce folosiți?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Quick Assist / Asistență la distanță Windows1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%altceva20

  • 3,2%LiteManager2

Au votat 62 de utilizatori. S-au abținut 22 de utilizatori.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster