PowerShell 6 Core comes with a new feature that allows you to work with PowerShell remoting using SSH transport instead of WinRM-based remoting, which uses the HTTP/HTTPS protocol. SSH-based PowerShell remoting has two main advantages. It is easier to set up for machines not members of an Active Directory domain, and you can work with any SSH client on any operating system to manage remote computers with PowerShell.
Latest posts by Michael Pietroforte (see all)

Why SSH transport for PowerShell remoting?

You can use PowerShell remoting cmdlets such as Enter-PSsession and Invoke-Command on a PowerShell 6 console via SSH. However, as you can see in the screenshot below, PowerShell remoting works nicely in the popular SSH client PuTTY. Of course, you can work with any SSH client. SSH is certainly the most common remote management protocol, and clients are available for all operating systems.

Running PowerShell 6 in PuTTY

Running PowerShell 6 in PuTTY

The main advantage of PowerShell remoting via SSH is that it easier to manage in environments without Active Directory. If you work with WinRM in this case, you have to configure trusted hosts and set up PowerShell remoting for HTTPS because the default protocol HTTP is not secure outside an Active Directory domain. SSH's host identification and public key authentication are secure, and you don't have to mess with SSL/TLS certificates as with HTTPS.

Enabling SSH for PowerShell on the host

Below I show you how can install and enable PowerShell remoting for SSH transport. As you will notice, the process differs significantly from enabling remoting for WinRM. One big difference is that you no longer need the Enable-PSremoting cmdlet.

