374 lines
12 KiB
HTML
374 lines
12 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<link rel="stylesheet" href="main.css" type="text/css" />
|
|
<link rel="stylesheet" href="blog.css" type="text/css" />
|
|
<link rel="alternate" type="application/rss+xml" title="Subscribe to this page..." href="feed.rss" />
|
|
<title>Win32 OpenSSH Package</title>
|
|
</head><body>
|
|
<div id="divbodyholder">
|
|
<div class="headerholder"><div class="header">
|
|
<div id="title">
|
|
<h1 class="nomargin"><a class="ablack" href="http://zigford.org/index.html">zigford.org</a></h1>
|
|
<div id="description"><a href="about.html">About</a><a href="links.html"> | Links</a><a href="scripts.html"> | Scripts</a><br>Sharing linux/windows scripts and tips</br></div>
|
|
</div></div></div>
|
|
<div id="divbody"><div class="content">
|
|
<!-- entry begin -->
|
|
<h3><a class="ablack" href="win32-openssh-package.html">
|
|
Win32 OpenSSH Package
|
|
</a></h3>
|
|
<!-- bashblog_timestamp: #201808140553.41# -->
|
|
<div class="subtitle">August 14, 2018 —
|
|
Jesse Harris
|
|
</div>
|
|
<!-- text begin -->
|
|
<h4 id="update-20092018">Update 20/09/2018</h4>
|
|
<p>Updated the script to UseBasicParsing so it works on Server core out of the box.
|
|
Also, if you have to allow the port on Windows Firewall:</p>
|
|
<p><code>New-NetFirewallRule -DisplayName "Allow SSH" -Direction Inbound -LocalPort 22 -Protocol TCP -Action Allow</code></p>
|
|
<h4 id="update-11092018">Update 11/09/2018</h4>
|
|
<p>I've made a copy of this <a href="scripts.html">script</a> which downloads the dependencies (including
|
|
PSCore. Also of note, on a machine I ran it on, I had to set the allowed .Net
|
|
TLS modes before it would let me download from github.</p>
|
|
<p><code>[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"</code></p>
|
|
<hr />
|
|
<p>I've recently been using Macos at work in order to share
|
|
admin responsibilities across the team. Still suppporting Windows, however
|
|
there are a couple of tools I use to make working Windows from a Mac
|
|
simpler.</p>
|
|
<h2 id="powershell">PowerShell</h2>
|
|
<p>Microsoft Open-Sourced PowerShell in <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">2016</a> and today
|
|
in 2018, you can get stable installations for Macos, Linux and Windows on
|
|
<a href="https://github.com/Powershell/Powershell">github</a> which is often referred
|
|
to as PSCore.</p>
|
|
<p>As an aside, this new version of powershell is not nativly backward
|
|
compatible with compiled binary modules of the previous "Windows Powershell",
|
|
however recently in development is a new module:
|
|
<a href="https://github.com/PowerShell/WindowsCompatibility">WindowsCompatibility</a>
|
|
(currently only available on Windows Insider builds) that allows your to
|
|
import "Windows Powershell" modules into PSCore.</p>
|
|
<p>When alpha and beta builds first became available I started testing remote
|
|
sessions from Linux and Macos to Windows (As I would prefer to work from a
|
|
unix system at work), but quickly found that the native "Enter-PSSession"
|
|
wasn't supported from PSCore.</p>
|
|
<h2 id="openssh">OpenSSH</h2>
|
|
<p>Around the same time, Microsoft began working with the OpenBSD's OpenSSH
|
|
project to bring official OpenSSH builds to Windows and the PSCore team
|
|
found a way to make "Enter-PSSession" work with this.</p>
|
|
<h2 id="packaging-pscore">Packaging PSCore</h2>
|
|
<p>Packaging PSCore is very straightforward and I won't go into detail here.
|
|
Suffice it to say that PSCore is released as an
|
|
<a href="https://en.wikipedia.org/wiki/Windows_Installer">MSI</a> and these are very
|
|
simple to deploy using tools like <a href="https://aka.ms/sccm">Configuration Manager</a>.</p>
|
|
<h2 id="openssh-package">OpenSSH Package</h2>
|
|
<p>Essentially I created a Windows Powershell script which follows the
|
|
installation directions on the Win32 OpenSSH github <a href="https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH">Installation</a> page.</p>
|
|
<h3 id="the-scripts">The Scripts</h3>
|
|
<p>Deploying an application using scripts in Configuration Manager, usually
|
|
requires 3 scripts, and this case is no exception. I have provided the all
|
|
needed scripts below:</p>
|
|
<h4 id="install.ps1">Install.ps1</h4>
|
|
<pre><code>[CmdLetBinding()]
|
|
Param()
|
|
|
|
#region Helper functions
|
|
function Get-Path {
|
|
[CmdLetBinding()]
|
|
Param(
|
|
[ValidateSet(
|
|
"Machine",
|
|
"User"
|
|
)]$Context = "User",
|
|
[Switch]$Raw
|
|
)
|
|
If ($Context -eq "Machine") {
|
|
$Root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
|
|
} else {
|
|
$Root = 'HKCU:'
|
|
}
|
|
If ($Raw){
|
|
Get-ItemPropertyValue -Path "$Root\Environment" -Name Path
|
|
} Else {
|
|
Try {
|
|
|
|
(Get-ItemPropertyValue -Path "$Root\Environment" `
|
|
-Name Path -EA SilentlyContinue) -split ';'
|
|
} Catch {
|
|
Write-Warning "No user environment variables found"
|
|
}
|
|
}
|
|
}
|
|
|
|
function Add-Path {
|
|
[CmdLetBinding()]
|
|
Param(
|
|
[Parameter(Mandatory=$True)]
|
|
[ValidateScript({
|
|
if (Test-Path -Path $_) {
|
|
$True
|
|
} else {
|
|
throw "Unable to validate path $_"
|
|
}
|
|
})]$Path,
|
|
[ValidateSet(
|
|
"Machine",
|
|
"User"
|
|
)]$Context
|
|
)
|
|
|
|
Write-Verbose "Adding $Path to environment"
|
|
if ($Context -eq 'Machine') {
|
|
If (! $Path -in (Get-Path -Context Machine)){
|
|
Write-Verbose "Adding $Path to machine context"
|
|
setx /m PATH "$(Get-Path -Context Machine -Raw);$Path"
|
|
}
|
|
} else {
|
|
Write-Verbose "Adding $Path to user context"
|
|
If (! $Path -in (Get-Path -Context User)){
|
|
Write-Verbose "Adding $Path to user context"
|
|
setx PATH "$(Get-Path -Context Use -Raw);$Path"
|
|
}
|
|
}
|
|
}
|
|
|
|
function New-SymbolicLink {
|
|
Param($Link,$Target)
|
|
If (-Not (Test-Path -Path $Link)){
|
|
If ((Get-Item $Target).PSIsContainer) {
|
|
cmd.exe /c mklink /D $Link $Target
|
|
} Else {
|
|
cmd.exe /c mklink $Link $Target
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
# Extract OpenSSH
|
|
$Archive = Get-ChildItem -Filter *.zip
|
|
Expand-Archive -Path $Archive -DestinationPath $env:ProgramFiles
|
|
Rename-Item -Path $Env:ProgramFiles\OpenSSH-Win64 -NewName OpenSSH
|
|
|
|
#Add InstallDir to Path
|
|
Add-Path -Path $Env:ProgramFiles\OpenSSH -Context Machine -Verbose
|
|
|
|
# Configure OpenSSH
|
|
& $Env:ProgramFiles\OpenSSH\install-sshd.ps1
|
|
|
|
# Start sshd service
|
|
|
|
Start-Service -Name sshd
|
|
|
|
# Set service startup
|
|
|
|
Set-Service sshd -StartupType Automatic
|
|
Set-Service ssh-agent -StartupType Automatic
|
|
|
|
# Setup pwsh link to work around
|
|
# https://github.com/PowerShell/Win32-OpenSSH/issues/784
|
|
# Find PSCore Install and Make symbolic link
|
|
|
|
$PSCoreDir = Get-ChildItem -Path $env:ProgramFiles\PowerShell `
|
|
-Directory | Select-Object -Last 1
|
|
New-SymbolicLink -Link $env:SystemDrive\pwsh -Target $PSCoreDir.FullName
|
|
|
|
# Enable Password Authentication and set pwsh as default shell
|
|
$NewConfig = Get-Content -Path $Env:ProgramData\ssh\sshd_config |
|
|
ForEach-Object {
|
|
Switch ($_) {
|
|
{$_ -match '^#PasswordAuthentication\syes'} {$_.replace('#','')}
|
|
{$_ -match '^#PubkeyAuthentication\syes'} {$_.replace('#','')}
|
|
{$_ -match '^Subsystem\s+sftp\s+'} {
|
|
'Subsystem powershell c:\pwsh\pwsh.exe -sshs -NoLogo -NoProfile'
|
|
}
|
|
Default {$_}
|
|
}
|
|
}
|
|
# Update sshd config
|
|
Set-Content -Path $Env:ProgramData\ssh\sshd_config -Value $NewConfig `
|
|
-Force
|
|
|
|
# Restart sshd
|
|
Restart-Service sshd
|
|
</code></pre>
|
|
<h4 id="uninstall.ps1">Uninstall.ps1</h4>
|
|
<pre><code>[CmdLetBinding()]
|
|
Param()
|
|
|
|
#region Helper functions
|
|
|
|
function Remove-SymbolicLink {
|
|
Param($Link,$Target)
|
|
If (Test-Path -Path $Link){
|
|
If ((Get-Item $Target).PSIsContainer) {
|
|
cmd.exe /c rmdir $Link
|
|
|
|
} Else {
|
|
cmd.exe /c del $Link
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function Get-Path {
|
|
[CmdLetBinding()]
|
|
Param(
|
|
[ValidateSet(
|
|
"Machine",
|
|
"User"
|
|
|
|
)]$Context = "User",
|
|
[Switch]$Raw
|
|
|
|
)
|
|
If ($Context -eq "Machine") {
|
|
$Root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
|
|
|
|
} else {
|
|
$Root = 'HKCU:'
|
|
|
|
}
|
|
If ($Raw){
|
|
Get-ItemPropertyValue -Path "$Root\Environment" -Name Path
|
|
|
|
} Else {
|
|
Try {
|
|
|
|
(Get-ItemPropertyValue -Path "$Root\Environment" `
|
|
-Name Path -EA SilentlyContinue) -split ';'
|
|
|
|
} Catch {
|
|
Write-Warning "No user environment variables found"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function Remove-Path {
|
|
[CmdLetBinding()]
|
|
Param(
|
|
[Parameter(Mandatory=$True)]
|
|
$Path,
|
|
[ValidateSet(
|
|
"Machine",
|
|
"User"
|
|
|
|
)]$Context
|
|
|
|
)
|
|
|
|
Write-Verbose "Removing $Path from environment"
|
|
if ($Context -eq 'Machine') {
|
|
If ($Path -in (Get-Path -Context Machine)){
|
|
Write-Verbose "Removing $Path from machine context"
|
|
$NewPath = ""
|
|
Get-Path -Context Machine | Where-Object {
|
|
$psItem -ne $Path -and
|
|
$psItem -ne ""
|
|
|
|
} ForEach-Object {
|
|
$NewPath += "$psItem;"
|
|
|
|
}
|
|
setx /m PATH "$NewPath"
|
|
|
|
}
|
|
|
|
} else {
|
|
Write-Verbose "Removing $Path from user context"
|
|
If ($Path -in (Get-Path -Context User)){
|
|
Write-Verbose "Removing $Path from user context"
|
|
$NewPath = ""
|
|
Get-Path -Context User | Where-Object {
|
|
$psItem -ne $Path -and
|
|
$psItem -ne ""
|
|
|
|
} ForEach-Object {
|
|
$NewPath += "$psItem;"
|
|
|
|
}
|
|
setx PATH "$NewPath"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
& $Env:ProgramFiles\OpenSSH\uninstall-sshd.ps1
|
|
|
|
# Extract OpenSSH
|
|
Remove-Item -Path $env:ProgramFiles\OpenSSH -Recurse -Force
|
|
Remove-Path -Path $env:ProgramFiles\OpenSSH -Context Machine -Verbose
|
|
|
|
# Find PSCore Install and remove symbolic link
|
|
|
|
$PSCoreDir = Get-ChildItem -Path $env:ProgramFiles\PowerShell -Directory | Select-Object -Last 1
|
|
Remove-SymbolicLink -Link $env:SystemDrive\pwsh -Target $PSCoreDir.FullName
|
|
|
|
# Remove old config
|
|
Remove-Item -Path $env:ProgramData\ssh -Recurse -Force
|
|
</code></pre>
|
|
<h4 id="detect.ps1">Detect.ps1</h4>
|
|
<pre><code>$AssumeInstalled = $True
|
|
|
|
If (-Not (Test-Path $Env:ProgramFiles\OpenSSH)) {
|
|
$AssumeInstalled = $False
|
|
|
|
}
|
|
|
|
If (-Not (Test-Path $Env:SystemDrive\pwsh)) {
|
|
$AssumeInstalled = $False
|
|
|
|
}
|
|
|
|
If (-Not (Get-Service sshd -ErrorAction SilentlyContinue)) {
|
|
$AssumeInstalled = $False
|
|
|
|
}
|
|
|
|
If ($AssumeInstalled) {
|
|
Write-Output "True"
|
|
|
|
}
|
|
</code></pre>
|
|
<h2 id="using-openssh-with-powershell">Using OpenSSH with Powershell</h2>
|
|
<p>Now that I have used these scripts to deploy OpenSSH and PSCore, I can
|
|
PSRemote to a PC using my Mac.</p>
|
|
<p>The old way to use "Enter-PSSession" was by specifying the ComputerName
|
|
parameter like so:</p>
|
|
<pre><code>PS\> Enter-PSSession -ComputerName Blah
|
|
</code></pre>
|
|
<p>However, when using OpenSSH with a PS Session you do the following:</p>
|
|
<pre><code>PS\> Enter-PSSession -HostName Blah -UserName MrBlah
|
|
</code></pre>
|
|
<p>You could also setup a session in a variable and resue it multiple times
|
|
in a session:</p>
|
|
<pre><code>PS\> $s = New-PSSesssion -HostName Blah -UserName MrBlah
|
|
PS\> Enter-PSSession -Session $s
|
|
|
|
[Blah] PS\>
|
|
</code></pre>
|
|
<p>I hope you have found this usefull.</p>
|
|
<p>Tags: <a href='tag_powershell.html'>powershell</a>, <a href='tag_pscore.html'>pscore</a>, <a href='tag_openssh.html'>openssh</a>, <a href='tag_windows.html'>windows</a>, <a href='tag_macos.html'>macos</a></p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- text end -->
|
|
<!-- entry end -->
|
|
</div>
|
|
<div id="footer">© <a href="http://twitter.com/zigford_org">Jesse Harris</a> — <a href="mailto:jesse@zigford.org">jesse@zigford.org</a><br/>
|
|
Generated with <a href="https://github.com/cfenollosa/bashblog">bashblog</a>, a single bash script to easily create blogs like this one</div>
|
|
</div></div>
|
|
</body></html>
|