Win32-OpenSSH
Win32-OpenSSH copied to clipboard
Export OpenSSH environment variables to bash.exe and wsl.exe
Summary of the new feature / enhancement
As a user, upon a successful connection, I would like to see that (at minimum) these OpenSSH environment variables are set when the default shell is set to bash.exe
or wsl.exe
(not an exhaustive list of all possible environment variables set by OpenSSH):
- SSH_CLIENT
- SSH_CONNECTION
- SSH_TTY
- SSH_ORIGINAL_COMMAND
If the default shell for ssh is not set (cmd.exe
is used as the shell) then I can see that this happens as (I) expected:
$ ssh host
user@HOST C:\Users\user>set
...
SSH_CLIENT='192.168.223.17 36673 22'
SSH_CONNECTION='192.168.223.17 36673 192.168.223.229 22'
SSH_TTY=windows-pty
...
However, if the default shell is changed to bash.exe
or wsl.exe
like so:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\wsl.exe" -PropertyType String -Force
Then none of the above-mentioned environment variables are set in the shell:
$ ssh host
$ echo $SHELL
/bin/bash
env | grep -E "(SSH_CLIENT|SSH_CONNECTION|SSH_TTY)" || echo "SSH environment not set"
SSH environment not set
Proposed technical implementation details (optional)
What I would like to happen is for the environment to contain the expected variables if the default shell is wsl.exe
or bash.exe
:
$ ssh host
$ echo $SHELL
/bin/bash
env | grep -E "(SSH_CLIENT|SSH_CONNECTION|SSH_TTY)" || echo "SSH environment not set"
SSH_CLIENT=Client socket info
SSH_CONNECTION=Client and server socket info
SSH_TTY=Name of allocated TTY
$
Also, as an user I would like to see that $SSH_ORIGINAL_COMMAND
is set when ssh is started with a forced command.
Found a reasonable workaround/solution.
Open C:\ProgramData\ssh\sshd_config
and add this line:
SetEnv WSLENV=SSH_CLIENT/u:SSH_CONNECTION/u:SSH_TTY/u:SSH_ORIGINAL_COMMAND/u
Restart sshd.
Now when connecting the variables are set:
$ ssh host
$ echo $SHELL
/bin/bash
$ env | grep -E "(SSH_CLIENT|SSH_CONNECTION|SSH_TTY)" || echo "SSH environment not set"
SSH_CONNECTION=192.168.0.94 50834 192.168.0.56 22
SSH_CLIENT=192.168.0.94 50834 22
WSLENV=SSH_CLIENT/u:SSH_CONNECTION/u:SSH_TTY/u:SSH_ORIGINAL_COMMAND/u
SSH_TTY=windows-pty
I wonder if the value for SSH_TTY is correct - but the other values seem to be as expected.
Maybe this fix could be added in the OpenSSH configuration for windows?
WSL treats Linux environment variables separately from Win32 environment variables, for good reasons: most environment variables from one world mean nothing, or something else, in the other. Therefore if you want an environment variable from a Win32 application, such as OpenSSH for Windows, to be translated into a Linux environment variable, you'll have to do this yourself, as you have done already, via WSLENV.
This is really more a WSL design decision, and not an OpenSSH issue. You could raise an issue with the WSL developers to argue that passing on at least SSH_CONNECTION
and/or SSH_CLIENT
by default would generally be useful, and should not require having to set WSLENV.
I don't think anything needs fixing here in OpenSSH for Windows, and note that if it added by default your line to set WSLENV
, then that might override an already pre-existing WSLENV setting that some WSL users might have made elsewhere, i.e. it could cause unexpected malfunctions for them.
Passing on SSH_TTY
doesn't seem useful, because Win32's PTYs are very different from POSIX PTYs and I don't see what useful path could be passed on or translated here. (WSL2 presumably will be using its own Linux PTY anyway to communicate with bash.)
More interesting is the question of how SSH_AUTH_SOCK
could be gotten across the Win32/POSIX boundary, such that ssh -A
could work ... but I guess at some point it probably makes more sense to run sshd inside WSL.
Yes, as you say this implementation provides the correct environment at the win32 level - no argument from me there. The environment of win32 is not the environment of the WSL - these environments reside in separate universes with WSLENV acting as a gateway between these.
Nonetheless, in this case they do share the same reality of being accessed through a remote shell and if the WSL team accepts this reality it could perhaps convince them that at least this part of the environment is shared and should not require having to set a rule in WSLENV.