Remote Desktop Gateway (RD Gateway) provides secure, encrypted access to internal Remote Desktop servers through HTTPS. Instead of exposing RDP port 3389 directly to the internet, RD Gateway tunnels RDP traffic over SSL/TLS on port 443, significantly improving security. This guide covers deploying RD Gateway on your Windows Server VPS.
Why RD Gateway?
- Security: No need to expose port 3389 to the internet
- SSL encryption: RDP traffic tunneled over HTTPS (port 443)
- Access control: Connection Authorization Policies (CAPs) and Resource Authorization Policies (RAPs)
- NLA support: Network Level Authentication before establishing a session
- Audit logging: Track all connections through the gateway
Install RD Gateway Role
# Install Remote Desktop Gateway and dependencies
Install-WindowsFeature -Name RDS-Gateway -IncludeManagementTools -IncludeAllSubFeature
# This also installs:
# - IIS (required for HTTPS)
# - Network Policy Server (NPS)
# - RPC over HTTP Proxy
# Verify installation
Get-WindowsFeature RDS-Gateway
Configure SSL Certificate
# Option 1: Use Let's Encrypt with win-acme
C:\win-acme\wacs.exe --target manual --host rdgw.example.com `
--store certificatestore --certificatestore My `
--installation script --script "powershell.exe" `
--scriptparameters "-Command Import-Module RemoteDesktopServices; Set-Item -Path 'RDS:\GatewayServer\SSLCertificate\Thumbprint' -Value '{CertThumbprint}'"
# Option 2: Import an existing certificate
$cert = Import-PfxCertificate -FilePath "C:\certs\rdgw.pfx" `
-CertStoreLocation "Cert:\LocalMachine\My" `
-Password (ConvertTo-SecureString "CertP@ss" -AsPlainText -Force)
# Apply certificate to RD Gateway
Import-Module RemoteDesktopServices
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $cert.Thumbprint
Create Authorization Policies
# Connection Authorization Policy (CAP) — who can connect
Import-Module RemoteDesktopServices
# Create CAP
New-Item -Path "RDS:\GatewayServer\CAP" -Name "AllowDomainUsers" `
-UserGroups @("CORP\Domain Users") `
-AuthMethod 1 # Password authentication
# Allow specific groups
New-Item -Path "RDS:\GatewayServer\CAP" -Name "AllowITAdmins" `
-UserGroups @("CORP\IT Administrators") `
-AuthMethod 1
# Resource Authorization Policy (RAP) — what they can connect to
New-Item -Path "RDS:\GatewayServer\RAP" -Name "AllowInternalServers" `
-UserGroups @("CORP\Domain Users") `
-ComputerGroupType 2 # Allow any network resource
# Or restrict to specific computers
New-Item -Path "RDS:\GatewayServer\RAP" -Name "AllowSpecificServers" `
-UserGroups @("CORP\IT Administrators") `
-ComputerGroupType 1 `
-ComputerGroup "CORP\RDP Servers"
Configure Gateway Settings
# Set maximum connections
Set-Item -Path "RDS:\GatewayServer\MaxConnections" -Value 100
# Enable logging
Set-Item -Path "RDS:\GatewayServer\EnableLogging" -Value 1
# Set idle timeout (minutes)
Set-Item -Path "RDS:\GatewayServer\IdleTimeout" -Value 120
# Set session timeout (minutes)
Set-Item -Path "RDS:\GatewayServer\SessionTimeout" -Value 480
# Configure firewall
New-NetFirewallRule -DisplayName "RD Gateway (HTTPS)" `
-Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
# Optionally enable UDP transport for better performance
New-NetFirewallRule -DisplayName "RD Gateway (UDP)" `
-Direction Inbound -Protocol UDP -LocalPort 3391 -Action Allow
Client Configuration
# Configure RDP client to use the gateway
# In the .rdp file, add:
gatewayhostname:s:rdgw.example.com
gatewayusagemethod:i:1
gatewayprofileusagemethod:i:1
gatewayaccesstoken:s:
# Or configure via PowerShell on client machines (GPO-deployable):
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Terminal Server Client" `
-Name "DefaultGateway" -Value "rdgw.example.com"
# Group Policy deployment:
# Computer Config > Admin Templates > Windows Components > Remote Desktop Services
# > RD Gateway > Set RD Gateway server address
Monitoring and Troubleshooting
# View active connections
Get-WmiObject -Namespace "root\CIMV2\TerminalServices" `
-Class "Win32_TSGatewayConnection" | `
Select-Object UserName, ConnectedResource, ConnectedTime | `
Format-Table
# Check RD Gateway event logs
Get-WinEvent -LogName "Microsoft-Windows-TerminalServices-Gateway/Operational" `
-MaxEvents 50 | Format-Table TimeCreated, Message -Wrap
# Test gateway connectivity
Test-NetConnection rdgw.example.com -Port 443
# Check certificate
$cert = Get-Item "RDS:\GatewayServer\SSLCertificate\Thumbprint"
Get-ChildItem Cert:\LocalMachine\My\$cert | Select-Object Subject, NotAfter
Best Practices
- Use a public SSL certificate — self-signed certs cause connection errors for external users
- Enable NLA (Network Level Authentication) on all target RDP servers
- Use MFA: Integrate with Azure MFA or DUO for two-factor authentication
- Restrict RAP targets: Don't allow access to "any network resource" — specify allowed servers
- Monitor connections: Review gateway logs for unauthorized access attempts
- Keep the gateway updated with the latest security patches
- Use separate gateway server: Don't run RD Gateway on the same server users RDP into