Win32-OpenSSH icon indicating copy to clipboard operation
Win32-OpenSSH copied to clipboard

Export OpenSSH environment variables to bash.exe and wsl.exe

Open joes opened this issue 2 years ago • 2 comments

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.

joes avatar Sep 15 '22 12:09 joes

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?

joes avatar Sep 15 '22 12:09 joes

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.

mgkuhn avatar Sep 16 '22 10:09 mgkuhn

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.

joes avatar Sep 22 '22 19:09 joes