Open AngellusMortis opened 4 years ago
Thanks for the issue @AngellusMortis , I am aware of this limitation. There is a workaround currently which works with npiperelay
and the Windows SSH support. It's possible to bridge Pageant to Windows SSH and then use npiperelay
to bridge that into WSL 2. If there is interest this could possibly be added in the tool itself, what do you think?
@benpye How do I run npiperelay correctly?
I have tried this
joel@JOEL-XPS15:/mnt/c/Users/Joel$ socat UNIX-LISTEN:/home/joel/.ssh/authsock,fork,group=joel,umask=007 EXEC:"npiperelay.exe -ep -s //./pipe/ssh-pageant",nofork
/usr/local/bin/npiperelay.exe: Invalid argument
But whenever I try to use the agent I get a /usr/local/bin/npiperelay.exe: Invalid argument
error.
I have this: export SSH_AUTH_SOCK=/home/joel/.ssh/authsock
as well
What's the magic syntax?
Woops! I totally forgot about this thread. I use the following command line - I guess you need to pass the full path to npiperelay.exe.
socat EXEC:"/mnt/c/Users/benpy/go/bin/npiperelay.exe /\/\./\pipe/\ssh" UNIX-LISTEN:/tmp/wsl-ssh-pageant.socket,unlink-close,unlink-early,fork
Ahh awesome thanks. I think it turned out "Invalid argument" was because I was trying to run windows binaries from a windows working directory. You can see I was using /mnt/c/Users. When I changed to the Linux home directory it worked fine.
Out of interest how do you start socat? I tried to get systemd to run it for me, but it just keeps crashing.
I have:
[Service]
User=joel
Type=Simple
ExecStart=/usr/bin/socat -u EXEC:"/mnt/c/Users/Joel/go/bin/npiperelay.exe //./pipe/ssh-pageant" UNIX-LISTEN:/tmp/wsl-ssh-pageant.socket,unlink-close,unlink-early,fork
But it dies with:
Apr 11 23:03:23 JOEL-XPS15 systemd[1]: Started ssh-agent-socat.service.
Apr 11 23:03:23 JOEL-XPS15 socat[3045]: 2020/04/11 23:03:23 socat[3045] E waitpid(): child 3046 exited with status 1
Apr 11 23:03:23 JOEL-XPS15 systemd[1]: ssh-agent-socat.service: Main process exited, code=exited, status=1/FAILURE
Apr 11 23:03:23 JOEL-XPS15 systemd[1]: ssh-agent-socat.service: Failed with result 'exit-code'.
I've added this to my ~/.bashrc
if [ ! -S /tmp/wsl-ssh-pageant.socket ] && [ -z "$TMUX" ]; then
echo "Starting socat relay to ssh-pageant"
tmux new-session -d -s socat-ssh-agent
tmux send-keys '/usr/bin/socat EXEC:"/mnt/c/Users/Joel/go/bin/npiperelay.exe //./pipe/ssh-pageant" UNIX-LISTEN:/tmp/wsl-ssh-pageant.socket,unlink-close,unlink-early,fork' C-m
fi
export SSH_AUTH_SOCK=/tmp/wsl-ssh-pageant.socket
Using tmux seems a bit blah, but it gets the job done. Simply backgrounding the socat command in the ~/.bashrc
with &
was making VSCode hang when starting up inside WSL 2
Adding this to ~/.bashrc
kill -9 $(ps x | grep npiperelay | grep -v grep | awk '{ print $1 }')
setsid nohup socat EXEC:"/mnt/c/work/ssh/npiperelay/npiperelay.exe /\/\./\pipe/\ssh-pageant" UNIX-LISTEN:/tmp/wsl2-ssh-agent.sock,unlink-close,unlink-early,fork >/dev/null 2>&1 &
export SSH_AUTH_SOCK=/tmp/wsl2-ssh-agent.sock
seems to work for me, both in Windows Terminal and VSCode
I struggeled much to get this working. I found out that my pipe, that needs to be passed to npiperelay, had a different name.
You can use this powershell command to check which pipes with "ssh" in name exist on your system.
[System.IO.Directory]::GetFiles("\\.\\pipe\\") | Select-String -Pattern ssh
for me it was \\.\\pipe\\openssh-ssh-agent
WSL v2 is public builds now (may update, ver 2004). Is this limitation still a factor? Since updating to WSLv2 I'm just getting public key permission denied to my servers (i.e. it isn't working!)
The only two issues I have with https://github.com/benpye/wsl-ssh-pageant/issues/33#issuecomment-640935516 are that:
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
To solve issue 2, I am using this:
EXISTING_RELAY_PIDS=$(ps x | grep npiperelay | grep -v grep | awk '{ print $1 }')
if [[ ! -z "${EXISTING_RELAY_PIDS}" ]]; then
kill -9 ${EXISTING_RELAY_PIDS}
fi
setsid nohup socat \
EXEC:"/mnt/c/Users/MY_USERNAME/bin/npiperelay.exe /\/\./\pipe/\ssh-pageant" \
UNIX-LISTEN:/tmp/wsl2-ssh-agent.sock,unlink-close,unlink-early,fork >/dev/null 2>&1 &
export SSH_AUTH_SOCK=/tmp/wsl2-ssh-agent.sock
This variant of https://github.com/benpye/wsl-ssh-pageant/issues/33#issuecomment-640935516 worked better for me, and avoids the hang-at-close:
EXISTING_RELAY_PIDS=$(ps x | grep npiperelay | grep -v grep | awk '{ print $1 }')
if [[ -z "${EXISTING_RELAY_PIDS}" ]]; then
socat \
EXEC:"/mnt/c/Users/MY_USERNAME/bin/npiperelay.exe /\/\./\pipe/\ssh-pageant" \
UNIX-LISTEN:/tmp/wsl2-ssh-agent.sock,unlink-close,unlink-early,fork >/dev/null 2>&1 &
fi
export SSH_AUTH_SOCK=/tmp/wsl2-ssh-agent.sock
@GuyPaddock I'm using your variant, but when I try to ssh to somewhere within WSL, socat exits:
voltagex@Argentum:/mnt/c/Users/Adam$ ssh 10.1.1.2
voltagex@10.1.1.2: Permission denied (publickey).
[1]+ Exit 1 socat EXEC:"/mnt/c/Users/Adam/OneDrive/bin/npiperelay.exe /\/\./\pipe/\ssh-pageant" UNIX-LISTEN:/tmp/wsl2-ssh-agent.sock,unlink-close,unlink-early,fork > /dev/null 2>&1
@voltagex Yeah, I'm seeing that too... not sure why socat isn't staying open.
I just noticed @ BlackReloaded has sort of forked/borrowed some code from @benpye's project specifically for WSL2 (using socat): https://github.com/BlackReloaded/wsl2-ssh-pageant. That setup works for me. Just note that the docs say $HOME/.ssh/
than just the home directory (took me a couple of reads to pick up on that).
Mind you I'm using it with https://smartcard-auth.de/index-en.html for pageant in order to support my Yubikey.
I just noticed @ BlackReloaded has sort of forked/borrowed some code from @benpye's project specifically for WSL2 (using socat): https://github.com/BlackReloaded/wsl2-ssh-pageant. That setup works for me. Just note that the docs say
$HOME/.ssh/
than just the home directory (took me a couple of reads to pick up on that).Mind you I'm using it with https://smartcard-auth.de/index-en.html for pageant in order to support my Yubikey.
I got wsl2-ssh-pageant working, However, not sure why in wsl2, I cannot make this work in my .zshrc. The socat process is running and the sock file is created, I can see it in ss -a, but ssh-add -l hang, I have to kill socat process and resource .zshrc, then it start working again. This behavior is same for weasel-pageant, I cannot eval and start weasel-pageant.exe in my .zshrc in wsl2, I have to run the eval outside my .zshrc or kill the socat process and re-source my .zshrc once my terminal started. WSL1 do not have this issu. Anyone have this issue in WSL2?
Thanks
I just noticed @ BlackReloaded has sort of forked/borrowed some code from @benpye's project specifically for WSL2 (using socat): https://github.com/BlackReloaded/wsl2-ssh-pageant. That setup works for me. Just note that the docs say
$HOME/.ssh/
than just the home directory (took me a couple of reads to pick up on that). Mind you I'm using it with https://smartcard-auth.de/index-en.html for pageant in order to support my Yubikey.I got wsl2-ssh-pageant working, However, not sure why in wsl2, I cannot make this work in my .zshrc. The socat process is running and the sock file is created, I can see it in ss -a, but ssh-add -l hang, I have to kill socat process and resource .zshrc, then it start working again. This behavior is same for weasel-pageant, I cannot eval and start weasel-pageant.exe in my .zshrc in wsl2, I have to run the eval outside my .zshrc or kill the socat process and re-source my .zshrc once my terminal started. WSL1 do not have this issu. Anyone have this issue in WSL2?
Thanks
Well I didn't have any issues on Ubuntu 18.04, I do see something similar on Ubuntu 20.04. But in my case socat wasn't running and ssh-add -l gave me 'file not found'. I discovered that when I run the socat command in the terminal, it works just fine, but it wasn't doing it when I ran it via my .zshrc. My workaround / fix was to remove the if statement so it will always execute.
Just sharing what worked for me - I was new to Windows named pipes, and it's not obvious in the above comments that you need to tell wsl-ssh-pageant to set up the named pipe:
I installed https://github.com/rupor-github/wsl-ssh-agent first because it includes a pre-built npiperelay.exe - I didn't want to have to create a Go build environment.
# in windows, set up a named pipe called ssh-pageant - NOTE: install it in a path with no spaces, it makes the socat command simpler:
"c:\wsl-ssh-agent\wsl-ssh-pageant-386.exe" --winssh ssh-pageant
# then from wsl, use socat to connect it to a socket file:
socat EXEC:"/mnt/c/wsl-ssh-agent/npiperelay.exe -ei -s //./pipe/ssh-pageant" UNIX-LISTEN:/tmp/wsl-ssh-pageant.socket,unlink-close,unlink-early,fork
# then tell ssh to use that socket
export SSH_AUTH_SOCK=/tmp/wsl-ssh-pageant.socket
I'll try and have a dig into why this isn't working well. I've generally not had too much trouble with npiperelay
and socat
though it would be nice to avoid needing the npiperelay
binary at the very least.
@ckuai I'm experiencing the same issue.
@ckuai I'm experiencing the same issue. Since the Nov win10 monthly update or after 20H2 feature update, the issue seems gone for me.
Hi,
Are there any plans to incorporate WSL2 support into wsl-ssh-pageant? I'd rather not have to fumble with multiple utilities.
@ckuai Not sure why that would be true, unless you switched to WSL 1.
WSL 2 still has no support for AF_UNIX
-based socket communication with Windows programs. (See https://github.com/microsoft/WSL/issues/4240)
seems like that thread is alive https://github.com/microsoft/WSL/issues/4240 perhaps they'll close this issue in nearest future ๐ถโโ๏ธ
but for now wsl.exe --set-version Ubuntu 1
๐
Wow, this was not easy. Added the steps here as a Gist, works without tmux, in different WSL2 windows, no issues or errors on start or logout. Tested with Pageant running on the Windows side.
Originally missed to set permissions and ownership of files, which meant that the pipe relay did not work when sourced in bashrc.
For those that have issues using npiperelay due to false positives from antivirus software... if you are using pageant, you'll likely have the full PuTTY suite installed that includes plink.exe
. You can use that to connect to pipes as well. My solution doesn't use wsl-ssh-pageant, and doesn't need npiperelay. I run below command as a systemd service in WSL, and export the corresponding socket path via .bashrc:
socat UNIX-LISTEN:/home/username/.ssh/pageant.sock,unlink-early,fork "EXEC:'"'"'"/mnt/c/Program Files/PuTTY/plink.exe"'"'" -serial //
./pipe/pageant.YOURUSERNAME.SOMERVALUE'"
In case you need to look up the pipe name for pageant, you can run this in powershell:
Get-ChildItem \\.\pipe\ | ?{ $_ -like "*pageant*" } | %{ $_.name }
My systemd unit file:
[Unit]
Description=SSH Pageant Forwarder
[Service]
Type=simple
User=fholzer
ExecStart=/usr/bin/socat UNIX-LISTEN:/home/wls-username/.ssh/pageant.sock,unlink-early,fork "EXEC:'"'"'"/mnt/c/Program Files/PuTTY/plink.exe"'"'" -serial //./pipe/pageant.windows-username.random-data'"
[Install]
WantedBy=default.target
Turns out the random string is different on every reboot, at least for me, so have to figure out a way to automate this yet.
@fholzer Just an idea: run the power-shell command in a startup task on logon and write output to a file. Read that file as part of the ExecStart
You can just run the PowerShell command from within WSL2
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command 'Get-ChildItem \\.\pipe\ | ?{ $_ -like "*pageant*" } | %{ $_.name }'
An alternative to the PowerShell command is to get pageant itself to write an OpenSSH configuration file, which you could parse the data from.
You would need to start pageant like this:
"C:\Program Files\PuTTY\pageant.exe" --openssh-config %USERPROFILE%\pageant.conf
Then %USERPROFILE%\pageant.conf
has:
IdentityAgent \\.\pipe\pageant.pearj.2d30b9f59dc36f3f89423fe713164d35f9efb8b13fbe40022158982e0fa27d79
From WSL you can grab that with cut -d' ' -f2 /mnt/c/Users/pearj/pageant.conf | tr '\\' '/'
which switches the slashes around.
Mixing @fholzer and @pearj solutions:
#!/usr/bin/bash
plink="/c/Program\\\\ Files/PuTTY/plink.exe"
IdentityAgent=$(<pageant.conf)
IdentityAgent=${IdentityAgent:0:-1} # removes \r
IdentityAgent=${IdentityAgent##IdentityAgent } # cut it out
IdentityAgent=${IdentityAgent//\\/\/} # flips slashes
/usr/bin/socat \
UNIX-LISTEN:/tmp/pageant.sock,unlink-early,fork \
"EXEC:${plink} -serial ${IdentityAgent}"
Do any of y'all have a step-by-step instruction manual on how to accomplish this?
I've been at this for about a month now, and I still can't get OpenGPG to work in my instance of WSL2, and I've tried just about everything, including all the examples here, and none of them worked.
I'm hoping I just overlooked something, but so far I'm able to get this to work.
I roo have dealt with it for several days. My simple solution was to set my instance back to WSL1 ๐คฎ๐๐ฉVon meinem iPhone gesendetAm 11/05/23 um 21:30 schrieb Kerick Howlett @.***>:๏ปฟ Do any of y'all have a step-by-step instruction manual on how to accomplish this? I've been at this for about a month now, and I still can't get OpenGPG to work in my instance of WSL2, and I've tried just about everything, including all the examples here, and none of them worked. I'm hoping I just overlooked something, but so far I'm able to get this to work. Please help!
โReply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: @.***>
Since people still seem to be having problems with this, I thought I would post my solution for getting a pretty reliable agent into WSL2.
I have found the npipe+socat options pretty unstable, and frustrating.
My solution for getting an agent into WSL uses a combination of WSL2 systemd support, OpenSSH server installed in WSL2, and using OpenSSH client in Windows.
Prepare the environment
ssh-add.exe -L
That is all the prep work done. Now how do I actually forward the agent. It is pretty simple. I add a new systemd unit and enable it. This unit will use the WSL interop to run the windows ssh.exe client to the WSL2 environment. It enables agent forwarding, and will leave an symlink to the agent socket in ~/.ssh/agent
. Systemd will keep this ssh session open.
/etc/systemd/system/ssh_agent.service
[Unit]
Description=SSH Agent
After=ssh.service
ConditionPathExists=/mnt/c/Windows/System32/OpenSSH/ssh.exe
[Service]
ExecStart=/mnt/c/Windows/System32/OpenSSH/ssh.exe \
wsl_username@localhost -p 2200 -A -t -t bash -c \
': ; ln -sf "$SSH_AUTH_SOCK" ~/.ssh/agent ; exec sleep 1d'
KillMode=process
Restart=on-failure
Type=simple
[Install]
WantedBy=multi-user.target
With that done, all you have to do is update your shell profile to set the SSH_AUTH_SOCK
variable. I have something like this in my bash profile.
if [ -L ~/.ssh/agent -a -z ${SSH_AUTH_SOCK+x} ]; then
# wait a bit for systemd to start sshd and ssh_agent units.
wait_tries=20
until test $((wait_tries--)) -eq 0 -o -S ~/.ssh/agent ; do sleep 0.5; done
unset wait_seconds
# set our socket
export SSH_AUTH_SOCK=~/.ssh/agent
fi
I like this solution since it doesn't require any fancy magic to forward. It simply uses the ssh client and ssh daemon to forward exactly the way ssh agents are normally forwarded. We just are using the WSL2 systemd and interop to get this to happen in the background.
@zoredache Stupid question, but this also works with OpenPGP, right?
@zoredache Stupid question, but this also works with OpenPGP, right?
Sorry, don't know. Haven't tried. I haven't ever really needed to use PGP in my WSL2 environment.
my workaround ๐
> cat ~/bin/ssh
#!/bin/sh
exec '/mnt/c/Windows/System32/OpenSSH/ssh.exe' "$@"
~/bin
is on PATH
via ~/.bashrc
Where were you when I needed you over a year ago! ๐
Sadly, I can no longer try implementing this, because this problem got so frustrating, I switched over to Linux.
my workaround ๐
> cat ~/bin/ssh #!/bin/sh exec '/mnt/c/Windows/System32/OpenSSH/ssh.exe' "$@"
~/bin
is onPATH
via~/.bashrc
I struggle like 20h on this... I even found someone that did similar for the gpg.exe to get access to the smartcard and that worked... but I didnt think in ssh it self...
Thanks you mentioned this, Funny how it works...
my workaround ๐
> cat ~/bin/ssh #!/bin/sh exec '/mnt/c/Windows/System32/OpenSSH/ssh.exe' "$@"
~/bin
is onPATH
via~/.bashrc
I struggle like 20h on this... I even found someone that did similar for the gpg.exe to get access to the smartcard and that worked... but I didnt think in ssh it self...
Thanks you mentioned this, Funny how it works...
I'm also doing that for gpg ๐
my workaround ๐
> cat ~/bin/ssh #!/bin/sh exec '/mnt/c/Windows/System32/OpenSSH/ssh.exe' "$@"
~/bin
is onPATH
via~/.bashrc
This works for standard ssh connections, but it does not work for git
on my side, e.g. git push
> nothing happens, no error, just a prompt that never ends.
I tried specifying the GIT_SSH directly:
export GIT_SSH='/mnt/c/Windows/System32/OpenSSH/ssh.exe'
without success.
my workaround ๐
> cat ~/bin/ssh #!/bin/sh exec '/mnt/c/Windows/System32/OpenSSH/ssh.exe' "$@"
~/bin
is onPATH
via~/.bashrc
This works for standard ssh connections, but it does not work for
git
on my side, e.g.git push
> nothing happens, no error, just a prompt that never ends.I tried specifying the GIT_SSH directly:
export GIT_SSH='/mnt/c/Windows/System32/OpenSSH/ssh.exe'
without success.
GIT_SSH
didn't work for me too, that's why I created the simple shell wrapper which is working fine for me.
Strange, even with the SSH wrapper it is not working with git (but with ssh ...
directly, it works)
Indeed weird, it works normal here too, just a remind that using the windows openssh you might need to use the windows .ssh dir as well, so I just linked to mine /home/fabricio/.ssh -> /mnt/c/Users/fabricio/.ssh
Im also not using a wrapper but instead I linked the ssh.exe to /usr/local/bin/ssh (same for the others)
Ok, thanks - I could not get this to work under WSL2. I reverted to splitting my work: (1) Coding in WSL2 and (2) git commit/pull in WSL1.
.. finally was able to set this up with the latest Windows 10 and WSL2 following @zoredache steps. Minor changes on my side were necessary. I added it step by step here.
One more workaround
export GIT_SSH=/mnt/c/Program\ Files/Putty/plink.exe
works on wsl2 ubuntu.
According to a similar project, https://github.com/rupor-github/wsl-ssh-agent/issues/3, it seems this is not possible yet, but I just wanted to make an issue to cover it for anyone else was doing some digging.
It seems that the Windows/Unix socket interoperability does not work yet for WSL 2.