[{"data":1,"prerenderedAt":2524},["ShallowReactive",2],{"post:\u002F2025\u002F09\u002F17\u002Fpowershell-windows-server-harden-rdp-without-breaking-access\u002F":3},{"post":4,"newer":2485,"older":2495,"related":2504,"series":2522},{"id":5,"title":6,"body":7,"canonical":2467,"categories":2468,"date":2471,"description":2472,"extension":2473,"featured":2474,"hero":2475,"image":2475,"meta":2476,"navigation":683,"path":2477,"readingTime":396,"seo":2478,"series":2475,"seriesOrder":2475,"sites":2479,"source":2475,"stem":2480,"tags":2481,"updated":2475,"url":2483,"__hash__":2484},"blog\u002Fblog\u002F2025\u002F09\u002F17\u002Fpowershell-windows-server-harden-rdp-without-breaking-access.md","PowerShell: Windows Server – Harden RDP Without Breaking Access",{"type":8,"value":9,"toc":2459},"minimark",[10,14,19,47,51,198,202,205,236,239,294,297,305,308,358,362,2270,2274,2391,2395,2455],[11,12,13],"p",{},"RDP is still the most common way I end up on a Windows Server box, and it's also one of the first things I harden on a fresh build, because the defaults are more permissive than they need to be. Network Level Authentication is on by default on current Windows Server releases, but the security layer defaults to Negotiate (which can fall back to native RDP encryption with no server authentication), sessions can sit idle or disconnected forever, and the Remote Desktop firewall rules accept any source address. Locking RDP down to the point where you lock yourself out is a real risk, so this script leans on an explicit allowlist instead of guessing, checks for Group Policy that would override it, and is meant to be run from an address that's already on that allowlist.",[15,16,18],"h2",{"id":17},"requirements","Requirements",[20,21,22,26,29,41,44],"ul",{},[23,24,25],"li",{},"Windows Server 2016 or later, elevated PowerShell (Administrator).",[23,27,28],{},"Remote Desktop already enabled. The built-in \"Remote Desktop\" firewall rule group exists on every Windows Server install; RDP for administration is part of the base OS, not the RDS role.",[23,30,31,32,36,37,40],{},"The built-in ",[33,34,35],"code",{},"NetSecurity"," module for the firewall changes, and the ",[33,38,39],{},"root\\cimv2\\TerminalServices"," WMI namespace (present by default) for the Group Policy check.",[23,42,43],{},"Clients that support NLA (Remote Desktop Connection 6.0 or later) and TLS 1.2. Every supported Windows client does.",[23,45,46],{},"Your management network's address ranges, and a console you can reach without RDP (iDRAC, iLO, hypervisor console) the first time you run it.",[15,48,50],{"id":49},"parameters","Parameters",[52,53,54,73],"table",{},[55,56,57],"thead",{},[58,59,60,64,67,70],"tr",{},[61,62,63],"th",{},"Name",[61,65,66],{},"Type",[61,68,69],{},"Required",[61,71,72],{},"Description",[74,75,76,96,116,133,148,162,184],"tbody",{},[58,77,78,84,90,93],{},[79,80,81],"td",{},[33,82,83],{},"AllowedSource",[79,85,86,87],{},"string",[88,89],"span",{},[79,91,92],{},"Yes",[79,94,95],{},"IP addresses or CIDR ranges allowed to reach RDP. Must include the range you are connecting from.",[58,97,98,103,106,109],{},[79,99,100],{},[33,101,102],{},"IdleTimeoutMinutes",[79,104,105],{},"int",[79,107,108],{},"No",[79,110,111,112,115],{},"Idle time before an active session is disconnected. Default ",[33,113,114],{},"30",".",[58,117,118,123,125,127],{},[79,119,120],{},[33,121,122],{},"DisconnectedSessionTimeoutMinutes",[79,124,105],{},[79,126,108],{},[79,128,129,130,115],{},"How long a disconnected session is kept before it's ended. Default ",[33,131,132],{},"60",[58,134,135,140,143,145],{},[79,136,137],{},[33,138,139],{},"DisableDriveRedirection",[79,141,142],{},"switch",[79,144,108],{},[79,146,147],{},"Blocks client drive mapping (and clipboard file copy) into sessions.",[58,149,150,155,157,159],{},[79,151,152],{},[33,153,154],{},"DisableClipboardRedirection",[79,156,142],{},[79,158,108],{},[79,160,161],{},"Blocks clipboard sharing between client and session.",[58,163,164,169,171,173],{},[79,165,166],{},[33,167,168],{},"AllowRestrictedAdmin",[79,170,142],{},[79,172,108],{},[79,174,175,176,179,180,183],{},"Lets clients connect with Restricted Admin mode or Remote Credential Guard (",[33,177,178],{},"DisableRestrictedAdmin"," = ",[33,181,182],{},"0",").",[58,185,186,191,193,195],{},[79,187,188],{},[33,189,190],{},"DisableLegacyTls",[79,192,142],{},[79,194,108],{},[79,196,197],{},"Disables the TLS 1.0 and TLS 1.1 server protocols in Schannel. Affects every TLS service on the host; restart required.",[15,199,201],{"id":200},"usage","Usage",[11,203,204],{},"Harden RDP for a management subnet with the default session limits:",[206,207,212],"pre",{"className":208,"code":209,"language":210,"meta":211,"style":211},"language-powershell shiki shiki-themes github-dark",".\\Set-HardenedRdpConfiguration.ps1 -AllowedSource \"10.10.5.0\u002F24\"\n","powershell","",[33,213,214],{"__ignoreMap":211},[88,215,218,221,225,229,232],{"class":216,"line":217},"line",1,[88,219,115],{"class":220},"s95oV",[88,222,224],{"class":223},"sDLfK","\\Set-HardenedRdpConfiguration.ps1",[88,226,228],{"class":227},"snl16"," -",[88,230,231],{"class":220},"AllowedSource ",[88,233,235],{"class":234},"sU2Wk","\"10.10.5.0\u002F24\"\n",[11,237,238],{},"A jump host that only ever needs a terminal: tighter limits, no drive or clipboard redirection, Restricted Admin allowed:",[206,240,242],{"className":208,"code":241,"language":210,"meta":211,"style":211},".\\Set-HardenedRdpConfiguration.ps1 -AllowedSource \"10.10.5.0\u002F24\", \"10.10.6.10\" -IdleTimeoutMinutes 15 -DisconnectedSessionTimeoutMinutes 30 -DisableDriveRedirection -DisableClipboardRedirection -AllowRestrictedAdmin\n",[33,243,244],{"__ignoreMap":211},[88,245,246,248,250,252,254,257,260,263,265,268,271,273,276,278,280,283,286,289,291],{"class":216,"line":217},[88,247,115],{"class":220},[88,249,224],{"class":223},[88,251,228],{"class":227},[88,253,231],{"class":220},[88,255,256],{"class":234},"\"10.10.5.0\u002F24\"",[88,258,259],{"class":227},",",[88,261,262],{"class":234}," \"10.10.6.10\"",[88,264,228],{"class":227},[88,266,267],{"class":220},"IdleTimeoutMinutes ",[88,269,270],{"class":223},"15",[88,272,228],{"class":227},[88,274,275],{"class":220},"DisconnectedSessionTimeoutMinutes ",[88,277,114],{"class":223},[88,279,228],{"class":227},[88,281,282],{"class":220},"DisableDriveRedirection ",[88,284,285],{"class":227},"-",[88,287,288],{"class":220},"DisableClipboardRedirection ",[88,290,285],{"class":227},[88,292,293],{"class":220},"AllowRestrictedAdmin\n",[11,295,296],{},"Sample output:",[206,298,303],{"className":299,"code":301,"language":302,"meta":211},[300],"language-text","WARNING: Rule 'Allow 3389 - legacy' (enabled, inbound, TCP 3389) is not in the Remote Desktop group and still allows RemoteAddress Any. Review it; this script does not change it.\n\nUserAuthentication SecurityLayer MinEncryptionLevel DisableRestrictedAdmin\n------------------ ------------- ------------------ ----------------------\n                 1             2                  3                      0\n\nMaxIdleTime MaxDisconnectionTime fDisableCdm fDisableClip\n----------- -------------------- ----------- ------------\n     900000              1800000           1            1\n\nRuleName                                  RemoteAddress\n--------                                  -------------\nRemote Desktop - User Mode (TCP-In)       {10.10.5.0\u002F255.255.255.0, 10.10.6.10}\nRemote Desktop - User Mode (UDP-In)       {10.10.5.0\u002F255.255.255.0, 10.10.6.10}\n","text",[33,304,301],{"__ignoreMap":211},[11,306,307],{},"From a client, connect with Restricted Admin mode (credentials never sent to the server; you need to be in the server's local Administrators group) or with Remote Credential Guard (Kerberos only, direct connections only):",[206,309,311],{"className":208,"code":310,"language":210,"meta":211,"style":211},"mstsc.exe \u002Fv:\u003Cserver> \u002FrestrictedAdmin\nmstsc.exe \u002Fv:\u003Cserver> \u002FremoteGuard\n",[33,312,313,338],{"__ignoreMap":211},[88,314,315,318,321,324,327,330,333,335],{"class":216,"line":217},[88,316,317],{"class":223},"mstsc.exe",[88,319,320],{"class":227}," \u002F",[88,322,323],{"class":220},"v:",[88,325,326],{"class":227},"\u003C",[88,328,329],{"class":220},"server",[88,331,332],{"class":227},">",[88,334,320],{"class":227},[88,336,337],{"class":220},"restrictedAdmin\n",[88,339,341,343,345,347,349,351,353,355],{"class":216,"line":340},2,[88,342,317],{"class":223},[88,344,320],{"class":227},[88,346,323],{"class":220},[88,348,326],{"class":227},[88,350,329],{"class":220},[88,352,332],{"class":227},[88,354,320],{"class":227},[88,356,357],{"class":220},"remoteGuard\n",[15,359,361],{"id":360},"script","Script",[206,363,365],{"className":208,"code":364,"language":210,"meta":211,"style":211},"\u003C#\n.SYNOPSIS\n    Hardens Windows Server RDP: NLA, TLS, session limits, redirection, and a source-IP allowlist.\n.DESCRIPTION\n    On the RDP-Tcp listener, requires Network Level Authentication\n    (UserAuthentication = 1), the TLS security layer (SecurityLayer = 2) and High\n    encryption (MinEncryptionLevel = 3). Writes idle and disconnected session\n    limits and optional drive and clipboard redirection blocks to the Terminal\n    Services policy key. Optionally allows Restricted Admin mode and Remote\n    Credential Guard, and disables TLS 1.0\u002F1.1 server protocols. Scopes the\n    enabled inbound rules in the Remote Desktop firewall group to the allowlist,\n    warns about other rules that open TCP 3389, and warns when Group Policy\n    already controls a listener setting.\n.PARAMETER AllowedSource\n    IP addresses or CIDR ranges allowed to reach RDP. Must include the range you\n    are connecting from, or you will lock yourself out.\n.PARAMETER IdleTimeoutMinutes\n    Idle time before an active session is disconnected. Default 30.\n.PARAMETER DisconnectedSessionTimeoutMinutes\n    How long a disconnected session is kept before it is ended. Default 60.\n.PARAMETER DisableDriveRedirection\n    Blocks client drive mapping (and clipboard file copy) into sessions.\n.PARAMETER DisableClipboardRedirection\n    Blocks clipboard sharing between the client and the session.\n.PARAMETER AllowRestrictedAdmin\n    Sets DisableRestrictedAdmin = 0 so clients can use Restricted Admin mode or\n    Remote Credential Guard.\n.PARAMETER DisableLegacyTls\n    Disables the TLS 1.0 and TLS 1.1 server protocols in Schannel. Restart required.\n.EXAMPLE\n    .\\Set-HardenedRdpConfiguration.ps1 -AllowedSource \"10.10.5.0\u002F24\" -IdleTimeoutMinutes 15 -DisableDriveRedirection\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2025-09-17)\n    Requires: Windows Server 2016 or later, NetSecurity module, Administrator\n#>\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory = $true)]\n    [string[]]$AllowedSource,\n\n    [ValidateRange(1, 1440)]\n    [int]$IdleTimeoutMinutes = 30,\n\n    [ValidateRange(1, 1440)]\n    [int]$DisconnectedSessionTimeoutMinutes = 60,\n\n    [switch]$DisableDriveRedirection,\n\n    [switch]$DisableClipboardRedirection,\n\n    [switch]$AllowRestrictedAdmin,\n\n    [switch]$DisableLegacyTls\n)\n\n$listenerPath = \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp\"\n$policyPath = \"HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\Terminal Services\"\n$lsaPath = \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\"\n\nif (-not (Test-Path -Path $listenerPath)) {\n    throw \"RDP-Tcp listener key not found. Is Remote Desktop configured on this host?\"\n}\n\n# Warn when Group Policy already sets a listener value; the GPO wins over the local registry.\n$general = Get-CimInstance -Namespace \"root\\cimv2\\TerminalServices\" -ClassName Win32_TSGeneralSetting -Filter \"TerminalName='RDP-Tcp'\" -ErrorAction SilentlyContinue\n\nif ($general) {\n    foreach ($source in @(\"PolicySourceUserAuthenticationRequired\", \"PolicySourceSecurityLayer\", \"PolicySourceMinEncryptionLevel\")) {\n        if ($general.$source -eq 1) {\n            Write-Warning \"$source = Group Policy. The local value set below will be overridden; change the GPO instead.\"\n        }\n    }\n}\n\n# Listener: NLA required, TLS security layer, High encryption.\nSet-ItemProperty -Path $listenerPath -Name \"UserAuthentication\" -Value 1 -Type DWord\nSet-ItemProperty -Path $listenerPath -Name \"SecurityLayer\" -Value 2 -Type DWord\nSet-ItemProperty -Path $listenerPath -Name \"MinEncryptionLevel\" -Value 3 -Type DWord\n\n# Session limits and redirection through the policy key. Values are milliseconds.\nif (-not (Test-Path -Path $policyPath)) {\n    New-Item -Path $policyPath -Force | Out-Null\n}\n\nNew-ItemProperty -Path $policyPath -Name \"MaxIdleTime\" -Value ($IdleTimeoutMinutes * 60000) -PropertyType DWord -Force | Out-Null\nNew-ItemProperty -Path $policyPath -Name \"MaxDisconnectionTime\" -Value ($DisconnectedSessionTimeoutMinutes * 60000) -PropertyType DWord -Force | Out-Null\n\nif ($DisableDriveRedirection) {\n    New-ItemProperty -Path $policyPath -Name \"fDisableCdm\" -Value 1 -PropertyType DWord -Force | Out-Null\n}\n\nif ($DisableClipboardRedirection) {\n    New-ItemProperty -Path $policyPath -Name \"fDisableClip\" -Value 1 -PropertyType DWord -Force | Out-Null\n}\n\n# Restricted Admin mode and Remote Credential Guard need delegation of non-exportable credentials.\nif ($AllowRestrictedAdmin) {\n    New-ItemProperty -Path $lsaPath -Name \"DisableRestrictedAdmin\" -Value 0 -PropertyType DWord -Force | Out-Null\n}\n\n# Legacy TLS off for every Schannel server on the box. Takes effect after a restart.\nif ($DisableLegacyTls) {\n    foreach ($protocol in @(\"TLS 1.0\", \"TLS 1.1\")) {\n        $serverKey = \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\$protocol\\Server\"\n\n        if (-not (Test-Path -Path $serverKey)) {\n            New-Item -Path $serverKey -Force | Out-Null\n        }\n\n        New-ItemProperty -Path $serverKey -Name \"Enabled\" -Value 0 -PropertyType DWord -Force | Out-Null\n    }\n\n    Write-Warning \"TLS 1.0\u002F1.1 server protocols disabled. Restart the server for Schannel to pick this up.\"\n}\n\n# Firewall: scope the enabled inbound Remote Desktop rules to the allowlist.\n$rdpRules = @(Get-NetFirewallRule -DisplayGroup \"Remote Desktop\" -ErrorAction SilentlyContinue |\n    Where-Object { $_.Direction -eq \"Inbound\" -and $_.Enabled -eq \"True\" })\n\nif ($rdpRules.Count -eq 0) {\n    Write-Warning \"No enabled inbound Remote Desktop firewall rules found. Firewall scope was not changed.\"\n}\n\nforeach ($rule in $rdpRules) {\n    Set-NetFirewallRule -Name $rule.Name -RemoteAddress $AllowedSource\n}\n\n# Any other enabled allow rule on TCP 3389 would bypass the allowlist.\n$rdpRuleNames = $rdpRules | ForEach-Object { $_.Name }\n$otherRules = Get-NetFirewallPortFilter -Protocol TCP |\n    Where-Object { $_.LocalPort -contains \"3389\" } |\n    Get-NetFirewallRule |\n    Where-Object { $_.Enabled -eq \"True\" -and $_.Direction -eq \"Inbound\" -and $_.Action -eq \"Allow\" -and $rdpRuleNames -notcontains $_.Name }\n\nforeach ($other in $otherRules) {\n    $remote = ($other | Get-NetFirewallAddressFilter).RemoteAddress -join \", \"\n    Write-Warning \"Rule '$($other.DisplayName)' (enabled, inbound, TCP 3389) is not in the Remote Desktop group and still allows RemoteAddress $remote. Review it; this script does not change it.\"\n}\n\n# Report the resulting configuration.\n$listener = Get-ItemProperty -Path $listenerPath\n$lsa = Get-ItemProperty -Path $lsaPath\n\n[PSCustomObject]@{\n    UserAuthentication     = $listener.UserAuthentication\n    SecurityLayer          = $listener.SecurityLayer\n    MinEncryptionLevel     = $listener.MinEncryptionLevel\n    DisableRestrictedAdmin = $lsa.DisableRestrictedAdmin\n} | Format-Table -AutoSize\n\nGet-ItemProperty -Path $policyPath |\n    Select-Object -Property MaxIdleTime, MaxDisconnectionTime, fDisableCdm, fDisableClip |\n    Format-Table -AutoSize\n\n$rdpRules |\n    ForEach-Object {\n        [PSCustomObject]@{\n            RuleName      = $_.DisplayName\n            RemoteAddress = (Get-NetFirewallRule -Name $_.Name | Get-NetFirewallAddressFilter).RemoteAddress\n        }\n    } |\n    Format-Table -AutoSize\n",[33,366,367,373,380,386,394,400,406,412,418,424,430,436,442,448,459,465,471,481,487,497,503,513,519,529,535,545,551,557,567,573,581,587,595,601,607,613,619,631,640,665,678,685,705,723,728,745,762,767,779,784,796,801,813,818,828,834,839,850,861,872,877,899,908,914,919,925,962,967,975,1008,1026,1041,1047,1053,1058,1063,1069,1100,1127,1154,1159,1165,1183,1205,1210,1215,1259,1298,1303,1311,1346,1351,1356,1364,1398,1403,1408,1414,1422,1457,1462,1467,1473,1481,1505,1522,1527,1545,1564,1569,1574,1609,1614,1619,1628,1633,1638,1644,1675,1712,1717,1732,1740,1745,1750,1764,1780,1785,1790,1796,1819,1837,1860,1869,1918,1923,1936,1960,1988,1993,1998,2004,2020,2035,2040,2057,2068,2079,2090,2101,2117,2122,2134,2162,2172,2177,2184,2193,2207,2220,2248,2253,2261],{"__ignoreMap":211},[88,368,369],{"class":216,"line":217},[88,370,372],{"class":371},"sAwPA","\u003C#\n",[88,374,375,377],{"class":216,"line":340},[88,376,115],{"class":223},[88,378,379],{"class":227},"SYNOPSIS\n",[88,381,383],{"class":216,"line":382},3,[88,384,385],{"class":371},"    Hardens Windows Server RDP: NLA, TLS, session limits, redirection, and a source-IP allowlist.\n",[88,387,389,391],{"class":216,"line":388},4,[88,390,115],{"class":223},[88,392,393],{"class":227},"DESCRIPTION\n",[88,395,397],{"class":216,"line":396},5,[88,398,399],{"class":371},"    On the RDP-Tcp listener, requires Network Level Authentication\n",[88,401,403],{"class":216,"line":402},6,[88,404,405],{"class":371},"    (UserAuthentication = 1), the TLS security layer (SecurityLayer = 2) and High\n",[88,407,409],{"class":216,"line":408},7,[88,410,411],{"class":371},"    encryption (MinEncryptionLevel = 3). Writes idle and disconnected session\n",[88,413,415],{"class":216,"line":414},8,[88,416,417],{"class":371},"    limits and optional drive and clipboard redirection blocks to the Terminal\n",[88,419,421],{"class":216,"line":420},9,[88,422,423],{"class":371},"    Services policy key. Optionally allows Restricted Admin mode and Remote\n",[88,425,427],{"class":216,"line":426},10,[88,428,429],{"class":371},"    Credential Guard, and disables TLS 1.0\u002F1.1 server protocols. Scopes the\n",[88,431,433],{"class":216,"line":432},11,[88,434,435],{"class":371},"    enabled inbound rules in the Remote Desktop firewall group to the allowlist,\n",[88,437,439],{"class":216,"line":438},12,[88,440,441],{"class":371},"    warns about other rules that open TCP 3389, and warns when Group Policy\n",[88,443,445],{"class":216,"line":444},13,[88,446,447],{"class":371},"    already controls a listener setting.\n",[88,449,451,453,456],{"class":216,"line":450},14,[88,452,115],{"class":223},[88,454,455],{"class":227},"PARAMETER",[88,457,458],{"class":227}," AllowedSource\n",[88,460,462],{"class":216,"line":461},15,[88,463,464],{"class":371},"    IP addresses or CIDR ranges allowed to reach RDP. Must include the range you\n",[88,466,468],{"class":216,"line":467},16,[88,469,470],{"class":371},"    are connecting from, or you will lock yourself out.\n",[88,472,474,476,478],{"class":216,"line":473},17,[88,475,115],{"class":223},[88,477,455],{"class":227},[88,479,480],{"class":227}," IdleTimeoutMinutes\n",[88,482,484],{"class":216,"line":483},18,[88,485,486],{"class":371},"    Idle time before an active session is disconnected. Default 30.\n",[88,488,490,492,494],{"class":216,"line":489},19,[88,491,115],{"class":223},[88,493,455],{"class":227},[88,495,496],{"class":227}," DisconnectedSessionTimeoutMinutes\n",[88,498,500],{"class":216,"line":499},20,[88,501,502],{"class":371},"    How long a disconnected session is kept before it is ended. Default 60.\n",[88,504,506,508,510],{"class":216,"line":505},21,[88,507,115],{"class":223},[88,509,455],{"class":227},[88,511,512],{"class":227}," DisableDriveRedirection\n",[88,514,516],{"class":216,"line":515},22,[88,517,518],{"class":371},"    Blocks client drive mapping (and clipboard file copy) into sessions.\n",[88,520,522,524,526],{"class":216,"line":521},23,[88,523,115],{"class":223},[88,525,455],{"class":227},[88,527,528],{"class":227}," DisableClipboardRedirection\n",[88,530,532],{"class":216,"line":531},24,[88,533,534],{"class":371},"    Blocks clipboard sharing between the client and the session.\n",[88,536,538,540,542],{"class":216,"line":537},25,[88,539,115],{"class":223},[88,541,455],{"class":227},[88,543,544],{"class":227}," AllowRestrictedAdmin\n",[88,546,548],{"class":216,"line":547},26,[88,549,550],{"class":371},"    Sets DisableRestrictedAdmin = 0 so clients can use Restricted Admin mode or\n",[88,552,554],{"class":216,"line":553},27,[88,555,556],{"class":371},"    Remote Credential Guard.\n",[88,558,560,562,564],{"class":216,"line":559},28,[88,561,115],{"class":223},[88,563,455],{"class":227},[88,565,566],{"class":227}," DisableLegacyTls\n",[88,568,570],{"class":216,"line":569},29,[88,571,572],{"class":371},"    Disables the TLS 1.0 and TLS 1.1 server protocols in Schannel. Restart required.\n",[88,574,576,578],{"class":216,"line":575},30,[88,577,115],{"class":223},[88,579,580],{"class":227},"EXAMPLE\n",[88,582,584],{"class":216,"line":583},31,[88,585,586],{"class":371},"    .\\Set-HardenedRdpConfiguration.ps1 -AllowedSource \"10.10.5.0\u002F24\" -IdleTimeoutMinutes 15 -DisableDriveRedirection\n",[88,588,590,592],{"class":216,"line":589},32,[88,591,115],{"class":223},[88,593,594],{"class":227},"NOTES\n",[88,596,598],{"class":216,"line":597},33,[88,599,600],{"class":371},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[88,602,604],{"class":216,"line":603},34,[88,605,606],{"class":371},"    Version : 1.0 (2025-09-17)\n",[88,608,610],{"class":216,"line":609},35,[88,611,612],{"class":371},"    Requires: Windows Server 2016 or later, NetSecurity module, Administrator\n",[88,614,616],{"class":216,"line":615},36,[88,617,618],{"class":371},"#>\n",[88,620,622,625,628],{"class":216,"line":621},37,[88,623,624],{"class":220},"[",[88,626,627],{"class":223},"CmdletBinding",[88,629,630],{"class":220},"()]\n",[88,632,634,637],{"class":216,"line":633},38,[88,635,636],{"class":227},"param",[88,638,639],{"class":220}," (\n",[88,641,643,646,649,652,656,659,662],{"class":216,"line":642},39,[88,644,645],{"class":220},"    [",[88,647,648],{"class":223},"Parameter",[88,650,651],{"class":220},"(",[88,653,655],{"class":654},"s9osk","Mandatory",[88,657,658],{"class":227}," =",[88,660,661],{"class":223}," $true",[88,663,664],{"class":220},")]\n",[88,666,668,670,672,675],{"class":216,"line":667},40,[88,669,645],{"class":220},[88,671,86],{"class":227},[88,673,674],{"class":220},"[]]$AllowedSource",[88,676,677],{"class":227},",\n",[88,679,681],{"class":216,"line":680},41,[88,682,684],{"emptyLinePlaceholder":683},true,"\n",[88,686,688,690,693,695,698,700,703],{"class":216,"line":687},42,[88,689,645],{"class":220},[88,691,692],{"class":223},"ValidateRange",[88,694,651],{"class":220},[88,696,697],{"class":223},"1",[88,699,259],{"class":227},[88,701,702],{"class":223}," 1440",[88,704,664],{"class":220},[88,706,708,710,712,715,718,721],{"class":216,"line":707},43,[88,709,645],{"class":220},[88,711,105],{"class":227},[88,713,714],{"class":220},"]$IdleTimeoutMinutes ",[88,716,717],{"class":227},"=",[88,719,720],{"class":223}," 30",[88,722,677],{"class":227},[88,724,726],{"class":216,"line":725},44,[88,727,684],{"emptyLinePlaceholder":683},[88,729,731,733,735,737,739,741,743],{"class":216,"line":730},45,[88,732,645],{"class":220},[88,734,692],{"class":223},[88,736,651],{"class":220},[88,738,697],{"class":223},[88,740,259],{"class":227},[88,742,702],{"class":223},[88,744,664],{"class":220},[88,746,748,750,752,755,757,760],{"class":216,"line":747},46,[88,749,645],{"class":220},[88,751,105],{"class":227},[88,753,754],{"class":220},"]$DisconnectedSessionTimeoutMinutes ",[88,756,717],{"class":227},[88,758,759],{"class":223}," 60",[88,761,677],{"class":227},[88,763,765],{"class":216,"line":764},47,[88,766,684],{"emptyLinePlaceholder":683},[88,768,770,772,774,777],{"class":216,"line":769},48,[88,771,645],{"class":220},[88,773,142],{"class":227},[88,775,776],{"class":220},"]$DisableDriveRedirection",[88,778,677],{"class":227},[88,780,782],{"class":216,"line":781},49,[88,783,684],{"emptyLinePlaceholder":683},[88,785,787,789,791,794],{"class":216,"line":786},50,[88,788,645],{"class":220},[88,790,142],{"class":227},[88,792,793],{"class":220},"]$DisableClipboardRedirection",[88,795,677],{"class":227},[88,797,799],{"class":216,"line":798},51,[88,800,684],{"emptyLinePlaceholder":683},[88,802,804,806,808,811],{"class":216,"line":803},52,[88,805,645],{"class":220},[88,807,142],{"class":227},[88,809,810],{"class":220},"]$AllowRestrictedAdmin",[88,812,677],{"class":227},[88,814,816],{"class":216,"line":815},53,[88,817,684],{"emptyLinePlaceholder":683},[88,819,821,823,825],{"class":216,"line":820},54,[88,822,645],{"class":220},[88,824,142],{"class":227},[88,826,827],{"class":220},"]$DisableLegacyTls\n",[88,829,831],{"class":216,"line":830},55,[88,832,833],{"class":220},")\n",[88,835,837],{"class":216,"line":836},56,[88,838,684],{"emptyLinePlaceholder":683},[88,840,842,845,847],{"class":216,"line":841},57,[88,843,844],{"class":220},"$listenerPath ",[88,846,717],{"class":227},[88,848,849],{"class":234}," \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp\"\n",[88,851,853,856,858],{"class":216,"line":852},58,[88,854,855],{"class":220},"$policyPath ",[88,857,717],{"class":227},[88,859,860],{"class":234}," \"HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\Terminal Services\"\n",[88,862,864,867,869],{"class":216,"line":863},59,[88,865,866],{"class":220},"$lsaPath ",[88,868,717],{"class":227},[88,870,871],{"class":234}," \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\"\n",[88,873,875],{"class":216,"line":874},60,[88,876,684],{"emptyLinePlaceholder":683},[88,878,880,883,886,889,891,894,896],{"class":216,"line":879},61,[88,881,882],{"class":227},"if",[88,884,885],{"class":220}," (",[88,887,888],{"class":227},"-not",[88,890,885],{"class":220},[88,892,893],{"class":223},"Test-Path",[88,895,228],{"class":227},[88,897,898],{"class":220},"Path $listenerPath)) {\n",[88,900,902,905],{"class":216,"line":901},62,[88,903,904],{"class":227},"    throw",[88,906,907],{"class":234}," \"RDP-Tcp listener key not found. Is Remote Desktop configured on this host?\"\n",[88,909,911],{"class":216,"line":910},63,[88,912,913],{"class":220},"}\n",[88,915,917],{"class":216,"line":916},64,[88,918,684],{"emptyLinePlaceholder":683},[88,920,922],{"class":216,"line":921},65,[88,923,924],{"class":371},"# Warn when Group Policy already sets a listener value; the GPO wins over the local registry.\n",[88,926,928,931,933,936,938,941,944,946,949,951,954,957,959],{"class":216,"line":927},66,[88,929,930],{"class":220},"$general ",[88,932,717],{"class":227},[88,934,935],{"class":223}," Get-CimInstance",[88,937,228],{"class":227},[88,939,940],{"class":220},"Namespace ",[88,942,943],{"class":234},"\"root\\cimv2\\TerminalServices\"",[88,945,228],{"class":227},[88,947,948],{"class":220},"ClassName Win32_TSGeneralSetting ",[88,950,285],{"class":227},[88,952,953],{"class":220},"Filter ",[88,955,956],{"class":234},"\"TerminalName='RDP-Tcp'\"",[88,958,228],{"class":227},[88,960,961],{"class":220},"ErrorAction SilentlyContinue\n",[88,963,965],{"class":216,"line":964},67,[88,966,684],{"emptyLinePlaceholder":683},[88,968,970,972],{"class":216,"line":969},68,[88,971,882],{"class":227},[88,973,974],{"class":220}," ($general) {\n",[88,976,978,981,984,987,990,992,995,997,1000,1002,1005],{"class":216,"line":977},69,[88,979,980],{"class":227},"    foreach",[88,982,983],{"class":220}," ($source ",[88,985,986],{"class":227},"in",[88,988,989],{"class":227}," @",[88,991,651],{"class":220},[88,993,994],{"class":234},"\"PolicySourceUserAuthenticationRequired\"",[88,996,259],{"class":227},[88,998,999],{"class":234}," \"PolicySourceSecurityLayer\"",[88,1001,259],{"class":227},[88,1003,1004],{"class":234}," \"PolicySourceMinEncryptionLevel\"",[88,1006,1007],{"class":220},")) {\n",[88,1009,1011,1014,1017,1020,1023],{"class":216,"line":1010},70,[88,1012,1013],{"class":227},"        if",[88,1015,1016],{"class":220}," ($general.$source ",[88,1018,1019],{"class":227},"-eq",[88,1021,1022],{"class":223}," 1",[88,1024,1025],{"class":220},") {\n",[88,1027,1029,1032,1035,1038],{"class":216,"line":1028},71,[88,1030,1031],{"class":223},"            Write-Warning",[88,1033,1034],{"class":234}," \"",[88,1036,1037],{"class":220},"$source",[88,1039,1040],{"class":234}," = Group Policy. The local value set below will be overridden; change the GPO instead.\"\n",[88,1042,1044],{"class":216,"line":1043},72,[88,1045,1046],{"class":220},"        }\n",[88,1048,1050],{"class":216,"line":1049},73,[88,1051,1052],{"class":220},"    }\n",[88,1054,1056],{"class":216,"line":1055},74,[88,1057,913],{"class":220},[88,1059,1061],{"class":216,"line":1060},75,[88,1062,684],{"emptyLinePlaceholder":683},[88,1064,1066],{"class":216,"line":1065},76,[88,1067,1068],{"class":371},"# Listener: NLA required, TLS security layer, High encryption.\n",[88,1070,1072,1075,1077,1080,1082,1085,1088,1090,1093,1095,1097],{"class":216,"line":1071},77,[88,1073,1074],{"class":223},"Set-ItemProperty",[88,1076,228],{"class":227},[88,1078,1079],{"class":220},"Path $listenerPath ",[88,1081,285],{"class":227},[88,1083,1084],{"class":220},"Name ",[88,1086,1087],{"class":234},"\"UserAuthentication\"",[88,1089,228],{"class":227},[88,1091,1092],{"class":220},"Value ",[88,1094,697],{"class":223},[88,1096,228],{"class":227},[88,1098,1099],{"class":220},"Type DWord\n",[88,1101,1103,1105,1107,1109,1111,1113,1116,1118,1120,1123,1125],{"class":216,"line":1102},78,[88,1104,1074],{"class":223},[88,1106,228],{"class":227},[88,1108,1079],{"class":220},[88,1110,285],{"class":227},[88,1112,1084],{"class":220},[88,1114,1115],{"class":234},"\"SecurityLayer\"",[88,1117,228],{"class":227},[88,1119,1092],{"class":220},[88,1121,1122],{"class":223},"2",[88,1124,228],{"class":227},[88,1126,1099],{"class":220},[88,1128,1130,1132,1134,1136,1138,1140,1143,1145,1147,1150,1152],{"class":216,"line":1129},79,[88,1131,1074],{"class":223},[88,1133,228],{"class":227},[88,1135,1079],{"class":220},[88,1137,285],{"class":227},[88,1139,1084],{"class":220},[88,1141,1142],{"class":234},"\"MinEncryptionLevel\"",[88,1144,228],{"class":227},[88,1146,1092],{"class":220},[88,1148,1149],{"class":223},"3",[88,1151,228],{"class":227},[88,1153,1099],{"class":220},[88,1155,1157],{"class":216,"line":1156},80,[88,1158,684],{"emptyLinePlaceholder":683},[88,1160,1162],{"class":216,"line":1161},81,[88,1163,1164],{"class":371},"# Session limits and redirection through the policy key. Values are milliseconds.\n",[88,1166,1168,1170,1172,1174,1176,1178,1180],{"class":216,"line":1167},82,[88,1169,882],{"class":227},[88,1171,885],{"class":220},[88,1173,888],{"class":227},[88,1175,885],{"class":220},[88,1177,893],{"class":223},[88,1179,228],{"class":227},[88,1181,1182],{"class":220},"Path $policyPath)) {\n",[88,1184,1186,1189,1191,1194,1196,1199,1202],{"class":216,"line":1185},83,[88,1187,1188],{"class":223},"    New-Item",[88,1190,228],{"class":227},[88,1192,1193],{"class":220},"Path $policyPath ",[88,1195,285],{"class":227},[88,1197,1198],{"class":220},"Force ",[88,1200,1201],{"class":227},"|",[88,1203,1204],{"class":223}," Out-Null\n",[88,1206,1208],{"class":216,"line":1207},84,[88,1209,913],{"class":220},[88,1211,1213],{"class":216,"line":1212},85,[88,1214,684],{"emptyLinePlaceholder":683},[88,1216,1218,1221,1223,1225,1227,1229,1232,1234,1237,1240,1243,1246,1248,1251,1253,1255,1257],{"class":216,"line":1217},86,[88,1219,1220],{"class":223},"New-ItemProperty",[88,1222,228],{"class":227},[88,1224,1193],{"class":220},[88,1226,285],{"class":227},[88,1228,1084],{"class":220},[88,1230,1231],{"class":234},"\"MaxIdleTime\"",[88,1233,228],{"class":227},[88,1235,1236],{"class":220},"Value ($IdleTimeoutMinutes ",[88,1238,1239],{"class":227},"*",[88,1241,1242],{"class":223}," 60000",[88,1244,1245],{"class":220},") ",[88,1247,285],{"class":227},[88,1249,1250],{"class":220},"PropertyType DWord ",[88,1252,285],{"class":227},[88,1254,1198],{"class":220},[88,1256,1201],{"class":227},[88,1258,1204],{"class":223},[88,1260,1262,1264,1266,1268,1270,1272,1275,1277,1280,1282,1284,1286,1288,1290,1292,1294,1296],{"class":216,"line":1261},87,[88,1263,1220],{"class":223},[88,1265,228],{"class":227},[88,1267,1193],{"class":220},[88,1269,285],{"class":227},[88,1271,1084],{"class":220},[88,1273,1274],{"class":234},"\"MaxDisconnectionTime\"",[88,1276,228],{"class":227},[88,1278,1279],{"class":220},"Value ($DisconnectedSessionTimeoutMinutes ",[88,1281,1239],{"class":227},[88,1283,1242],{"class":223},[88,1285,1245],{"class":220},[88,1287,285],{"class":227},[88,1289,1250],{"class":220},[88,1291,285],{"class":227},[88,1293,1198],{"class":220},[88,1295,1201],{"class":227},[88,1297,1204],{"class":223},[88,1299,1301],{"class":216,"line":1300},88,[88,1302,684],{"emptyLinePlaceholder":683},[88,1304,1306,1308],{"class":216,"line":1305},89,[88,1307,882],{"class":227},[88,1309,1310],{"class":220}," ($DisableDriveRedirection) {\n",[88,1312,1314,1317,1319,1321,1323,1325,1328,1330,1332,1334,1336,1338,1340,1342,1344],{"class":216,"line":1313},90,[88,1315,1316],{"class":223},"    New-ItemProperty",[88,1318,228],{"class":227},[88,1320,1193],{"class":220},[88,1322,285],{"class":227},[88,1324,1084],{"class":220},[88,1326,1327],{"class":234},"\"fDisableCdm\"",[88,1329,228],{"class":227},[88,1331,1092],{"class":220},[88,1333,697],{"class":223},[88,1335,228],{"class":227},[88,1337,1250],{"class":220},[88,1339,285],{"class":227},[88,1341,1198],{"class":220},[88,1343,1201],{"class":227},[88,1345,1204],{"class":223},[88,1347,1349],{"class":216,"line":1348},91,[88,1350,913],{"class":220},[88,1352,1354],{"class":216,"line":1353},92,[88,1355,684],{"emptyLinePlaceholder":683},[88,1357,1359,1361],{"class":216,"line":1358},93,[88,1360,882],{"class":227},[88,1362,1363],{"class":220}," ($DisableClipboardRedirection) {\n",[88,1365,1367,1369,1371,1373,1375,1377,1380,1382,1384,1386,1388,1390,1392,1394,1396],{"class":216,"line":1366},94,[88,1368,1316],{"class":223},[88,1370,228],{"class":227},[88,1372,1193],{"class":220},[88,1374,285],{"class":227},[88,1376,1084],{"class":220},[88,1378,1379],{"class":234},"\"fDisableClip\"",[88,1381,228],{"class":227},[88,1383,1092],{"class":220},[88,1385,697],{"class":223},[88,1387,228],{"class":227},[88,1389,1250],{"class":220},[88,1391,285],{"class":227},[88,1393,1198],{"class":220},[88,1395,1201],{"class":227},[88,1397,1204],{"class":223},[88,1399,1401],{"class":216,"line":1400},95,[88,1402,913],{"class":220},[88,1404,1406],{"class":216,"line":1405},96,[88,1407,684],{"emptyLinePlaceholder":683},[88,1409,1411],{"class":216,"line":1410},97,[88,1412,1413],{"class":371},"# Restricted Admin mode and Remote Credential Guard need delegation of non-exportable credentials.\n",[88,1415,1417,1419],{"class":216,"line":1416},98,[88,1418,882],{"class":227},[88,1420,1421],{"class":220}," ($AllowRestrictedAdmin) {\n",[88,1423,1425,1427,1429,1432,1434,1436,1439,1441,1443,1445,1447,1449,1451,1453,1455],{"class":216,"line":1424},99,[88,1426,1316],{"class":223},[88,1428,228],{"class":227},[88,1430,1431],{"class":220},"Path $lsaPath ",[88,1433,285],{"class":227},[88,1435,1084],{"class":220},[88,1437,1438],{"class":234},"\"DisableRestrictedAdmin\"",[88,1440,228],{"class":227},[88,1442,1092],{"class":220},[88,1444,182],{"class":223},[88,1446,228],{"class":227},[88,1448,1250],{"class":220},[88,1450,285],{"class":227},[88,1452,1198],{"class":220},[88,1454,1201],{"class":227},[88,1456,1204],{"class":223},[88,1458,1460],{"class":216,"line":1459},100,[88,1461,913],{"class":220},[88,1463,1465],{"class":216,"line":1464},101,[88,1466,684],{"emptyLinePlaceholder":683},[88,1468,1470],{"class":216,"line":1469},102,[88,1471,1472],{"class":371},"# Legacy TLS off for every Schannel server on the box. Takes effect after a restart.\n",[88,1474,1476,1478],{"class":216,"line":1475},103,[88,1477,882],{"class":227},[88,1479,1480],{"class":220}," ($DisableLegacyTls) {\n",[88,1482,1484,1486,1489,1491,1493,1495,1498,1500,1503],{"class":216,"line":1483},104,[88,1485,980],{"class":227},[88,1487,1488],{"class":220}," ($protocol ",[88,1490,986],{"class":227},[88,1492,989],{"class":227},[88,1494,651],{"class":220},[88,1496,1497],{"class":234},"\"TLS 1.0\"",[88,1499,259],{"class":227},[88,1501,1502],{"class":234}," \"TLS 1.1\"",[88,1504,1007],{"class":220},[88,1506,1508,1511,1513,1516,1519],{"class":216,"line":1507},105,[88,1509,1510],{"class":220},"        $serverKey ",[88,1512,717],{"class":227},[88,1514,1515],{"class":234}," \"HKLM:\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\",[88,1517,1518],{"class":220},"$protocol",[88,1520,1521],{"class":234},"\\Server\"\n",[88,1523,1525],{"class":216,"line":1524},106,[88,1526,684],{"emptyLinePlaceholder":683},[88,1528,1530,1532,1534,1536,1538,1540,1542],{"class":216,"line":1529},107,[88,1531,1013],{"class":227},[88,1533,885],{"class":220},[88,1535,888],{"class":227},[88,1537,885],{"class":220},[88,1539,893],{"class":223},[88,1541,228],{"class":227},[88,1543,1544],{"class":220},"Path $serverKey)) {\n",[88,1546,1548,1551,1553,1556,1558,1560,1562],{"class":216,"line":1547},108,[88,1549,1550],{"class":223},"            New-Item",[88,1552,228],{"class":227},[88,1554,1555],{"class":220},"Path $serverKey ",[88,1557,285],{"class":227},[88,1559,1198],{"class":220},[88,1561,1201],{"class":227},[88,1563,1204],{"class":223},[88,1565,1567],{"class":216,"line":1566},109,[88,1568,1046],{"class":220},[88,1570,1572],{"class":216,"line":1571},110,[88,1573,684],{"emptyLinePlaceholder":683},[88,1575,1577,1580,1582,1584,1586,1588,1591,1593,1595,1597,1599,1601,1603,1605,1607],{"class":216,"line":1576},111,[88,1578,1579],{"class":223},"        New-ItemProperty",[88,1581,228],{"class":227},[88,1583,1555],{"class":220},[88,1585,285],{"class":227},[88,1587,1084],{"class":220},[88,1589,1590],{"class":234},"\"Enabled\"",[88,1592,228],{"class":227},[88,1594,1092],{"class":220},[88,1596,182],{"class":223},[88,1598,228],{"class":227},[88,1600,1250],{"class":220},[88,1602,285],{"class":227},[88,1604,1198],{"class":220},[88,1606,1201],{"class":227},[88,1608,1204],{"class":223},[88,1610,1612],{"class":216,"line":1611},112,[88,1613,1052],{"class":220},[88,1615,1617],{"class":216,"line":1616},113,[88,1618,684],{"emptyLinePlaceholder":683},[88,1620,1622,1625],{"class":216,"line":1621},114,[88,1623,1624],{"class":223},"    Write-Warning",[88,1626,1627],{"class":234}," \"TLS 1.0\u002F1.1 server protocols disabled. Restart the server for Schannel to pick this up.\"\n",[88,1629,1631],{"class":216,"line":1630},115,[88,1632,913],{"class":220},[88,1634,1636],{"class":216,"line":1635},116,[88,1637,684],{"emptyLinePlaceholder":683},[88,1639,1641],{"class":216,"line":1640},117,[88,1642,1643],{"class":371},"# Firewall: scope the enabled inbound Remote Desktop rules to the allowlist.\n",[88,1645,1647,1650,1652,1654,1656,1659,1661,1664,1667,1669,1672],{"class":216,"line":1646},118,[88,1648,1649],{"class":220},"$rdpRules ",[88,1651,717],{"class":227},[88,1653,989],{"class":227},[88,1655,651],{"class":220},[88,1657,1658],{"class":223},"Get-NetFirewallRule",[88,1660,228],{"class":227},[88,1662,1663],{"class":220},"DisplayGroup ",[88,1665,1666],{"class":234},"\"Remote Desktop\"",[88,1668,228],{"class":227},[88,1670,1671],{"class":220},"ErrorAction SilentlyContinue ",[88,1673,1674],{"class":227},"|\n",[88,1676,1678,1681,1684,1687,1690,1692,1695,1698,1701,1704,1706,1709],{"class":216,"line":1677},119,[88,1679,1680],{"class":223},"    Where-Object",[88,1682,1683],{"class":220}," { ",[88,1685,1686],{"class":223},"$_",[88,1688,1689],{"class":220},".Direction ",[88,1691,1019],{"class":227},[88,1693,1694],{"class":234}," \"Inbound\"",[88,1696,1697],{"class":227}," -and",[88,1699,1700],{"class":223}," $_",[88,1702,1703],{"class":220},".Enabled ",[88,1705,1019],{"class":227},[88,1707,1708],{"class":234}," \"True\"",[88,1710,1711],{"class":220}," })\n",[88,1713,1715],{"class":216,"line":1714},120,[88,1716,684],{"emptyLinePlaceholder":683},[88,1718,1720,1722,1725,1727,1730],{"class":216,"line":1719},121,[88,1721,882],{"class":227},[88,1723,1724],{"class":220}," ($rdpRules.Count ",[88,1726,1019],{"class":227},[88,1728,1729],{"class":223}," 0",[88,1731,1025],{"class":220},[88,1733,1735,1737],{"class":216,"line":1734},122,[88,1736,1624],{"class":223},[88,1738,1739],{"class":234}," \"No enabled inbound Remote Desktop firewall rules found. Firewall scope was not changed.\"\n",[88,1741,1743],{"class":216,"line":1742},123,[88,1744,913],{"class":220},[88,1746,1748],{"class":216,"line":1747},124,[88,1749,684],{"emptyLinePlaceholder":683},[88,1751,1753,1756,1759,1761],{"class":216,"line":1752},125,[88,1754,1755],{"class":227},"foreach",[88,1757,1758],{"class":220}," ($rule ",[88,1760,986],{"class":227},[88,1762,1763],{"class":220}," $rdpRules) {\n",[88,1765,1767,1770,1772,1775,1777],{"class":216,"line":1766},126,[88,1768,1769],{"class":223},"    Set-NetFirewallRule",[88,1771,228],{"class":227},[88,1773,1774],{"class":220},"Name $rule.Name ",[88,1776,285],{"class":227},[88,1778,1779],{"class":220},"RemoteAddress $AllowedSource\n",[88,1781,1783],{"class":216,"line":1782},127,[88,1784,913],{"class":220},[88,1786,1788],{"class":216,"line":1787},128,[88,1789,684],{"emptyLinePlaceholder":683},[88,1791,1793],{"class":216,"line":1792},129,[88,1794,1795],{"class":371},"# Any other enabled allow rule on TCP 3389 would bypass the allowlist.\n",[88,1797,1799,1802,1804,1807,1809,1812,1814,1816],{"class":216,"line":1798},130,[88,1800,1801],{"class":220},"$rdpRuleNames ",[88,1803,717],{"class":227},[88,1805,1806],{"class":220}," $rdpRules ",[88,1808,1201],{"class":227},[88,1810,1811],{"class":223}," ForEach-Object",[88,1813,1683],{"class":220},[88,1815,1686],{"class":223},[88,1817,1818],{"class":220},".Name }\n",[88,1820,1822,1825,1827,1830,1832,1835],{"class":216,"line":1821},131,[88,1823,1824],{"class":220},"$otherRules ",[88,1826,717],{"class":227},[88,1828,1829],{"class":223}," Get-NetFirewallPortFilter",[88,1831,228],{"class":227},[88,1833,1834],{"class":220},"Protocol TCP ",[88,1836,1674],{"class":227},[88,1838,1840,1842,1844,1846,1849,1852,1855,1858],{"class":216,"line":1839},132,[88,1841,1680],{"class":223},[88,1843,1683],{"class":220},[88,1845,1686],{"class":223},[88,1847,1848],{"class":220},".LocalPort ",[88,1850,1851],{"class":227},"-contains",[88,1853,1854],{"class":234}," \"3389\"",[88,1856,1857],{"class":220}," } ",[88,1859,1674],{"class":227},[88,1861,1863,1866],{"class":216,"line":1862},133,[88,1864,1865],{"class":223},"    Get-NetFirewallRule",[88,1867,1868],{"class":227}," |\n",[88,1870,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896,1898,1901,1903,1906,1908,1911,1914,1916],{"class":216,"line":1871},134,[88,1873,1680],{"class":223},[88,1875,1683],{"class":220},[88,1877,1686],{"class":223},[88,1879,1703],{"class":220},[88,1881,1019],{"class":227},[88,1883,1708],{"class":234},[88,1885,1697],{"class":227},[88,1887,1700],{"class":223},[88,1889,1689],{"class":220},[88,1891,1019],{"class":227},[88,1893,1694],{"class":234},[88,1895,1697],{"class":227},[88,1897,1700],{"class":223},[88,1899,1900],{"class":220},".Action ",[88,1902,1019],{"class":227},[88,1904,1905],{"class":234}," \"Allow\"",[88,1907,1697],{"class":227},[88,1909,1910],{"class":220}," $rdpRuleNames ",[88,1912,1913],{"class":227},"-notcontains",[88,1915,1700],{"class":223},[88,1917,1818],{"class":220},[88,1919,1921],{"class":216,"line":1920},135,[88,1922,684],{"emptyLinePlaceholder":683},[88,1924,1926,1928,1931,1933],{"class":216,"line":1925},136,[88,1927,1755],{"class":227},[88,1929,1930],{"class":220}," ($other ",[88,1932,986],{"class":227},[88,1934,1935],{"class":220}," $otherRules) {\n",[88,1937,1939,1942,1944,1946,1948,1951,1954,1957],{"class":216,"line":1938},137,[88,1940,1941],{"class":220},"    $remote ",[88,1943,717],{"class":227},[88,1945,1930],{"class":220},[88,1947,1201],{"class":227},[88,1949,1950],{"class":223}," Get-NetFirewallAddressFilter",[88,1952,1953],{"class":220},").RemoteAddress ",[88,1955,1956],{"class":227},"-join",[88,1958,1959],{"class":234}," \", \"\n",[88,1961,1963,1965,1968,1971,1973,1976,1979,1982,1985],{"class":216,"line":1962},138,[88,1964,1624],{"class":223},[88,1966,1967],{"class":234}," \"Rule '",[88,1969,1970],{"class":227},"$",[88,1972,651],{"class":234},[88,1974,1975],{"class":220},"$other.DisplayName",[88,1977,1978],{"class":234},")",[88,1980,1981],{"class":234},"' (enabled, inbound, TCP 3389) is not in the Remote Desktop group and still allows RemoteAddress ",[88,1983,1984],{"class":220},"$remote",[88,1986,1987],{"class":234},". Review it; this script does not change it.\"\n",[88,1989,1991],{"class":216,"line":1990},139,[88,1992,913],{"class":220},[88,1994,1996],{"class":216,"line":1995},140,[88,1997,684],{"emptyLinePlaceholder":683},[88,1999,2001],{"class":216,"line":2000},141,[88,2002,2003],{"class":371},"# Report the resulting configuration.\n",[88,2005,2007,2010,2012,2015,2017],{"class":216,"line":2006},142,[88,2008,2009],{"class":220},"$listener ",[88,2011,717],{"class":227},[88,2013,2014],{"class":223}," Get-ItemProperty",[88,2016,228],{"class":227},[88,2018,2019],{"class":220},"Path $listenerPath\n",[88,2021,2023,2026,2028,2030,2032],{"class":216,"line":2022},143,[88,2024,2025],{"class":220},"$lsa ",[88,2027,717],{"class":227},[88,2029,2014],{"class":223},[88,2031,228],{"class":227},[88,2033,2034],{"class":220},"Path $lsaPath\n",[88,2036,2038],{"class":216,"line":2037},144,[88,2039,684],{"emptyLinePlaceholder":683},[88,2041,2043,2045,2048,2051,2054],{"class":216,"line":2042},145,[88,2044,624],{"class":220},[88,2046,2047],{"class":227},"PSCustomObject",[88,2049,2050],{"class":220},"]",[88,2052,2053],{"class":227},"@",[88,2055,2056],{"class":220},"{\n",[88,2058,2060,2063,2065],{"class":216,"line":2059},146,[88,2061,2062],{"class":220},"    UserAuthentication     ",[88,2064,717],{"class":227},[88,2066,2067],{"class":220}," $listener.UserAuthentication\n",[88,2069,2071,2074,2076],{"class":216,"line":2070},147,[88,2072,2073],{"class":220},"    SecurityLayer          ",[88,2075,717],{"class":227},[88,2077,2078],{"class":220}," $listener.SecurityLayer\n",[88,2080,2082,2085,2087],{"class":216,"line":2081},148,[88,2083,2084],{"class":220},"    MinEncryptionLevel     ",[88,2086,717],{"class":227},[88,2088,2089],{"class":220}," $listener.MinEncryptionLevel\n",[88,2091,2093,2096,2098],{"class":216,"line":2092},149,[88,2094,2095],{"class":220},"    DisableRestrictedAdmin ",[88,2097,717],{"class":227},[88,2099,2100],{"class":220}," $lsa.DisableRestrictedAdmin\n",[88,2102,2104,2107,2109,2112,2114],{"class":216,"line":2103},150,[88,2105,2106],{"class":220},"} ",[88,2108,1201],{"class":227},[88,2110,2111],{"class":223}," Format-Table",[88,2113,228],{"class":227},[88,2115,2116],{"class":220},"AutoSize\n",[88,2118,2120],{"class":216,"line":2119},151,[88,2121,684],{"emptyLinePlaceholder":683},[88,2123,2125,2128,2130,2132],{"class":216,"line":2124},152,[88,2126,2127],{"class":223},"Get-ItemProperty",[88,2129,228],{"class":227},[88,2131,1193],{"class":220},[88,2133,1674],{"class":227},[88,2135,2137,2140,2142,2145,2147,2150,2152,2155,2157,2160],{"class":216,"line":2136},153,[88,2138,2139],{"class":223},"    Select-Object",[88,2141,228],{"class":227},[88,2143,2144],{"class":220},"Property MaxIdleTime",[88,2146,259],{"class":227},[88,2148,2149],{"class":220}," MaxDisconnectionTime",[88,2151,259],{"class":227},[88,2153,2154],{"class":220}," fDisableCdm",[88,2156,259],{"class":227},[88,2158,2159],{"class":220}," fDisableClip ",[88,2161,1674],{"class":227},[88,2163,2165,2168,2170],{"class":216,"line":2164},154,[88,2166,2167],{"class":223},"    Format-Table",[88,2169,228],{"class":227},[88,2171,2116],{"class":220},[88,2173,2175],{"class":216,"line":2174},155,[88,2176,684],{"emptyLinePlaceholder":683},[88,2178,2180,2182],{"class":216,"line":2179},156,[88,2181,1649],{"class":220},[88,2183,1674],{"class":227},[88,2185,2187,2190],{"class":216,"line":2186},157,[88,2188,2189],{"class":223},"    ForEach-Object",[88,2191,2192],{"class":220}," {\n",[88,2194,2196,2199,2201,2203,2205],{"class":216,"line":2195},158,[88,2197,2198],{"class":220},"        [",[88,2200,2047],{"class":227},[88,2202,2050],{"class":220},[88,2204,2053],{"class":227},[88,2206,2056],{"class":220},[88,2208,2210,2213,2215,2217],{"class":216,"line":2209},159,[88,2211,2212],{"class":220},"            RuleName      ",[88,2214,717],{"class":227},[88,2216,1700],{"class":223},[88,2218,2219],{"class":220},".DisplayName\n",[88,2221,2223,2226,2228,2230,2232,2234,2236,2238,2241,2243,2245],{"class":216,"line":2222},160,[88,2224,2225],{"class":220},"            RemoteAddress ",[88,2227,717],{"class":227},[88,2229,885],{"class":220},[88,2231,1658],{"class":223},[88,2233,228],{"class":227},[88,2235,1084],{"class":220},[88,2237,1686],{"class":223},[88,2239,2240],{"class":220},".Name ",[88,2242,1201],{"class":227},[88,2244,1950],{"class":223},[88,2246,2247],{"class":220},").RemoteAddress\n",[88,2249,2251],{"class":216,"line":2250},161,[88,2252,1046],{"class":220},[88,2254,2256,2259],{"class":216,"line":2255},162,[88,2257,2258],{"class":220},"    } ",[88,2260,1674],{"class":227},[88,2262,2264,2266,2268],{"class":216,"line":2263},163,[88,2265,2167],{"class":223},[88,2267,228],{"class":227},[88,2269,2116],{"class":220},[15,2271,2273],{"id":2272},"notes","Notes",[20,2275,2276,2286,2309,2328,2353,2363,2372,2381,2388],{},[23,2277,2278,2282,2283,2285],{},[2279,2280,2281],"strong",{},"Order of trust."," Run this from a session already inside ",[33,2284,83],{},", and keep a console or out-of-band connection open the first time, in case the allowlist is wrong.",[23,2287,2288,2291,2292,2295,2296,2298,2299,2301,2302,2304,2305,2308],{},[2279,2289,2290],{},"SecurityLayer, not MinEncryptionLevel, is the one that matters."," ",[33,2293,2294],{},"SecurityLayer"," is ",[33,2297,182],{}," (native RDP security), ",[33,2300,697],{}," (Negotiate, the default) or ",[33,2303,1122],{}," (TLS). Microsoft's policy text for \"Require use of specific security layer for remote (RDP) connections\" calls TLS \"the recommended setting,\" and notes that with RDP or a Negotiate fallback \"the RD Session Host server isn't authenticated.\" The \"Set client connection encryption level\" setting (",[33,2306,2307],{},"MinEncryptionLevel",": 1 Low, 2 Client Compatible, 3 High, 4 FIPS) \"only applies when you are using native RDP encryption\" and \"doesn't apply to SSL encryption.\" The script sets it to High anyway so a later change back to Negotiate doesn't silently fall to Low.",[23,2310,2311,2314,2315,179,2317,2319,2320,2323,2324,2327],{},[2279,2312,2313],{},"The certificate."," With ",[33,2316,2294],{},[33,2318,1122],{}," and nothing else configured, the listener uses its self-signed certificate, so clients see a certificate warning unless you deploy a CA-issued one. The ",[33,2321,2322],{},"Win32_TSGeneralSetting"," WMI class exposes ",[33,2325,2326],{},"SSLCertificateSHA1Hash"," (read\u002Fwrite) for pointing the listener at a certificate by thumbprint.",[23,2329,2330,2333,2334,2337,2338,2341,2342,2341,2345,2348,2349,2352],{},[2279,2331,2332],{},"Group Policy wins."," Values under ",[33,2335,2336],{},"HKLM\\SOFTWARE\\Policies\\Microsoft\\Windows NT\\Terminal Services"," are where the Remote Desktop Session Host policies land (for example ",[33,2339,2340],{},"UserAuthentication",", ",[33,2343,2344],{},"fDisableCdm",[33,2346,2347],{},"fDisableClip",", and ",[33,2350,2351],{},"MaxIdleTime"," in milliseconds). Writing them locally works on a standalone server, but a domain GPO that configures the same setting overwrites them at the next refresh. For a fleet, set the same values in a GPO under Computer Configuration > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host. Session limit changes apply to new sessions; existing sessions keep the old limit until they reconnect.",[23,2354,2355,2358,2359,115],{},[2279,2356,2357],{},"Restricted Admin vs Remote Credential Guard."," Both keep credentials off the target and prevent pass-the-hash, but they differ: Restricted Admin connects to other resources as the server's identity and requires local Administrators membership; Remote Credential Guard gives single sign-on onward, needs Kerberos (no NTLM fallback), and doesn't work through RD Gateway or Connection Broker. Microsoft recommends Restricted Admin for helpdesk connections to possibly compromised machines. To force clients to use one or the other, set \"Restrict delegation of credentials to remote servers\" under Computer Configuration > Administrative Templates > System > Credentials Delegation on the ",[2360,2361,2362],"em",{},"clients",[23,2364,2365,2368,2369,115],{},[2279,2366,2367],{},"Account lockout."," Brute-force protection is the lockout policy, not RDP. Since the October 11, 2022 cumulative updates, Windows supports locking out the built-in local Administrator, and Microsoft's recommended baseline is 10 failed attempts within 10 minutes, locked for 10 minutes. It's on by default only for new Windows 11 22H2 installs; existing servers need it set. On domain members, lockout for domain accounts comes from the domain password policy. For local accounts on a standalone box: ",[33,2370,2371],{},"net accounts \u002Flockoutthreshold:10 \u002Flockoutwindow:10 \u002Flockoutduration:10",[23,2373,2374,2291,2377,2380],{},[2279,2375,2376],{},"Legacy TLS.",[33,2378,2379],{},"-DisableLegacyTls"," changes Schannel for the whole server, not just RDP: IIS, SQL Server connections, LDAPS on a DC and anything else using Schannel lose TLS 1.0 and 1.1 after the restart. Microsoft is disabling both by default in new Windows releases, starting with the 2024 Windows 11 and Windows Server Insider builds, and documents event 36871 as the sign of an application that fails once they're off.",[23,2382,2383,2384,2387],{},"The firewall lookup uses the English display group name \"Remote Desktop\". On a localized OS, find the group name with ",[33,2385,2386],{},"Get-NetFirewallRule -Name \"RemoteDesktop-UserMode-In-TCP\" | Select-Object -Property DisplayGroup"," and adjust.",[23,2389,2390],{},"This doesn't replace putting RDP behind a VPN or an RD Gateway. The allowlist narrows who can reach the port; it adds no authentication beyond NLA.",[15,2392,2394],{"id":2393},"source","Source",[20,2396,2397,2406,2413,2420,2427,2434,2441,2448],{},[23,2398,2399],{},[2400,2401,2405],"a",{"href":2402,"rel":2403},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fclient-management\u002Fmdm\u002Fpolicy-csp-remotedesktopservices",[2404],"nofollow","RemoteDesktopServices Policy CSP (encryption level, drive redirection, registry mappings)",[23,2407,2408],{},[2400,2409,2412],{"href":2410,"rel":2411},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fclient-management\u002Fmdm\u002Fpolicy-csp-admx-terminalserver",[2404],"ADMX_TerminalServer Policy CSP (NLA, security layer, session limits, clipboard)",[23,2414,2415],{},[2400,2416,2419],{"href":2417,"rel":2418},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fwin32\u002Ftermserv\u002Fwin32-tsgeneralsetting",[2404],"Win32_TSGeneralSetting class",[23,2421,2422],{},[2400,2423,2426],{"href":2424,"rel":2425},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows-hardware\u002Fcustomize\u002Fdesktop\u002Funattend\u002Fmicrosoft-windows-terminalservices-rdp-winstationextensions-securitylayer",[2404],"SecurityLayer values (unattend reference)",[23,2428,2429],{},[2400,2430,2433],{"href":2431,"rel":2432},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fsecurity\u002Fidentity-protection\u002Fremote-credential-guard",[2404],"Remote Credential Guard",[23,2435,2436],{},[2400,2437,2440],{"href":2438,"rel":2439},"https:\u002F\u002Fsupport.microsoft.com\u002Fen-us\u002Ftopic\u002Fkb5020282-account-lockout-available-for-built-in-local-administrators-bce45c4d-f28d-43ad-b6fe-70156cb2dc00",[2404],"KB5020282: Account lockout available for built-in local administrators",[23,2442,2443],{},[2400,2444,2447],{"href":2445,"rel":2446},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fwindows\u002Fwin32\u002Fsecauthn\u002Ftls-10-11-deprecation-in-windows",[2404],"TLS 1.0 and TLS 1.1 deprecation in Windows",[23,2449,2450],{},[2400,2451,2454],{"href":2452,"rel":2453},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Ftroubleshoot\u002Fpower-platform\u002Fpower-automate\u002Fdesktop-flows\u002Fdesktop-flow-max-session-duration-error",[2404],"Session time limit registry values (MaxIdleTime, milliseconds)",[2456,2457,2458],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":211,"searchDepth":340,"depth":340,"links":2460},[2461,2462,2463,2464,2465,2466],{"id":17,"depth":340,"text":18},{"id":49,"depth":340,"text":50},{"id":200,"depth":340,"text":201},{"id":360,"depth":340,"text":361},{"id":2272,"depth":340,"text":2273},{"id":2393,"depth":340,"text":2394},"techcolumnist",[2469,2470],"ps","scripts","2025-09-17T14:00:00Z","A PowerShell script that locks down Windows Server RDP: NLA, TLS-only, session limits, redirection, a firewall allowlist, Restricted Admin support and legacy TLS off.","md",false,null,{},"\u002Fblog\u002F2025\u002F09\u002F17\u002Fpowershell-windows-server-harden-rdp-without-breaking-access",{"title":6,"description":2472},[2467],"blog\u002F2025\u002F09\u002F17\u002Fpowershell-windows-server-harden-rdp-without-breaking-access",[210,2482],"windows","\u002F2025\u002F09\u002F17\u002Fpowershell-windows-server-harden-rdp-without-breaking-access\u002F","P79j07cB882vKXGYG49MHOyu08-FtFH2TZDVN9vvUCo",{"title":2486,"description":2487,"date":2488,"url":2489,"categories":2490,"tags":2491,"image":2475,"readingTime":388,"canonical":2467,"sites":2494,"series":2475,"seriesOrder":2475},"PowerShell: Azure – Tag Every Untagged Resource in a Subscription","A PowerShell sweep that finds untagged Azure resources and adds only the missing resource group tags, plus the built-in Azure Policy that does it going forward.","2025-09-24T14:00:00Z","\u002F2025\u002F09\u002F24\u002Fpowershell-azure-tag-every-untagged-resource-in-a-subscription\u002F",[2469,2470],[210,2492,2493],"azure","discovery",[2467],{"title":2496,"description":2497,"date":2498,"url":2499,"categories":2500,"tags":2501,"image":2475,"readingTime":402,"canonical":2467,"sites":2503,"series":2475,"seriesOrder":2475},"PowerShell: Intune – Remediation Script for Stuck BitLocker Encryption","An Intune Remediations detect and remediate pair that finds paused, suspended or stalled BitLocker encryption on Windows and fixes the cases that have a documented fix.","2025-09-10T14:00:00Z","\u002F2025\u002F09\u002F10\u002Fpowershell-intune-remediation-script-for-stuck-bitlocker-encryption\u002F",[2469,2470],[210,2502,2482],"intune",[2467],[2505,2513,2495],{"title":2506,"description":2507,"date":2508,"url":2509,"categories":2510,"tags":2511,"image":2475,"readingTime":388,"canonical":2467,"sites":2512,"series":2475,"seriesOrder":2475},"PowerShell: Windows Server – Disable SMBv1 Fleet-Wide and Verify","A script that audits SMBv1 access (event 3000), disables the SMBv1 server and optional feature across Windows servers, and reports which ones still need a restart.","2025-11-26T14:00:00Z","\u002F2025\u002F11\u002F26\u002Fpowershell-windows-server-disable-smbv1-fleet-wide-and-verify-it-stuck\u002F",[2469,2470],[210,2482],[2467],{"title":2514,"description":2515,"date":2516,"url":2517,"categories":2518,"tags":2519,"image":2475,"readingTime":396,"canonical":2467,"sites":2521,"series":2475,"seriesOrder":2475},"PowerShell: Windows – Discover Local Admins Across Every Workstation","A script that reads the local Administrators group on every workstation by SID, survives orphaned-SID errors, and flags members outside an approved allowlist.","2025-10-08T14:00:00Z","\u002F2025\u002F10\u002F08\u002Fpowershell-windows-discover-local-admins-across-every-workstation\u002F",[2469,2470],[210,2482,2493,2520],"active-directory",[2467],{"doc":2475,"posts":2523},[],1790052513180]