Prenos upravljanja sej RDP

Prenos upravljanja sej RDP
V organizaciji, kjer delam, je delo na daljavo načeloma prepovedano. bil. Do prejšnjega tedna. Zdaj smo morali nujno implementirati rešitev. Od poslovanja - prilagajanje procesov novemu formatu dela, od nas - PKI s PIN kodami in žetoni, VPN, podrobno beleženje in še mnogo več.
Med drugim sem nastavljal Remote Desktop Infrastructure alias Terminal Services. Imamo več uvedb RDS v različnih podatkovnih centrih. Eden od ciljev je bil omogočiti kolegom iz sorodnih IT oddelkov interaktivno povezovanje z uporabniškimi sejami. Kot veste, za to obstaja standardni mehanizem RDS Shadow in najlažji način za delegiranje je dodelitev lokalnih skrbniških pravic na strežnikih RDS.
Spoštujem in cenim svoje sodelavce, vendar sem zelo požrešen, ko gre za razdeljevanje skrbniških pravic. 🙂 Za tiste, ki se strinjate z mano, sledite rezu.

No, naloga je jasna, zdaj pa se lotimo dela.

Korak 1

Ustvarimo varnostno skupino v imeniku Active Directory RDP_Operatorji in vanj vključimo račune tistih uporabnikov, na katere želimo prenesti pravice:

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

Če imate več mest AD, boste morali počakati, da se podvoji na vse krmilnike domene, preden nadaljujete z naslednjim korakom. To običajno ne traja več kot 15 minut.

Korak 2

Dajmo skupini pravice za upravljanje terminalskih sej na vsakem od strežnikov 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")
        }
    }
}

Korak 3

Dodajte skupino v lokalno skupino Uporabniki oddaljenega namizja na vsakem od strežnikov RDSH. Če so vaši strežniki združeni v zbirke sej, potem to naredimo na ravni zbirke:

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

Za posamezne strežnike uporabljamo pravilnik skupine, ki čaka, da se uporabi na strežnikih. Tisti, ki so preleni, da bi čakali, lahko postopek pospešijo z dobrim starim gpupdate, po možnosti centralno.

Korak 4

Pripravimo naslednjo PS skripto za “managerje”:

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 "    сессий не найдено"
    }
}

Da bo skript PS udoben za izvajanje, bomo zanj ustvarili lupino v obliki datoteke cmd z istim imenom kot skript PS:

RDSManagement.cmd

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

Obe datoteki postavimo v mapo, ki bo dostopna “upraviteljem” in jih prosimo, da se ponovno prijavijo. Zdaj se bodo z zagonom datoteke cmd lahko povezali s sejami drugih uporabnikov v načinu RDS Shadow in jih prisilili v odjavo (to je lahko koristno, ko uporabnik ne more samostojno prekiniti "viseče" seje).

Izgleda nekako takole:

Za "menadžerja"Prenos upravljanja sej RDP

Za uporabnikaPrenos upravljanja sej RDP

Nekaj ​​končnih komentarjev

Niansa 1. Če je bila uporabniška seja, nad katero poskušamo pridobiti nadzor, zagnana, preden je bil na strežniku izveden skript Set-RDSPermissions.ps1, bo »upravitelj« prejel napako pri dostopu. Rešitev je očitna: počakajte, da se upravljani uporabnik prijavi.

Niansa 2. Po nekaj dneh dela z RDP Shadow smo opazili zanimivo napako oziroma funkcijo: po koncu sence sence jezikovna vrstica v pladnju izgine za uporabnika, s katerim se povezuje, in da jo pridobi nazaj, mora uporabnik znova -Vpiši se. Kot kaže, nismo sami: čas, два, 3.

To je vse. Vam in vašim strežnikom želim dobro zdravje. Kot vedno se veselim vaših povratnih informacij v komentarjih in vas prosim, da izpolnite spodnjo kratko anketo.

viri

V anketi lahko sodelujejo samo registrirani uporabniki. Prijaviti se, prosim.

Kaj uporabljate?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Hitra pomoč/Oddaljena pomoč Windows1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%drugo20

  • 3,2%LiteManager2

Glasovali so 62 uporabniki. 22 uporabniki so se vzdržali.

Vir: www.habr.com

Dodaj komentar