RDP oturumlarının yönetimini devretme

RDP oturumlarının yönetimini devretme
Çalıştığım kurumda prensip olarak uzaktan çalışma yasaktır. Öyleydi. Geçen haftaya kadar. Artık acilen bir çözüm uygulamamız gerekiyordu. İş uyarlama süreçlerinden yeni bir çalışma formatına kadar, bizden - PIN kodları ve belirteçleri olan PKI, VPN, ayrıntılı günlük kaydı ve çok daha fazlası.
Diğer işlerin yanı sıra Uzak Masaüstü Altyapısı yani Terminal Hizmetlerini kuruyordum. Farklı veri merkezlerinde çeşitli RDS dağıtımlarımız var. Hedeflerden biri, ilgili BT departmanlarındaki meslektaşların kullanıcı oturumlarına etkileşimli olarak bağlanmasını sağlamaktı. Bildiğiniz gibi bunun için standart bir RDS Shadow mekanizması mevcut ve bunu devretmenin en kolay yolu RDS sunucularında yerel yönetici hakları vermektir.
Meslektaşlarıma saygı duyuyorum ve değer veriyorum, ancak yönetici haklarının dağıtımı konusunda çok açgözlüyüm. 🙂 Benimle aynı fikirde olanlar lütfen kesimi takip etsin.

Pekala, görev açık, şimdi işe koyulalım.

1 Adım

Active Directory'de bir güvenlik grubu oluşturalım RDP_Operators ve hakları devretmek istediğimiz kullanıcıların hesaplarını buna dahil edin:

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

Birden fazla AD siteniz varsa, bir sonraki adıma geçmeden önce tüm etki alanı denetleyicilerine kopyalanana kadar beklemeniz gerekecektir. Bu genellikle 15 dakikadan fazla sürmez.

2 Adım

Gruba, RDSH sunucularının her birindeki terminal oturumlarını yönetme haklarını verelim:

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 Adım

Grubu yerel gruba ekleyin Uzak Masaüstü Kullanıcıları RDSH sunucularının her birinde. Sunucularınız oturum koleksiyonları halinde birleştirilmişse bunu koleksiyon düzeyinde yaparız:

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

Tek sunucular için kullandığımız Grup ilkesisunuculara uygulanması bekleniyor. Beklemek için fazla tembel olanlar, tercihen eski güzel gpupdate'i kullanarak süreci hızlandırabilirler. merkezi.

4 Adım

“Yöneticiler” için aşağıdaki PS scriptini hazırlayalım:

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 betiğinin çalıştırılmasını kolaylaştırmak için, PS betiğiyle aynı adı taşıyan cmd dosyası biçiminde bir kabuk oluşturacağız:

RDSManagement.cmd

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

Her iki dosyayı da “yöneticilerin” erişebileceği bir klasöre koyuyoruz ve onlardan yeniden giriş yapmalarını istiyoruz. Artık cmd dosyasını çalıştırarak, RDS Gölge modundaki diğer kullanıcıların oturumlarına bağlanabilecekler ve onları oturumu kapatmaya zorlayabilecekler (bu, kullanıcı "asılı" bir oturumu bağımsız olarak sonlandıramadığında yararlı olabilir).

Bu gibi bir şey görünüyor:

"Yönetici" içinRDP oturumlarının yönetimini devretme

Kullanıcı içinRDP oturumlarının yönetimini devretme

Son birkaç yorum

Nüans 1. Kontrolü ele geçirmeye çalıştığımız kullanıcı oturumu, Set-RDSPermissions.ps1 betiği sunucuda çalıştırılmadan önce başlatılmışsa, “yönetici” erişim hatası alacaktır. Buradaki çözüm açıktır: yönetilen kullanıcı oturum açana kadar bekleyin.

Nüans 2. RDP Shadow ile birkaç gün çalıştıktan sonra ilginç bir hata veya özellik fark ettik: Gölge oturumunun bitiminden sonra, bağlanan kullanıcı için tepsideki dil çubuğu kayboluyor ve onu geri almak için kullanıcının yeniden yapması gerekiyor. -giriş yapmak. Görünen o ki yalnız değiliz: zaman, iki, üç.

Bu kadar. Size ve sunucularınıza sağlık diliyorum. Her zaman olduğu gibi yorumlarda görüşlerinizi bekliyorum ve aşağıdaki kısa ankete katılmanızı rica ediyorum.

kaynaklar

Ankete sadece kayıtlı kullanıcılar katılabilir. Giriş yapLütfen.

Ne kullaniyorsun?

  • %8,1AMMYY Admin5

  • %17,7AnyDesk11

  • %9,7DameWare6

  • %24,2Radmin15

  • %14,5RDS Gölge9

  • %1,6Hızlı Yardım / Windows Uzaktan Yardım1

  • %38,7TeamViewer24

  • %32,3VNC20

  • %32,3diğer20

  • %3,2LiteManager2

62 kullanıcı oy kullandı. 22 kişi çekimser kaldı.

Kaynak: habr.com

Yorum ekle