Note that you need PowerShell Core 6 to follow this guide because only the latest release of Microsoft's scripting language comes with the required SSH support.

    1. Download the PowerShell 6 Core MSI and install it on your Windows machine. This is a simple next-next installation. Note that I am working with PowerShell 6.0 here because 6.1 is still in preview at the time of this writing.
    2. Download OpenSSH for Windows. I worked with the 64-bit version for this guide.
    3. Extract the OpenSSH-Win64.zip file and copy OpenSSH-Win64 to C:\Program Files\ (the 32-bit edition is fine too).
    4. Rename OpenSSH-Win64 to OpenSSH.
    5. Execute the command below to install OpenSSH:
      powershell.exe -ExecutionPolicy Bypass -File "C:\Program Files\OpenSSH\install-sshd.ps1"
    6. Next, we'll add the OpenSSH location to the PATH environment variable to ensure the operating system finds the OpenSSH executables. At a PowerShell console you can run the commands below:
      $env:Path="$env:Path;C:\Program Files\OpenSSH\"
      Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $env:Path

      Installing OpenSSH

      Installing OpenSSH

    7. We can now start the SSH service (sshd) with this PowerShell command:
      Start-Service sshd
    8. I recommend automatically starting the OpenSSH services sshd:
      Set-Service sshd -StartupType Automatic
    9. Launch Notepad as admin (right-click and select Run as administrator) and open sshd_config in C:\ProgramData\SSH\ (change the file type to *.*, otherwise you'll only see .txt files). Note that the ProgramData folder is hidden, and you will therefore only see the file if you enabled Hidden items in the File Explorer View.
    10. Comment out this line in sshd_config "Subsystem sftp   sftp-server.exe" and add this one instead:
      Subsystem powershell c:/program files/powershell/6.0.2/pwsh.exe -sshs -NoLogo -NoProfile
      Editing sshd config

      Editing sshd config

      Note that the path may vary if you work with another PowerShell Core version.

    11. To allow remote connections in the Windows Firewall, you have to open the SSH port (22). On a Windows PowerShell console you can do it with this command:
      New-NetFirewallRule -DisplayName 'SSH Inbound' -Profile @('Domain', 'Private', 'Public') -Direction Inbound -Action Allow -Protocol TCP ‑LocalPort 22

      Notice that this command doesn't work on PowerShell Core 6.0.

      Opening the SSH port in the Windows Firewall

      Opening the SSH port in the Windows Firewall

      This opens the SSH port for all three network profiles (Domain, Private, Public). Depending on your environment, you might want to open port 22 only for one of the profiles

    12. You now have to reboot the computer to ensure that the environment variable PATH is available systemwide

    Testing PowerShell remoting with SSH

    That's it. You just enabled PowerShell remoting for SSH. You can now test your connection on a PowerShell 6 console. Note that you have to install OpenSSH on the local and on the remote machine for this work. However, the sshd service only needs to run on the remote machine.

    Enter-PSsession -HostName <computer name>

    The HostName parameter ensures that PowerShell will use SSH as the transport protocol. PowerShell uses the user name used to log on to your local machine.

    If you are working with an Active Directory account, you have to pass the user name with the UserName parameter using this syntax: <user name>:<domain name>.

    Enter-PSsession -HostName <computer name> -UserName <user name>:<domain name>

    If you sign on the first time on the remote host, you have to acknowledge the key fingerprint by typing "yes." OpenSSH will store the fingerprint in the known_hosts file in the .ssh folder of your user profile. You then have to enter your password, and you are in.

  1. Of course, you can also work with Invoke-Command:
    Invoke-Command -HostName <computer name> -UserName <user name>:<domain name> -ScriptBlock {get-process}
    PowerShell remoting via SSH

    PowerShell remoting via SSH

    Enter-PSSession and Invoke-Command also offer the SSHTransport switch. If you omit the HostName parameter, you can use SSHTransport to tell PowerShell remoting to connect via SSH.

    Enter-PSsession <computer name> -UserName <user name>:<domain name> ‑SSHTransport

    The New-PSsession cmdlet supports SSH as well:

    $session = New-PSSession -HostName <computer name> -UserName <user name>
    Invoke-Command -Session $session -ScriptBlock {get-process}

    With the Get-PSSession cmdlet you can verify you are connected via SSH:

    Verifying the SSH connection with Get PSSession

    Verifying the SSH connection with Get PSSession

    Using the SSH client

    OpenSSH comes with a simple SSH client. At a command prompt, you can connect to your SSH host this way:

    ssh <user name>@<computer name>

    Or if you want to sign in with an Active Directory account:

    ssh <user name>:<domain name>@<computer name>

    This will launch cmd.exe instead of PowerShell. To switch to PowerShell, simply run pwsh.

    Using a SSH client for PowerShell remoting

    Using a SSH client for PowerShell remoting

    As mentioned above, this works with any SSH client such as PuTTY on Windows or vSSH on a Mac.

    You will have noticed that I always had to enter my password after I connected to the remote machine. This is not what we are used to with PowerShell remoting. In an Active Directory domain environment, you are usually already authenticated, and you therefore don't need to enter a password. This currently doesn't work with PowerShell remoting over SSH.

    Subscribe to 4sysops newsletter!

    However, you can use public key authentication to avoid entering passwords. This is particularly useful when automating remotely with Invoke-Command. I will show you in my next post how you can configure public key authentication.

avataravatar
13 Comments
  1. KAMALANATHAN DORAIRAJ 5 years ago

    Awesome!!!… Really Helpful. Deeply Appreciate your post.

  2. Nice write-up Michael! I’ll be saving that so I don’t need to figure out all the steps. Appreciate the work to document the process.

  3. Jonathan 5 years ago

    Good job 🙂

  4. Author
  5. Traiano 5 years ago

    Hi

    Thanks for the great article!  I’d like to run the Invoke-Command non-interactively for a script, but how can I provide the password non-interactively?

    I’ve tried this, but the command structure doesn’t seem to support it:

    1. set the password:

    $pw = convertto-securestring -AsPlainText -Force -String <somepassword>

    2. set the credential pair

    $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist “Administrator”,$pw

    3. Get a session

    “`

    PS windows-dns/scripts> $session = New-PSSession -HostName windns -Credential $cred

    New-PSSession : Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.

    “`

    Is there a way to obtain SSHTransport session without interactively providing the password?

     

    • @Traiano

      You are using parameters which belong to different parameter sets.

      When you use Get-Help or Get-Command -Syntax, there is a section named Syntax and where you can find all parameter belonging to the same parameter set. One line represent one parameter set.

      Get-Command -Name New-PSSession -Syntax

      With the SSHTransport parameter, you cannot use the Credential parameter. Only the UserName parameter can be used, and you will be asked for a password.

      In the context of a script, another way to login is by using the KeyFilePath parameter and a key file. But the SSH service on the remote server must be configured to accept key files without providing a username and a password. That’s a common configuration (provide either key file or username/password) because administrators are lazy. The risk is that someone can steal you key file…

      Finally, you can also start your process or scheduled task with credential which has already the permission to authenticate on the remote server. Then you don’t have to provide the username and password because it is implicit.

      Enter-PSSession -SSHTransport -HostName MyRemoteComputer
      avatar
  6. Gregoris Tsintaris 5 years ago

    Hi, awsome and clean install, but I cannot seem to get any elevation privileges, which is kind of the point here so as to do admin tasks silently… Do you get elevated priviliges? Is there a way to do that?

    Thank you!

    Gregory Tsintaris

    • Author

      Hmm, I somehow assumed you have the same privileges as with WinRM. I currently don’t have a test installation. Which command did you run that didn’t work and what was the error message?

      • Gregoris Tsintaris 5 years ago

        I have connected with a local admin account and with a domain admin account with the same results for the below commands:

        “Get-WUInstall –MicrosoftUpdate –AcceptAll -Install” and it produced:

        Get-WUInstall : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
        At line:1 char:1
        + Get-WUInstall -AcceptAll -Install
        + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : NotSpecified: (:) [Get-WindowsUpdate], UnauthorizedAccessException
        + FullyQualifiedErrorId : System.UnauthorizedAccessException,PSWindowsUpdate.GetWindowsUpdate

        This command is installed by “Install-Module PSWindowsUpdate” and when run from an elevated powershell prompt it installs windows updates. I used this command as a test as it only works from an elevated PS.

        Thank you!

        • Author

          Just to rule out that it isn’t another issue, can you stop services with stop-service? You can also check which account the sshd service uses to logon.

  7. Gregoris Tsintaris 5 years ago

    The sshd service uses local system account by default, the command stop-service works for spooler for example.

    Is there a way to verify if we have true elevated prompt?

    I tried another windows update vbs script which also requires elevated cmd and which runs fine using psexec and get an access denied error also…

    • Author

      I think you can’t stop a service without elevation. You can also try copying a file to “/program files/”. That also wouldn’t work without elevation.

  8. Gregoris Tsintaris 5 years ago

    I found out why: https://serverfault.com/questions/473991/run-remote-powershell-as-administrator

    The only way to run windows update or any similar action you can’t do it unless you use JEA feature… Back to reading! Thank you!

    avatar

Leave a reply

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account