Real-world use case
You need to administer a Windows server over SSH rather than RDP: here's how to install and manage OpenSSH via PowerShell.
Installing and configuring OpenSSH in PowerShell
The secure SSH communication protocol has become a must-have on BSD and GNU/Linux systems, with a history going back to the mid-90s. Microsoft managed, in 2017, to integrate native support for the SSH protocol (beta) into Windows. In 2018, to great relief, the OpenSSH version has been stable since Windows build 1809.
With the growing externalization of information systems, Microsoft is promoting open technologies in their proprietary products. It's now possible to connect to a Windows machine using the SSH communication protocol. In the following article, we'll use the OpenSSH client in Windows 10 and the OpenSSH server in Windows Server 2019 with a key pair, and we'll also discover PowerShell aliases.
Installing the OpenSSH client/server
All the steps will be done in PowerShell as an administrator. On a Windows 10 machine or a Windows 2019 server, it's possible to check the state of the OpenSSH feature:
Get-WindowsCapability -Online | ? Name -like "OpenSSH*"
Name : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
Currently, the feature is available in a notPresent state to install the OpenSSH client or server:
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Once the Windows feature installation is done, here's the result:
Path :
Online : True
RestartNeeded : False
No restart is needed, we'll now run a test of the SSH client in PowerShell:
ssh
usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
[-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
[-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
[-i identity_file] [-J [user@]host[:port]] [-L address]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-Q query_option] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] destination [command]
The client works, we find the source files at the following location: C:WindowsSystem32OpenSSH
ls C:WindowsSystem32OpenSSH
Directory : C:WindowsSystem32OpenSSH
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 05/09/2018 16:07 322560 scp.exe
-a---- 05/09/2018 16:07 390144 sftp.exe
-a---- 05/09/2018 16:07 491520 ssh-add.exe
-a---- 05/09/2018 16:07 384512 ssh-agent.exe
-a---- 05/09/2018 16:07 637952 ssh-keygen.exe
-a---- 05/09/2018 16:07 530432 ssh-keyscan.exe
-a---- 05/09/2018 16:07 882688 ssh.exe
The OpenSSH server uses a dedicated service, the SSH services' status shows:
Get-service ssh*
Status Name DisplayName
------ ---- -----------
Stopped ssh-agent OpenSSH Authentication Agent
Stopped sshd OpenSSH SSH Server
To start the SSHD and SSH-agent services:
net start sshd
The OpenSSH SSH Server service is starting..
The OpenSSH SSH Server service was started successfully.
net start ssh-agent
The OpenSSH Authentication Agent service is starting.
The OpenSSH Authentication Agent service was started successfully.
Let's check that the services have started properly:
Get-service ssh*
Status Name DisplayName
------ ---- -----------
Running ssh-agent OpenSSH Authentication Agent
Running sshd OpenSSH SSH Server
Let's add automatic startup to our SSH service:
Set-Service sshd -StartupType Automatic
Also to the public key control service, so we can use ssh-add.exe later:
Set-Service ssh-agent -StartupType Automatic
The OpenSSH client and server are installed on the Windows machine. We can run a connection test:
ssh user@ip
Configuring SSH aliases in PowerShell
If you have a large number of SSH connections, it can be essential to use aliases in PowerShell.
To do this, we need to configure a profile for our PowerShell command prompt and allow PS1 script execution:
new-item $PROFILE.CurrentUserAllHosts -ItemType file -Force
To access the script from the user:
ise $PROFILE.CurrentUserAllHosts
A warning message appears, since by default group policy applies to script execution. In order to be able to read our script: profile.ps1, we need to change the value to unrestricted.
Set-ExecutionPolicy -Scope CurrentUser
We now need to add:
RemoteSigned
We need to run the command again to access the script from the user:
ise $PROFILE.CurrentUserAllHosts
A new folder is now present in My Documents, along with a profile.ps1 script. Let's edit it with a text editor or the PowerShell ISE editor in order to add an SSH alias:
function sshserver1 { ssh "user@ip"}
It's also possible to use port forwarding like this (e.g.: vnc):
function sshvncserver1 {ssh -L "localhost:5900:localhost:5900" "user@ip"}
Generating an SSH key pair in PowerShell
Key pair authentication is a recommended method, by default, the folder containing it is in your user's personal location: ~.ssh. If it doesn't exist, we need to generate an SSH key pair (e.g.: ecdsa):
ssh-keygen -t ecdsa -b 521
Generating public/private ecdsa key pair.
Enter file in which to save the key (C:Usersmyuser/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:Usersmyuser/.ssh/id_ecdsa.
Your public key has been saved in C:Usersmyuser/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:tryXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX mydomainmyuser@nondns
The key's randomart image is:
+---[ECDSA 521]---+
| |
| |
|. . |
|X. . ... . |
|.X. .XXXXx |
|x .#.X-X.*. |
|. ..X)+&XX |
| . X .-.X. |
| . . ... |
+----[SHA256]-----+
Now we need to add the private key to our SSH server:
ssh-add.exe .id_ecdsa
Enter passphrase for .id_ecdsa:
Identity added:
.id_ecdsa (.id_ecdsa)
To transfer an SSH public key from our client to our server (listening on port e.g.: 2222):
scp -P 2222 C:Usersmyuser.sshid_ecdsa.pub mydomainuser@ip:C:Usersmyuser.ssh/authorized_keys
Once the copy is done, you can connect with your SSH key to the Windows server.
Configuring the OpenSSH server in PowerShell
The configuration options for a Windows SSH server are limited, as the wiki explains: not supported.
In PowerShell, let's run the following command to edit the OpenSSH server's configuration file:
notepad.exe "C:ProgramDatasshsshd_config"
Here's my sshd_config configuration file:
Port 2222
ListenAddress 192.168.0.2
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
Subsystem sftp sftp-server.exe
DenyUsers mydomain.local*
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
It might be necessary to add a firewall rule to allow SSH access:
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Service sshd -Enabled True -Direction Inbound -Protocol TCP -Action Allow -Profile Domain
Name : sshd
DisplayName : OpenSSH Server (sshd)
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Domain
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
Installing and configuring OpenSSH in PowerShell is now complete.



