Skip to content

Instantly share code, notes, and snippets.

@jeremygaither
Last active October 11, 2019 21:01
Show Gist options
  • Save jeremygaither/0979e4c2e6e3a4a69467dcc85d8a1eed to your computer and use it in GitHub Desktop.
Save jeremygaither/0979e4c2e6e3a4a69467dcc85d8a1eed to your computer and use it in GitHub Desktop.
# Invoke with:
# [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls11,Tls12'; Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-WebRequest -UseBasicParsing -Uri "https://gist.github.com/jeremygaither/0979e4c2e6e3a4a69467dcc85d8a1eed/raw/Enable-WinRMRemoting.ps1" | Invoke-Expression
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
If (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Write-Warning "You do not have Administrator rights to run this script!"
exit 1
}
Write-Output "$(Get-Date -Format u) ==> Set Power Plan: High Performance"
$powerPlan = Get-CimInstance -Name root\cimv2\power -Class win32_PowerPlan -Filter "ElementName = 'High Performance'"
Invoke-CimMethod -InputObject $powerPlan -MethodName Activate
Write-Output "$(Get-Date -Format u) ==> Enabling Windows Remote Management and PowerShell Remoting..."
Write-Output "$(Get-Date -Format u) --> Configure Networking Profile"
# disable annoying popup
$registryNewNetworkWindowOff = "HKLM:\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"
if (!(Test-Path $registryNewNetworkWindowOff)) {
New-Item -Path $registryNewNetworkWindowOff -Force
}
# winrm and psremoting wants adapters in Private networks
$netAdapters = Get-NetAdapter -Name "*"
foreach ($adapter in $netAdapters) {
Write-Output ("Seting connection profile on " + $adapter.Name)
Set-NetConnectionProfile -InterfaceAlias $adapter.Name -NetworkCategory Private
}
Write-Output "$(Get-Date -Format u) --> Configure WinRM"
Write-Output "$(Get-Date -Format u) ----> Ensure firewall rules exist"
# Configure-SMRemoting fails if expected firewall rules are not present
try {
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)"
Disable-NetFirewallRule -InputObject $httpWinrmRule
Write-Output "HTTP firewall rule disabled"
}
catch {
Write-Output "No original HTTP firewall rule found, creating..."
$httpWinrmRule = New-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)" -Name "Windows Remote Management (HTTP-In)" -Profile Any -LocalPort 5985 -Protocol TCP -RemoteAddress Any
Disable-NetFirewallRule -InputObject $httpWinrmRule
Write-Output "new HTTP firewall rule disabled"
}
Write-Output "$(Get-Date -Format u) ----> Disable default SMRemoting to clean up settings"
& "$env:SYSTEMROOT\System32\Configure-SMRemoting.exe" -disable | Out-String
Write-Output "$(Get-Date -Format u) ----> Enable SMRemoting"
& "$env:SYSTEMROOT\System32\Configure-SMRemoting.exe" -enable | Out-String
Write-Output "$(Get-Date -Format u) ----> Enable PSRemoting"
Enable-PSRemoting -Force
Write-Output "$(Get-Date -Format u) ----> Override UAC and allow all remote admin actions"
$regLocalPolicies="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
if (!(Test-Path $regLocalPolicies)) {
New-Item -Path $regLocalPolicies -Force
}
Remove-ItemProperty -Path $regLocalPolicies -Name "LocalAccountTokenFilterPolicy" -Force -ErrorAction Ignore
New-ItemProperty -Path $regLocalPolicies -Name "LocalAccountTokenFilterPolicy" -PropertyType "DWord" -Value 1 -Force
Write-Output "$(Get-Date -Format u) ----> Disable default WinRM firewall rules during listener config"
# Get-NetFirewallPortFilter not always working on Win2012
try {
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)"
Disable-NetFirewallRule -InputObject $httpWinrmRule
Write-Output "HTTP firewall rule disabled"
}
catch {
Write-Output "No HTTP firewall rule found"
}
try {
$httpsWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)"
Disable-NetFirewallRule -InputObject $httpsWinrmRule
Write-Output "WinRM HTTPS firewall rule disabled"
}
catch {
Write-Output "No WinRM HTTPS firewall rule found"
}
Write-Output "$(Get-Date -Format u) ----> Reconfigure WinRM Listeners"
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
Write-Output "old certificates:"
$certSubjectName = "CN=" + $env:COMPUTERNAME
Get-ChildItem -Path cert:\localmachine\My -Recurse | `
Where-Object { $_.Subject -eq ($certSubjectName)} | `
Format-Table subject, thumbprint, notbefore, notafter -AutoSize
Write-Output "Removing old certificates..."
Get-ChildItem -Path cert:\localmachine\My -Recurse | `
Where-Object { $_.Subject -eq ($certSubjectName)} | `
Remove-Item -Force
Write-Output "Creating new certificate..."
$SubjectName = $env:COMPUTERNAME
$ValidDays = 3650
$hostnonFQDN = $SubjectName
$SignatureAlgorithm = "SHA256"
$name = New-Object -COM "X509Enrollment.CX500DistinguishedName.1"
$name.Encode("CN=$SubjectName", 0)
$key = New-Object -COM "X509Enrollment.CX509PrivateKey.1"
$key.ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider"
$key.KeySpec = 1
$key.Length = 4096
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)"
$key.MachineContext = 1
$key.Create()
$serverauthoid = New-Object -COM "X509Enrollment.CObjectId.1"
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1")
$ekuoids = New-Object -COM "X509Enrollment.CObjectIds.1"
$ekuoids.Add($serverauthoid)
$ekuext = New-Object -COM "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1"
$ekuext.InitializeEncode($ekuoids)
$cert = New-Object -COM "X509Enrollment.CX509CertificateRequestCertificate.1"
$cert.InitializeFromPrivateKey(2, $key, "")
$cert.Subject = $name
$cert.Issuer = $cert.Subject
$cert.NotBefore = (Get-Date).AddDays(-1)
$cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)
$SigOID = New-Object -ComObject X509Enrollment.CObjectId
$SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value)
$AlternativeName = @()
$AlternativeName += $hostnonFQDN
$AlternativeName += [System.Net.Dns]::GetHostName()
$ec2Hosatname = $null
try {
$ec2Hostname = (Invoke-WebRequest -UseBasicParsing -Uri "http://169.254.169.254/latest/meta-data/local-hostname" -ErrorAction "Stop").Content
if ([String].IsNullOrWhiteSpace($ec2Hostname)) {
Write-Output "dns resolution for computername was empty"
}
else {
$AlternativeName += $ec2Hostname
}
}
catch {
Write-Output "unable to add ec2 local-hostname to certificate"
}
$resolvedHostname = $null
try {
$resolvedHostname = [System.Net.Dns]::GetHostByName(($env:COMPUTERNAME)).Hostname
if ([String].IsNullOrWhiteSpace($resolvedHostname)) {
Write-Output "dns resolution for computername was empty"
}
else {
$AlternativeName += $resolvedHostname
}
}
catch {
Write-Output "unable to add DNS resolved hostname to certificate"
}
$IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames
foreach ($AN in $AlternativeName)
{
$AltName = New-Object -ComObject X509Enrollment.CAlternativeName
$AltName.InitializeFromString(0x3,$AN)
$IAlternativeNames.Add($AltName)
}
$SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames
$SubjectAlternativeName.InitializeEncode($IAlternativeNames)
[String[]]$KeyUsage = ("DigitalSignature", "KeyEncipherment")
$KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage
$KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage))
$KeyUsageObj.Critical = $true
$cert.X509Extensions.Add($KeyUsageObj)
$cert.X509Extensions.Add($ekuext)
$cert.SignatureInformation.HashAlgorithm = $SigOID
$CERT.X509Extensions.Add($SubjectAlternativeName)
$cert.Encode()
$enrollment = New-Object -COM "X509Enrollment.CX509Enrollment.1"
$enrollment.InitializeFromRequest($cert)
$certdata = $enrollment.CreateRequest(0)
$enrollment.InstallResponse(2, $certdata, 0, "")
Write-Output "New certificate:"
$certificateThumbprint = $null
Get-ChildItem -Path cert:\localmachine\My -Recurse | `
Where-Object { $_.Subject -eq ($certSubjectName)} | `
Format-Table subject, thumbprint, notbefore, notafter -AutoSize
$certs = Get-ChildItem -Path cert:\localmachine\My -Recurse | `
Where-Object { $_.Subject -eq ($certSubjectName) }
foreach ($cert in $certs) {
Write-Output ("Cert: " + $cert.Subject + " = " + $cert.Thumbprint)
$certificateThumbprint = $cert.Thumbprint
}
Write-Output "new thumbprint: " $certificateThumbprint
New-Item -Path WSMan:\Localhost\Listener `
-Transport HTTPS `
-Address * `
-CertificateThumbPrint $certificateThumbprint `
-Force
# allow non-domain and non-ntlm authentication (over https)
Set-Item -Path WSMan:\Localhost\Service\Auth\Basic true -Force
# prevent out of memory crashes
Set-Item -Path WSMan:\localhost\Shell\MaxMemoryPerShellMB -Value 4096 -Force
Set-Item -Path WSMan:\localhost\Plugin\Microsoft.PowerShell\Quotas\MaxMemoryPerShellMB -Value 4096 -Force
Write-Output "$(Get-Date -Format u) ----> Restrict WinRM to internal subnets"
try {
$httpsWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)"
Remove-NetFirewallRule -InputObject $httpsWinrmRule
Write-Output "Old HTTPS firewall rule disabled"
}
catch {
Write-Output "No old HTTPS firewall rule found"
}
New-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" -Name "Windows Remote Management (HTTPS-In)" -Profile Any -LocalPort 5986 -Protocol TCP -RemoteAddress '10.0.0.0/8'
Write-Output "New HTTPS firewall rule created"
Write-Output "$(Get-Date -Format u) ----> Ensure WinRM over HTTP is still blocked"
try {
$httpWinrmRule = Get-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)"
Disable-NetFirewallRule -InputObject $httpWinrmRule
Write-Output "HTTP firewall rule disabled"
}
catch {
Write-Output "No HTTP firewall rule found"
}
Write-Output "$(Get-Date -Format u) ----> Restarting WinRM to enable changes"
Restart-Service -Force winrm
Write-Output "$(Get-Date -Format u) --> Enable other useful networking features"
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Enable-NetFirewallRule -DisplayGroup "File and Printer Sharing"
Enable-NetFirewallRule -DisplayGroup "Network Discovery"
Write-Output "$(Get-Date -Format u) --> COMPLETE: Windows Remote Management and PowerShell Remoting enabled!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment