From time to time I visit my public or private git repository knowing that I’ve faced and solved that problem before, knowing that the solution was tested and work as expected.
In this case, I had a script that was a oneliner ( nothing wrong with), it but to meet the goal I needed to add another 2 lines, so to make it more reusable by other user and still keep it readable and flexible I’ve refactored the script and wrote this article. As mentioned in the title the subject is RDP and Powershell.
This is, without any doubt, a 101 subject for every system administrator.
Microsoft RDP connection
If you’re not familiar with the Microsoft Remote Desktop Protocol, a good place to start is Wikipedia.
I assume that if you’re reading this article you’re using RDP to connect to other Workstations or Servers.
By default, any Windows OS doesn’t allow a user to connect via RDP. Indeed, this setting can be enabled by editing the registry, that by default is set to deny remote access to the host. Once the service is enabled a Local User Group called Remote Desktop Users secure the access by granting to a restricted list of users (all local administrators access is granted implicitly).
Last but not least, a firewall rule needs to be added to the host-based (Windows) firewall to enable the inbound RDP Connection on port 3389 (TCP).
To perform these simple steps via the Gui you’ll visit the System Properties from the Control Panel, Regedit and the Local Users and Groups (mmc snapin) and Windows Firewall, and checking with netstat if the port is open.
Enable-RemoteDesktop Script
If the workstation/server in your local network has the PowerShell remoting you can perform these steps with the following script with no need to login on the Server/Workstation (interactively via a console), but we can do it remotely.
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 |
#Paolo Frigo, https://www.scriptinglibrary.com # This script enables remote desktop connection on the target host, add a firewall rule to the winodws host based firewall and # tests if the standard RDP port is open. # If you want to provide local admin credentials # $cred = Get-Credential Param ( [Parameter( Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] $ComputerName ) #Tests if the target host is reachable if (test-connection -computername $ComputerName -quiet -count 1){ } else { Throw "$computername is not reachable" } #Tests PSRemoting is enabled on the target host if (test-wsman -computername $ComputerName){ #Enables The remote desktop connections invoke-command -computername $ComputerName -scriptblock {Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server'-name "fDenyTSConnections" -Value 0} #-credential $cred #Adds a firewall rule invoke-command -computername $ComputerName -scriptblock {Enable-NetFirewallRule -DisplayGroup "Remote Desktop"} #-credential $cred if ((test-netconnection -computername $ComputerName -port 3389).TcpTestSucceeded -eq $True){ Write-Output "Remote connection ENABLED, Firewall rule ADDED and RDP port OPEN on $ComputerName" } else{ Write-Warning "The RDP port on $ComputerName is BLOCKED" } } else { Throw "$ComputerName hasn't got PS Remoting Enabled" } |
The Old script
There wasn’t anything wrong with the old script, it was documented and working fine, but I thought that reverting to a less polished approach could help to make the code more approachable and reusable by a larger audience.
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 |
#Paolo Frigo, https://www.scriptinglibrary.com <# $Target = "Workstation1" # # Open a remote powershell session Enter-PSSession -Credential $(get-credential -Message "Auth") -ComputerName $Target # Enable Remote Desktop (Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null Get-NetFirewallRule -DisplayName "Remote Desktop*" | Set-NetFirewallRule -enabled true Exit-PSSession #> <# .SYNOPSIS Enable RDP connections on the remote PC .DESCRIPTION Enable RD Connection Services and Firewall Rules that will permit RDP connections to a remote PC. .PARAMETER ComputerName Specify your target computer using a FQDN or IP .EXAMPLE C:\PS>Enable-RemoteDesktopOnTarget -computername "172.16.0.5" -verbose VERBOSE: There are 2 IPs Available on network 172.16.0.* 172.16.0.9 172.16.0.10 .NOTES Author: Paolo Frigo, https://www.scriptinglibrary.com #> function Enable-RemoteDesktopOnTarget{ [CmdletBinding()] Param( # Parameter help description [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [string] $ComputerName ) Begin{ } Process{ Invoke-Command -ComputerName $ComputerName -ScriptBlock { # Enable Remote Desktop (Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null Write-Verbose -Message "$(get-date -Format [dd/MM/yyyy_hh:mm]) - Remote Desktop Services enabled on $ComputerName" Get-NetFirewallRule -DisplayName "Remote Desktop*" | Set-NetFirewallRule -enabled true Write-Verbose -Message "$(get-date -Format [dd/MM/yyyy_hh:mm]) - Firewall Rule enabled for RDP Connections on $ComputerName" } } End{ } } |
Group Policy
This is a one-off script, but to deploy to multiple domain-joined machines it’s always better to use Group Policies by adding a restricted security group to the local remote desktop users group, adding the firewall rule for opening port 3389 and enabling the remote connections.
I recommend to not avoid implementing GPO in favor of scripting, I won’t stress enough about it… using policies wisely to create a security baseline and avoid configuration drifts is necessary for an environment that should be consistent and manageable for a long time.
Wrap Up
I hope you’ll find that enable Remote Desktop on a Windows Os via scripting is simple as much is it using the graphical tools. As usual, you can find this script on my GitHub repository.