Press "Enter" to skip to content

How to detect Powershell environment over SSH

I recently installed the SSH role on a Windows 2022 Server and had a need to conditionally load elements of my Powershell profile depending on if the Powershell session was native (On the server) or remote via SSH.

I explored options to get the current process ID and iterate up the chain until it found sshd.exe. Another option was to run something like Get-Process -Id $pid).SessionId -eq 0 where this results in for an interactive session (on the server) or 2 for a remote session. This could catch remote powershell also, not only sessions initiated via ssh.

I ended up exploring a third option which made the most sense for my use case. This was to add a environment variable if (and only if) the session is started via SSH. To do this, I’ll run a batch file to open Powershell, set the environment variable.

You can change the default shell via the registry or via the ForceCommand in the ssh_config file. Both options are explained below. Since I was already managing the ssh_config file via configuration management (Puppet Enterprise) I opted to use the ssh_config file method to set the default shell.

ssh_config method

The ssh_config file located in C:\programdata\ssh allows you to specify a start command via ForceCommand COMMAND_TO_RUN. By default ssh sessions will drop you into cmd.exe, so this needed to change to Powershell regardless. I

Registry method

If you prefer, this can also set this via the registry. Configuring the default ssh shell is done in the Windows registry by adding the full path to the shell executable to HKEY_LOCAL_MACHINE\SOFTWARE\OpenSSH in the string value DefaultShell.

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "COMMAND_TO_RUN" -PropertyType String -Force

If you want to simply start powershell.exe, you could enter the full path to the Powershell binary and you’d be done. In our case, I need to not only start powershell, but configure the environment. So instead of starting powershell.exe, I’m going to start a custom start_powershell.bat located in C:\programdata\ssh. You can put this batch script wherever you’d like.

start_powershell.bat

Below is the contents of the batch file. We first need to start powershell without loading a profile and not exiting after the command is ran. We will create an environment variable named ssh_session and set the value to true. Once that’s done, we’ll load our custom powershell profile, if it exists. If not, we catch and suppress the error. This is just to make it clean for users who may not have a powershell profile configured.

@echo off
powershell -NoExit -NoProfile -Command "$env:ssh_session='true'; try{. $PROFILE}catch{}"

Once you have the batch file, update either the registry key or the ssh_config file to point to it. Restart the sshd service make the changes take effect.

How that we have this, I simply modified my Powershell profile to conditionally load elements based on this variable. For example, prompt for elevated credentials via get-credential only if it’s an interactive session. If session is via ssh don’t prompt, but add a function to set elevated credentials which prompts in the console.

Summary

It’s now super handy to have Powershell at my disposal from any where with ssh. Next up will be configuring vscode for remote powershell development. I hope this article is useful for the next person trying to solve this or simiar issues. Enjoy!

Sharing is caring!

Leave a Reply

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

thirteen − twelve =