Last active
August 27, 2020 11:46
-
-
Save Pandry/8494d9dab993b72148272b00ff4fa8e0 to your computer and use it in GitHub Desktop.
SSH Server on Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Author: github.com/Pandry | |
# Version: 1.1 | |
# Tested: Windows Server 2012 with Powershell 4 | |
# Lowest system tested: Windows Server 2008 R2 SP1 with Powershell 3 | |
#Your Public Key | |
$SSHPublicKey = "" | |
if ((Get-Host).Version.Major -lt 3){ | |
Write-Host -ForegroundColor Red "Warning! This script has not been tested with your powershell version $((Get-Host).Version.Major)!" | |
exit 1 | |
} | |
# Check for permissions to execute actions | |
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")){ | |
Write-Host -ForegroundColor Red "Error! Needed Administrator permissions to run!" | |
exit 1 | |
} | |
try { | |
if ((Get-Command "Get-WindowsCapability" -errorAction SilentlyContinue) -And ((Invoke-Expression "(Get-WindowsCapability -Online | ? Name -like 'OpenSSH*').count") -eq 2) ) { | |
Write-Host -ForegroundColor Green "Installing as Windows Capability" | |
# OpenSSH can be installed as a windows feature | |
# If installing the feature returns an error (0x800f0954), there is a gp that blocks the installation | |
# gpedit.msc => "Computer Configuration/Administrative Templates/System" "Specify settings for optional component installation and component repair" => Enable and tick the Download content from windows update checkbox (or delete this block ) | |
Get-WindowsCapability -Online | ? name -like *OpenSSH.Client* | Add-WindowsCapability -Online | |
Get-WindowsCapability -Online | ? name -like *OpenSSH.Server* | Add-WindowsCapability -Online | |
# Create a firewall rule if necessary | |
if ((Get-NetFirewallRule -Name *ssh* | group Name).count -eq 0) { | |
# The rule name is the same as the one the installation of the feature creates | |
New-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 | |
} | |
} else { | |
if (-not (Test-Path "C:\Program Files\OpenSSH" -PathType container )){ | |
Write-Host -ForegroundColor Green "Installing downloading the binary" | |
# OpenSSH cannot be installed as a Windows feature | |
# "Hacky" way to set the SecurityProtocol to the latest version | |
# This is required (at least TLS1.1) to maange the HTTPS link | |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::$([Net.SecurityProtocolType].GetEnumNames()[[Net.SecurityProtocolType].GetEnumNames().count -1]) | |
# The previous line can create some issue from time to time, temporarly using TLS12 | |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | |
#Download the latest version of the SSH server | |
$opensshUrlPath = "https://github.com/PowerShell/Win32-OpenSSH/releases/latest/download/OpenSSH-Win64.zip" | |
$downloadPath = "$env:temp\OpenSSH-Win64.zip" | |
(New-Object -TypeName System.Net.WebClient).DownloadFile("$opensshUrlPath", "$downloadPath") | |
# Unzip the file into the program files path | |
if (Get-Command "Expand-Archive" -errorAction SilentlyContinue) { | |
Expand-Archive -LiteralPath "$downloadPath" -DestinationPath "C:\Program Files\" -Force | |
} else { | |
[System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | |
[System.IO.Compression.ZipFile]::ExtractToDirectory($downloadPath, "C:\Program Files\") | |
} | |
# Remove the ZIP file | |
Remove-Item "$downloadPath" | |
# Rename the openssh version to the lastet version | |
Rename-Item "C:\Program Files\OpenSSH-Win64" "C:\Program Files\OpenSSH" | |
powershell.exe -ExecutionPolicy ByPass -File "C:\Program Files\OpenSSH\install-sshd.ps1" | |
}else{ | |
Write-Host -ForegroundColor Yellow "Seems like the server is already installed" | |
} | |
Start-Service sshd | |
Set-Service -Name sshd -StartupType 'Automatic' | |
} | |
try { | |
# Create a firewall rule if necessary | |
if (Get-Command "Get-WindowsCapability" -errorAction SilentlyContinue) { | |
if ((Get-NetFirewallRule -Name *ssh* | group Name).count -eq 0 ) { | |
# The rule name is the same as the one the installation of the feature creates | |
New-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 | |
} | |
}else{ | |
netsh advfirewall firewall add rule name="OpenSSH-Server-In-TCP" description="OpenSSH Server (sshd)" dir=in action=allow protocol=TCP localport=22 | |
} | |
} catch { | |
Write-Host -ForegroundColor Red "Error in checking or creating the firewall rule:" | |
Write-Host $_ | |
} | |
# Adding SSH Key | |
if ($SSHPublicKey -ne "" -And (-not (Test-Path "C:\ProgramData\ssh\administrators_authorized_keys" -PathType leaf ))) { | |
Set-Content -Path "C:\ProgramData\ssh\administrators_authorized_keys" -Value $SSHPublicKey | |
Write-Host -ForegroundColor Green "Setted public key" | |
} | |
$acl = Get-Acl "C:\ProgramData\ssh\administrators_authorized_keys" | |
$acl.SetAccessRuleProtection($true, $false) | |
$administratorsRule = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow") | |
$systemRule = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow") | |
$acl.SetAccessRule($administratorsRule) | |
$acl.SetAccessRule($systemRule) | |
$acl | Set-Acl | |
} catch [System.Management.Automation.CommandNotFoundException] { | |
Write-Host -ForegroundColor Red "Error in executing the script. Command not found:" | |
Write-Host $_ | |
} catch { | |
Write-Host -ForegroundColor Red "Error in executing the script." | |
Write-Host "${$_.Exception.ItemName}: ${$_.Exception.Message}" | |
Write-Host -ForegroundColor Red "Full exception:" | |
Write-Host $_ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment