Remote sessions using OpenSSH from Windows to Linux host

Starting from January 2018, Microsft has made PowerShell Core 6, a cross-platform tool available not only to Windows users which was the case so far with previous versions, but to Linux and Mac users as well.

Since it was tool for Windows only, it had it's own ways for remoting using WinRM unlike Linux operating systems which primarily rely on SSH. Windows is great for editing and development, I find it really comfortable to work on with so many tools and platform available. On the other hand, it is too robust, especially because of it's UI which makes it not so suitable for scaling. On the other hand, you can run Linux as a headless OS which makes is blazing fast, but it is not so comfortable for development because of the lack of UI.

For me winning combination is using Windows for development, but deploy to Linux machine. Now when there is PowerShell runing on both hosts it makes it a lot easier to automate stuff. Let's start with setting up new PowerShell on both host and finally connect from the development Windows machine to deployment Linux machine.

1. Setting up PowerShell on Linux

I will use Debian headless Linux VM for setting up PowerShell 6 Core for this demo, but you are free to use any other distro. If you are planning to install PowerShell 6 Core on any other distro other than Debian 9 Linux, follow the instructions from Microsoft documentation page https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-powershell-core-on-linux?view=powershell-6. Login to your Linux machine using SSH and execute following commands

sudo apt-get update sudo apt-get install curl gnupg apt-transport-https curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list' sudo apt-get update # Install PowerShell sudo apt-get install -y powershell

Now just verify the powershell is installed

pwsh -V

You should get the PowerShell version installed as an output of the command above

2. Configure OpenSSH on Linux host

First thing we need to do to enable OpenSSH connections for PowerShell is to modify OpenSSH config. Open the config using nano editor

sudo nano /etc/ssh/sshd_config

In opened configuration file in nano editor, paste the following live below existing subsystem line

Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile

Save the file and exit nano editor with CTRL+O ENTER to save and CTRL+X key combination to close nano editor

Restart the sshd service in order for it to pick up new configuration

sudo service sshd restart

We have now setup out Linux machine for running PowerShell 6 Core and to accept remote PowerShell sessions over OpenSSH.

3. Setting up PowerShell 6 Core on Windows machine

Setting up PowerShell 6 Core on Windows is pretty straight forward, pretty much like any other application on Windows. Navigate to https://github.com/PowerShell/PowerShell#get-powershell in your browser and download the .msi installer for your Windows platform. Upon download, double click on .msi installation package and follow the wizard instructions.

Verify that PowerShell 6 Core is installed by running the following commands in Windows console

cd C:\Program Files\PowerShell\6.0.2 pwsh -V

You should get the PowerShell Core version installed on your Windows machine. Additionally you can update PATH environment variable from Windows UI. You can access environment variables direly from elevated Command Prompt window by executing the following command

rundll32 sysdm.cpl,EditEnvironmentVariables

Or by running the following command Windows command prompt which will append PowerShell 6 Core installation path folder to PATH environemnt varibale

setx PATH "%PATH%;C:\Program Files\PowerShell\6.0.2" /M

Note Before adding the PowerShell path to PATH Environment Variable, verify that PowerShell Core is installed at that location. Folder may vary depending on the release you installed

4. Setting up OpenSSH on Windows machine

Download OpenSSH binaries for Windows from https://github.com/PowerShell/Win32-OpenSSH/releases. Extract files from downloaded archive on the Windows machine. I picked C:\Program Files\OpenSSH folder. For the consistency with this sample, create same folder on your machine and extract archive to this folder.

Open Windows console as administrator and execute following command

PowerShell -ExecutionPolicy bypass -File "C:\Program Files\OpenSSH\install-sshd.ps1"

You should get the following output from the command above executed

From the elevated command prompt you can run the following command to get you directly to the Windows environment variables window

rundll32 sysdm.cpl,EditEnvironmentVariables

In the System Variables section, locate Path variable and click Edit button

Path list should already contain path to OpenSSH with value %SYSTEMROOT%\System32\OpenSSH\. If this value is not present in the Path list, add the path of OpenSSH installation which is in our case C:\Program Files\OpenSSH.

Open the firewall port for OpenSSH by running the following command from elevated (Run as Administrator) Windows console

netsh advfirewall firewall add rule name=sshd dir=in action=allow protocol=TCP localport=22

Restart sshd service from Control Panel > Administrative Tools > Services of running PowerShell command from elevated Windows console

PowerShell -command "Restart-Service sshd -Force"

5. Connect to remote session from PowerShell 6 Core with OpenSSH

Now when we have PowerShell 6 Core setup on both Windows and Linux host we can try to connect and execute a command for remote session. You can use both Invoke-Command or Enter-Pssession. The command structure for both options is the following

Invoke-Command -Hostname "IP or Hostname" -UserName "Username" -ScriptBlock {PowerShell commands} Enter-Pssession -Hostname "IP or Hostname" -UserName "Username" -ScriptBlock {PowerShell commands}

For and example, let's list the processes on the remote Linux host

Invoke-Command -Hostname 192.168.211.129 -UserName dejan -ScriptBlock {Get-Process}

The output of this command will be the table of all processes currently running on the remote Linux host

References

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.