๋ด๊ฐ ๊ทผ๋ฌดํ๋ ์กฐ์ง์์๋ ์์น์ ์ผ๋ก ์๊ฒฉ๊ทผ๋ฌด๋ฅผ ๊ธ์งํ๊ณ ์์ต๋๋ค. ์๋ค. ์ง๋ ์ฃผ๊น์ง. ์ด์ ์๋ฃจ์
์ ๊ธด๊ธํ๊ฒ ๊ตฌํํด์ผ ํ์ต๋๋ค. ๋น์ฆ๋์ค์์ ์๋ก์ด ์์
ํ์์ผ๋ก์ ํ๋ก์ธ์ค ์ ์, ํ ์ฝ๋ ๋ฐ ํ ํฐ์ด ํฌํจ๋ PKI, VPN, ์์ธํ ๋ก๊น
๋ฑ.
๋ฌด์๋ณด๋ค๋ ํฐ๋ฏธ๋ ์๋น์ค๋ผ๋ ์๊ฒฉ ๋ฐ์คํฌํฑ ์ธํ๋ผ ์ค์ ์ ์ฐธ์ฌํ์ต๋๋ค. ์๋ก ๋ค๋ฅธ ๋ฐ์ดํฐ ์ผํฐ์ ์ฌ๋ฌ RDS ๋ฐฐํฌ๊ฐ ์์ต๋๋ค. ๋ชฉํ ์ค ํ๋๋ ๊ด๋ จ IT ๋ถ์์ ๋๋ฃ๊ฐ ๋ํํ์ผ๋ก ์ฌ์ฉ์ ์ธ์
์ ์ฐ๊ฒฐํ ์ ์๋๋ก ํ๋ ๊ฒ์ด์์ต๋๋ค. ์์๋ค์ํผ ์ด๋ฅผ ์ํ ์ผ๋ฐ RDS ์๋์ฐ ๋ฉ์ปค๋์ฆ์ด ์์ผ๋ฉฐ ์ด๋ฅผ ์์ํ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ RDS ์๋ฒ์ ๋ํ ๋ก์ปฌ ๊ด๋ฆฌ์ ๊ถํ์ ๋ถ์ฌํ๋ ๊ฒ์
๋๋ค.
๋๋ฃ๋ค์ ์กด๊ฒฝํ๊ณ ๊ณ ๋ง์ด ๋ง์์ ๊ฐ๊ณ ์์ง๋ง, ๊ด๋ฆฌ์ ๊ถํ ๋ฐฐ๋ถ์๋ ์์ฌ์ด ๋ง์ต๋๋ค. ๐ ์ ์๊ฒ ๋์ํ์๋ ๋ถ๋ค์ ๊ณ ์์ด ๋ฐ์ผ๋ก ๋ถํ๋๋ฆฝ๋๋ค.
๊ธ์, ์ง๊ธ์ ๋น์ฆ๋์ค์ ๋ํ ์์
์ด ๋ถ๋ช
ํฉ๋๋ค.
1 ๋จ๊ณ
Active Directory์์ ๋ณด์ ๊ทธ๋ฃน ์์ฑ RDP_์ด์์ ๊ถํ์ ์์ํ๋ ค๋ ์ฌ์ฉ์์ ๊ณ์ ์ ํฌํจํฉ๋๋ค.
$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 ์๋ฒ์์ ํฐ๋ฏธ๋ ์ธ์ ์ ๊ด๋ฆฌํ ์ ์๋ ๊ถํ์ ๊ทธ๋ฃน์ ๋ถ์ฌํด ๋ณด๊ฒ ์ต๋๋ค.
์ธํธ-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)
๋จ์ผ ์๋ฒ์ ๊ฒฝ์ฐ ๋ค์์ ์ฌ์ฉํ์ญ์์ค.
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 ์คํฌ๋ฆฝํธ๋ฅผ ํธ๋ฆฌํ๊ฒ ์คํํ ์ ์๋๋ก PS ์คํฌ๋ฆฝํธ์ ๋์ผํ ์ด๋ฆ์ ๊ฐ์ง cmd ํ์ผ ํ์์ผ๋ก ์ ธ์ ๋ง๋ญ๋๋ค.
RDSManagement.cmd
@ECHO OFF
powershell -NoLogo -ExecutionPolicy Bypass -File "%~d0%~p0%~n0.ps1" %*
๋ ํ์ผ์ "๊ด๋ฆฌ์"๊ฐ ์ฌ์ฉํ ์ ์๋ ํด๋์ ๋ฃ๊ณ ๋ค์ ๋ก๊ทธ์ธํ๋๋ก ์์ฒญํฉ๋๋ค. ์ด์ cmd ํ์ผ์ ์คํํ์ฌ RDS Shadow ๋ชจ๋์์ ๋ค๋ฅธ ์ฌ์ฉ์์ ์ธ์ ์ ์ฐ๊ฒฐํ๊ณ ๊ฐ์ ๋ก ๋ก๊ทธ์์ํ ์ ์์ต๋๋ค(์ฌ์ฉ์๊ฐ ์ค์ค๋ก "๋ฉ์ถ" ์ธ์ ์ ์ข ๋ฃํ ์ ์์ ๋ ์ ์ฉํจ).
๋ค์๊ณผ ๊ฐ์ด ๋ณด์ ๋๋ค.
"๋งค๋์ "์๊ฒ
์ฌ์ฉ์๋ฅผ ์ํด
๋ช ๊ฐ์ง ๋ง์ง๋ง ๋ฐ์ธ
๋์์ค 1. ์ ์ด๊ถ์ ์ป์ผ๋ ค๋ ์ฌ์ฉ์์ ์ธ์ ์ด ์๋ฒ์์ Set-RDSPermissions.ps1 ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๊ธฐ ์ ์ ์์๋ ๊ฒฝ์ฐ "๊ด๋ฆฌ์"๋ ์ก์ธ์ค ์ค๋ฅ๋ฅผ ๋ฐ๊ฒ ๋ฉ๋๋ค. ์ฌ๊ธฐ์ ํด๊ฒฐ์ฑ ์ ๋ถ๋ช ํฉ๋๋ค. ๊ด๋ฆฌ๋๋ ์ฌ์ฉ์๊ฐ ๋ค์ ๋ก๊ทธ์ธํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ญ์์ค.
๋์์ค 2. ๋ฉฐ์น ๋์ RDP Shadow๋ก ์์
ํ ํ ๊ทธ๋ค์ ํฅ๋ฏธ๋ก์ด ๋ฒ๊ทธ ๋๋ ๊ธฐ๋ฅ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ์ฌ์ฉ์๋ ๋ค์ ๋ก๊ทธ์ธํด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ํผ์๊ฐ ์๋๋๋ค.
๊ทธ๊ฒ ๋ค์ผ. ๋๋ ๋น์ ๊ณผ ๋น์ ์ ์๋ฒ์ ๊ฑด๊ฐ์ ๊ธฐ์ํฉ๋๋ค. ์ธ์ ๋์ฒ๋ผ ์๊ฒฌ์ ๋ํ ๊ทํ์ ํผ๋๋ฐฑ์ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ์๋์ ๊ฐ๋จํ ์ค๋ฌธ ์กฐ์ฌ์ ์ฐธ์ฌํด ์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
์์ค
RDS Shadow - Windows Server 2016/2012 R2์ RDP ์ฌ์ฉ์ ์ธ์ ์ ๋ํ ์๋์ฐ ์ฐ๊ฒฐ Windows Server 2012 ์๋์ - ๋น๊ด๋ฆฌ์์๊ฒ ๊ถํ ์์ Get-LoggedOnUser ์๊ฒฉ ์์คํ ์ ๋ก๊ทธ์จํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์์งํฉ๋๋ค. PowerShell PS1 ์คํฌ๋ฆฝํธ๋ฅผ ์์ํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ ๋ก์ปฌ ๋ณด์ ๊ทธ๋ฃน์ ๋๋ฉ์ธ ์ฌ์ฉ์ ์ถ๊ฐ GPMC โ OU์ ๋ชจ๋ ์ปดํจํฐ์์ gpupdate ๊ฐ์ ์ ์ฉ
๋ฑ๋ก๋ ์ฌ์ฉ์๋ง ์ค๋ฌธ ์กฐ์ฌ์ ์ฐธ์ฌํ ์ ์์ต๋๋ค.
๋น์ ์ ๋ฌด์์ ์ฌ์ฉํฉ๋๊น?
-
8,1%AMMYY ๊ด๋ฆฌ์5
-
17,7%์ ๋๋ฐ์คํฌ11
-
9,7%๋ฐ์์จ์ด6
-
24,2%๋ผ๋ฏผ15
-
14,5%RDS ์๋์ฐ9
-
1,6%๋น ๋ฅธ ์ง์ / Windows ์๊ฒฉ ์ง์1
-
38,7%ํ๋ทฐ์ด24
-
32,3%VNC20
-
32,3%๊ธฐํ20
-
3,2%๋ผ์ดํธ๋งค๋์ 2
62๋ช
์ ์ฌ์ฉ์๊ฐ ํฌํํ์ต๋๋ค. 22๋ช
์ ์ฌ์ฉ์๊ฐ ๊ธฐ๊ถํ์ต๋๋ค.
์ถ์ฒ : habr.com