Remote Desktop Services – Funzionalità di Shadowing delle Sessioni ed implementazione di Assistenza Remota
La funzionalità di Shadowing delle sessioni remote è presente da diverso tempo in RDS, sebbene abbia vissuto fasi alterne nel tempo, come è possibile leggere in questo Post di Ermanno Goletto. Per chi non la conoscesse, si tratta della possibilità di accedere, in modalità visualizzazione o controllo, ad una sessione RDP attiva su un session Host.
In una infrastruttura RDS è possibile sfruttare questa funzione per fornire assistenza e supporto agli utenti, interagendo con le loro attività.
Di default è attiva ed è utilizzabile direttamente da Server Manager nel contesto di gestione della Farm RDS, è sufficiente individuare la Collection, ed identificare la sessione a cui connettersi
Server Manager\Remote Desktop Services\Collections\Desktop1
Identificata la sessione, con il dato DX selezionare Shadow
Figura 1 selzione della sessione connessa
Si apre a questo punto una maschera in cui viene richiesto di specificare la modalità di connessione, ossia se in sola visualizzazione o in controllo e quindi in piena interazione con l’utente, è anche possibile specificare se richiedere all’utente il consenso alla connessione.
Figura 2 modalità di connessione
A questo punto proseguendo con OK all’utente connesso viene proposto un messaggio che lo informa della richiesta di accesso
Figura 3 prompt di conferma della richiesta di accesso
Non appena ottenuta la conferma la sessione può essere controllata o visualizzata da remoto
Questo comportamento, come detto prima, è di default e l’accesso è possibile in quanto il permesso di Shadowing sulle connessioni RDP è concesso agli utenti Amministratori.
Gestione dei permessi di Shadowing
Nel caso sia necessario garantire questa funzionalità ad utenti non amministratori è necessario che il permesso venga esplicitato per i vari utenti, direttamente sulla connessione RDP dei singoli Session Host
Per una gestione più semplice è preferibile creare un gruppo all’interno di AD ed assegnare il permesso di Shadowing a questo gruppo, successivamente verranno definiti come membri i vari utenti che dovranno operare in modalità Shadow sulle sessioni RDS
La modifica dei permessi di default avviene con un comando che opera direttamente tramite WMI sulle proprietà della connessione RDP dei Session Host. Tramite GPO invece è possibile modificare la modalità di accesso alle sessioni RDS.
Impostazioni tramite Wmic (WMI)
Supponendo di aver creato sul dominio ICTPOWER il gruppo UtentiRdsShadowing il comando per assegnarne i permessi è il seguente
wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSPermissionsSetting WHERE (TerminalName=”RDP-Tcp”) CALL AddAccount “ictpower\UtentiRdsShadowing”,2
più in dettaglio vediamo che viene identificato il nome della connessione RDP con TerminalName RDP-Tcp e con AddAccount viene definito il gruppo ictpower\UtentiRdsShadowing il parametro al termine del comando prevede 3 valori:
- 0 = WINSTATION_GUEST_ACCESS
- 1 = WINSTATION_USER_ACCESS
-
2 = WINSTATION_ALL_ACCESS
Per verificare le impostazioni correnti è possibile utilizzare il comando
wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSPermissionsSetting
il cui output sarà simile a questo
Caption DenyAdminPermissionForCustomization Description InstallDate Name PolicySourceDenyAdminPermissionForCustomization Status StringSecurityDescriptor TerminalName
O:SYG:SYD:(A;;CC;;;IU)(A;;0xf03bf;;;SY)(A;;CCSWLOSDRCWDWO;;;LS)(A;;CCLO;;;NS)(A;;0xf03bf;;;BA)(A;;CCWPCR;;;RD)S:NO_ACCESS_CONTROL Console
O:SYG:SYD:(A;;0xf03bf;;;S-1-5-21-263436683-1377918197-1349984968-1110)(A;;CC;;;IU)(A;;0xf03bf;;;SY)(A;;CCSWLOSDRCWDWO;;;LS)(A;;CCLO;;;NS)(A;;0xf03bf;;;BA)(A;;CCWPCR;;;RD)S:(AU;FA;CCWPCR;;;WD) RDP-Tcp
In grassetto nell’ultima riga è riportato il SID del gruppo ictpower\UtentiRdsShadowing, per poter risalire al nome del gruppo dato il SID il comando è sufficiente utilizzare il Cmd-Let
1 |
Get-ADGroup -Identity S-1-5-21-263436683-1377918197-1349984968-1110 |
Se fosse necessario ricondurre le impostazioni ad un valore di default è possibile utilizzare il comando seguente
1 |
wmic /namespace:\\root\CIMV2\TerminalServices PATH WIN32_TSPermissionsSetting WHERE (TerminalName="RDP-Tcp") CALL RestoreDefaults |
dopo la variazione dei permessi di accesso tramite il comando VMIC è necessario riavviare il servizio RDS con il comando
1 |
net stop "Remote Desktop Services" && net start "Remote Desktop Services" |
Impostazioni tramite Group Policy (GPO)
Le impostazioni per mezzo delle GPO definiscono la modalità con cui gli utenti che richiedono di effettuare lo shadow potranno accedere alla Sessione
La Group Policy è configurabile in Computer/Policies/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Connection
Figura 4 impostazione delle modalità di shadowing
Si può definire l’accesso in controllo completo con o senza autorizzazione utente, l’accesso in sola modalità visualizzazione con o senza autorizzazione esplicita dell’utente ed una ulteriore impostazione che nega qualunque tipo di accesso allo shadow delle sessioni, chiaramente questa configurazione è indipendente dai permessi di accesso impostati con WMIC che devono comunque essere dichiarati.
La Group Policy vista in figura 4 è configurabile a livello Macchina e quindi per qualunque utente che ha una connessione sul Session Host, nel caso fosse necessario definire regole diverse di controllo delle sessioni RDS in base agli utenti collegati, è possibile attivare una Group Policy nel contesto utente e come tale applicata solamente a determinati account.
La Group Policy è configurabile in User/Policies/Windows Components/Remote Desktop Services/Remote Desktop Session Host/Connection
Figura 5 impostazioni modalità di shadowing nel contesto utente
La GPO deve essere assegnata alla OU dove risiede l’utente che deve essere controllato e non all’utente che effettua il controllo sulla sessione RDS, per il resto le impostazioni sono identiche a quelle viste per il contesto macchina.
Utilizzo di Script in Powershell e del client RDS per la gestione delle attività di Shadowing
Fino a questo punto abbiamo visto le impostazioni dell’ambiente RDS e la modalità di accesso allo Shadowing avviene a partire dal Server Manager e dalle funzioni disponibili nella sua interfaccia.
Essendo a conoscenza dell’Id della sessione RDS su un determinato Session Host, è possibile eseguire il client RDP in modo che effettui il mirroring della sessione voluta.
Supponendo di eseguire l’accesso alla sessione 10 sul server RDSH01 in modalità di controllo, dovremo eseguire il comando MSTSC con le impostazioni seguenti:
1 |
Mstsc.exe /v: /shadow:10 /control |
Nel caso in cui non sia necessario eseguire il controllo ma solo la visualizzazione della sessione è sufficiente omettere l’opzione /control
L’individuazione dell’id della sessione non è propriamente immediato, soprattutto nel caso in cui l’accesso alla Farm RDS avviene con un unico utente comune a più connessioni, l’elenco all’interno del Server Manager presenta in questo caso molteplici connessioni tutte originate dal medesimo utente.
E’ necessario quindi individuare l’ID della sessione direttamente dall’interno della stessa eseguendo il command-let Get-Process
1 |
(Get-Process -PID $pid).SessionID |
Ottenuto il valore numerico relativo alla sessione, è possibile effettuarne il mirroring come visto sopra.
Scenario di utilizzo delle funzioni di Shadow
in ambienti distribuiti, con operatori che svolgono la funzione di assistenza nei confronti degli utenti della farm RDS è importante permettere che da un lato l’operatore che richiede supporto possa indicare in modo preciso le informazioni sulla propria connessione, e dall’altro il personale addetto al supporto possa accedere in visualizzazione o controllo della sessione senza possibilità di errori.
Qui di seguito sono riportati due script in PowerShell che permettono in modo semplice l’individuazione delle informazioni sulla sessione connessa alla Farm RDS, e la creazione guidata di una sessione di accesso in mirror o controllo della sessione stessa, chiaramente il primo script dovrà essere eseguito all’interno della sessione, ed il secondo script dovrà essere eseguito da una qualunque postazione di rete con le credenziali di un utente che dispone dei permessi di accesso in Shadow come visto in precedenza.
Per fare si che ogni utente che accede alla farm RDS abbia disponibile sul desktop il collegamento allo script di identificazione della sessione è possibile usare le Group Policy.
Identificazione della sessione RDS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#### Script per identificare (dato un desktop in RDS) il client da cui viene avviata la sessione, il server Session Host su cui si è collegati,e l'identificativo di Sessione # dichiarazione Variabili e recupero info di sessione $TsSessionID = (Get-Process -PID $pid).SessionID $TsServerName = $env:COMPUTERNAME $TsClientName = $env:CLIENTNAME ## Creazione della stringa messaggio inserita nel Pop-Up Utente $InfoSessioneTS = "Nome Client: " + $TsClientName + "`r`n" + "Nome Server: " + $TsServerName + "`r`n" + "Identificativo Sessione RDS ID: " +$TsSessionID Write-Host $InfoSessioneTS ### Add-Type -AssemblyName System.Windows.Forms # Costruzione della Msg-Box function Read-MessageBoxDialog([string]$Message, [string]$WindowTitle, [System.Windows.Forms.MessageBoxButtons]$Buttons = [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]$Icon = [System.Windows.Forms.MessageBoxIcon]::None) { return [System.Windows.Forms.MessageBox]::Show($Message, $WindowTitle, $Buttons, $Icon) } $buttonClicked = Read-MessageBoxDialog -Message $InfoSessioneTS -WindowTitle "IctPower " -Buttons OK -Icon Information |
Una volta eseguito questo script costruisce una MsgBox con riassunte le informazioni utili ad identificare la sessione
Figura 6 informazioni di sessione
Lo script sarà avviato direttamente da un file .cmd opportunamente strutturato e nel caso si voglia utilizzare una GPO per la pubblicazione del link sul desktop, questa dovrà riferirsi al file di avvio
start /min C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe C:\supporto\IdentificaSessione.ps1
Gestione guidata del di Mirror della sessione RDS
Individuata la sessione all’interno della Farm RDS è possibile utilizzare questo script per creare l’accesso in Shadow alla sessione stessa, lo script è più complesso nella sua costruzione ma non fa altro che creare una check-box per ogni Session-Host presente, consentire l’immissione del valore dell’ID sessione ed un ulteriore check-box relativo alla funzione di controllo o semplice visualizzazione della sessione, ottenute queste impostazioni viene strutturato ed eseguito il comando MSTSC come visto sopra.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
###### Script per l'avvio di una sessione Shadow su RDSSession Host ###### Per ogni Controllo System.Drawing.Point(x,y) per posizionamento nel Form (1,1) in alto a sx ###### Per ogni Session Host è necessario definire il comando VMIC di concessione della sessione Shadow al Gruppo/utenti Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # Creazione del Form generale $form = New-Object System.Windows.Forms.Form $form.Text = 'ICTPower' $form.Size = New-Object System.Drawing.Size(500,300) $form.StartPosition = 'CenterScreen' # Creazione del Tasto Ok $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(150,220) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.AcceptButton = $OKButton $form.Controls.Add($OKButton) # Creazione del Tasto Cancel $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(300,220) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Cancel' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $form.CancelButton = $CancelButton $form.Controls.Add($CancelButton) # Definizione di una Etichetta di Commento Generale $TestoForm = New-Object System.Windows.Forms.Label $TestoForm.Location = New-Object System.Drawing.Point(10,20) $TestoForm.Size = New-Object System.Drawing.Size(280,20) $TestoForm.Text = 'Inserire le Informazioni sulla Sessione Remota:' $form.Controls.Add($TestoForm) ##### Costruzione Area Inserimento ID Sessione ##### Etichetta e Textbox $TestoRDSId = New-Object System.Windows.Forms.Label $TestoRDSId.Location = New-Object System.Drawing.Point(10,40) $TestoRDSId.Size = New-Object System.Drawing.Size(130,20) $TestoRDSId.Text = 'Id Sessione RDS:' $Form.Controls.Add($TestoRDSId) $TsSessionID = New-Object System.Windows.Forms.TextBox $TsSessionID.Location = New-Object System.Drawing.Point(150,40) $TsSessionID.Size = New-Object System.Drawing.Size(40,20) $form.Controls.Add($TsSessionID) ##### Costruzione Area Inserimento checkbox Monitoraggio/Controllo #Checkbox Controllo $CheckboxTsSessionControl = New-Object System.Windows.Forms.CheckBox $CheckboxTsSessionControl.Location = New-Object System.Drawing.Point(250,40) $CheckboxTsSessionControl.Size = New-Object System.Drawing.Size(210,30) $CheckboxTsSessionControl.Text = "Selezionare per Controllo Sessione - Default solo Visualizzazione" $form.Controls.Add($CheckboxTsSessionControl) #### Costruzione Area Inserimento CheckBox di definizione dei SessionHost #Checkbox RdSh01 $Checkboxrdsh01 = New-Object System.Windows.Forms.Checkbox $Checkboxrdsh01.Location = New-Object System.Drawing.Point(150,80) $Checkboxrdsh01.Size = New-Object System.Drawing.Size(300,20) $Checkboxrdsh01.Text = "RDSH01" $Form.Controls.Add($Checkboxrdsh01) #Checkbox RdSh02 $CheckboxRdsh02 = New-Object System.Windows.Forms.Checkbox $CheckboxRdsh02.Location = New-Object System.Drawing.Point(150,110) $CheckboxRdsh02.Size = New-Object System.Drawing.Size(300,20) $CheckboxRdsh02.Text = "RDSH02" $Form.Controls.Add($CheckboxRdsh02) #Checkbox RdSh03 $CheckboxRdsh03 = New-Object System.Windows.Forms.Checkbox $CheckboxRdsh03.Location = New-Object System.Drawing.Point(150,140) $CheckboxRdsh03.Size = New-Object System.Drawing.Size(300,20) $CheckboxRdsh03.Text = "RDSH03" $Form.Controls.Add($CheckboxRdsh03) #Checkbox RdSh04 $CheckboxRdsh04 = New-Object System.Windows.Forms.Checkbox $CheckboxRdsh04.Location = New-Object System.Drawing.Point(150,170) $CheckboxRdsh04.Size = New-Object System.Drawing.Size(300,20) $CheckboxRdsh04.Text = "RDSH04" $Form.Controls.Add($CheckboxRdsh04) ## Carico il Form $form.Add_Shown({$TestoForm.Select()}) $result = $form.ShowDialog() $form.Topmost = $true ### Attribuzione Switch di controllo alla stringa di Connessione if ( $CheckboxTsSessionControl.Checked){ $TsSessionControl = "/Control" } # Avvio di MSTSC sulla base degli input definiti $RDSId = $TsSessionID.Text if (($result -eq [System.Windows.Forms.DialogResult]::OK) -and (($Checkboxrdsh01.Checked) -or ($CheckboxRdsh02.Checked)-or ($CheckboxRdsh03.Checked) -or ($CheckboxRdsh04.Checked))) { if ($Checkboxrdsh01.Checked) { $RdsHost = "rdsh01.ictpower.local" Write-Host $RdsHost } elseif ($CheckboxRdsh02.Checked) { $RdsHost = "rdsh02.ictpower.local" Write-Host $RdsHost } elseif ($CheckboxRdsh03.Checked) { $RdsHost = "rdsh03.ictpower.local" Write-Host $RdsHost } elseif ($CheckboxRdsh04.Checked) { $RdsHost = "rdsh04.ictpower.local" Write-Host $RdsHost } Mstsc.exe /v:$RdsHost /shadow:$RDSId $TsSessionControl } |
Figura 7
La figura qui sopra riporta il form che viene creato per mezzo di questo script, premendo ok in questo caso si effettua il mirror della sessione numero 5 sul Session Host RDSH01
Considerazioni
Le soluzioni proposte in questo articolo prendono spunto da un caso reale dove si è reso necessario permettere ad un gruppo di utenti di accedere in modalità di consultazione o controllo al fine di fornire assistenza agli utilizzatori su un certo numero di applicativi distribuiti da una Farm RDS, la scelta di implementazione della soluzione ha previsto l’impiego di pochi utenti di accesso comuni a numerosi utenti singoli, e demandando la successiva autenticazione a livello applicativo. Questa modalità ha evidenziato le problematiche esposte sopra relative all’identificazione delle singole Sessioni.