BlackReloaded/wsl2-ssh-pageant

"error fetching identities: communication with agent failed" with KeeAgent

BrainStone opened this issue · 12 comments

Describe the bug

I'm trying to use this with KeeAgent, which is a plugin for KeePass2, which in turn is essentially just a pageant, like putty-pageant, except that it loads SSH keys from your password database.

To Reproduce

Steps to reproduce the behavior:

  1. Setup KeeAgent
  2. Setup wsl2-ssh-pageant
  3. Run ssh-add -L
  4. Get error

Expected behavior

wsl2-ssh-pageant being able to communitcate with KeeAgent

Desktop (please complete the following information):

  • OS: Windows 10
  • WSL OS: Debian 10

Could you enable logging for wsl-ssh-pageant by adding --verbose?

For e.g. setsid nohup socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"$HOME/.ssh/wsl2-ssh-pageant.exe --verbose" &> /dev/null &.

After restarting wsl or killing the existing socat process you should find wsl2-gpg-ssh.log in your home directory with additional information.

Nope. No such file appeared.

The socket file gets created however and a process is running.
If I try to cat it I get this:

cat: /root/.ssh/agent.sock: No such device or address

And ls -l shows this:

srwxr-xr-x 1 root root 0 Feb  1 20:38 /root/.ssh/agent.sock

ps aux | grep socat:

root       643  0.0  0.0   6824  1960 ?        Ss   20:38   0:00 socat UNIX-LISTEN:/root/.ssh/agent.sock,fork EXEC:/root/.ssh/wsl2-ssh-pageant.exe --verbose

Everything looks good so far. Just a little question, any particular reason you're using the root user? It's not needed to run this with root privileges if your default user is another one.

From my standpoint it looks like your ssh agent is not connecting to the socket. Did you specify the right location for SSH_AUTH_SOCK? Maybe show the output of:

echo $SSH_AUTH_SOCK
whoami

Another option is to check if the socket is available by:

socat - UNIX-CONNECT:$HOME/.ssh/agent.sock
or similar commands.

Here you go:

root@BrainStone-wsl (~) # echo $SSH_AUTH_SOCK
/root/.ssh/agent.sock
root@BrainStone-wsl (~) # whoami
root
root@BrainStone-wsl (~) # socat - UNIX-CONNECT:$HOME/.ssh/agent.sock
root@BrainStone-wsl (~) #

And I know it doesn't have to be root. I just set it up to be root. That's not an issue, is it?

And I mean the agent works perfectly fine with PuTTY and FileZilla.

From your log, am I right to assume the socat command immediately returned? Normally it should block if it has established a connection to the socket.

No it shouldn't be an issue to run as root. I was only interested in it, to avoid that our documentation lacks the detail the agent/forwarder should run as the user who consumes it.

The connection between the windows pageant and the wsl one is never tried to establish. If it would be initiated the log file must appear.

My next debug trial would be to remove the automatic setup from the .bashrc or similiar and kill wsl to avoid having an old instance of the forwarder running. Afterwards I would run the socat manually to see if it outputs some sort of issue. Maybe the version of socat on your machine expect other flags or similar (we had that one before).

Remove the following from .bashrc or similiar:

export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
ss -a | grep -q $SSH_AUTH_SOCK
if [ $? -ne 0 ]; then
        rm -f $SSH_AUTH_SOCK
        (setsid nohup socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:$HOME/.ssh/wsl2-ssh-pageant.exe >/dev/null 2>&1 &)
fi

Launch two wsl terminals (same distribution) and hook up socat by yourself:

export SSH_AUTH_SOCK=$HOME/.ssh/agent.sock
socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:"$HOME/.ssh/wsl2-ssh-pageant.exe --verbose"

In another terminal try to export the SSH_AUTH_SOCK and use it with the ssh-add -L command.

During double checking if running as root should work I've gathered that I get a quiet similar result if the file /root/.ssh/wsl2-ssh-pageant.exe does not exist or is not executable. Can you double check that the file exists and is executable?

tobias@DESKTOP ~> $HOME/.ssh/wsl2-ssh-pageant.exe --help
Usage of wsl2-ssh-pageant.exe:
  -gpg string
        gpg mode
  -logfile string
        Path to logfile (default "wsl2-gpg-ssh.log")
  -ssh string
        windows ssh mode
  -verbose
        Enable verbose logging

Ok. This is very very odd.

The executable flag is set. But when I run the file with --help it just exits. No output, no error.

And the only message I got from the socat thing was

2021/02/03 20:12:44 socat[1567] E waitpid(): child 1568 exited with status 1

No clue what's going on. I'm using the 1.2 release.

Can you check, if it is possible to run a exe file from wsl for example notepad.exe?

By any chance your distribution has disabled windows interop?

tobias@DESKTOP-FSD244A ~> cat /proc/sys/fs/binfmt_misc/WSLInterop
enabled
interpreter /tools/init
flags: F
offset 0
magic 4d5a

https://docs.microsoft.com/de-de/windows/wsl/wsl-config#interop
https://docs.microsoft.com/en-us/windows/wsl/interop#disable-interoperability

Yeah. Looks like an issue with interop. I've managed to make the cat command you showed me print essentially the same info but that's about it.

I don't think this is an issue with your software so I'll close the issue.

The only question I have is why is this program a .exe file in the first place and not a native Linux binary?

Maybe try another distribution like Ubuntu and cross-use the socket. It's possible with cross-distro mounting. WSL does not isolate the linux network namespaces. Therefore the resource could be shared.

It must be an windows executable by design. Linux processes are unable to talk to windows processes in WSL2. Therefore the trick this utility leverages is a socket proxy (socat) which has the feature auf launching an program on connection attempts. This is what socat UNIX-LISTEN:$SSH_AUTH_SOCK,fork EXEC:$HOME/.ssh/wsl2-ssh-pageant.exe is doing. WSL has a so called windows interop mode, where executable files are launchable through binfmt on linux side. These executable are able to talk/communicate with windows processes (like the pageant window).

What the wsl2-ssh-pageant.exe is doing is:

  1. On launch identify the pageant window and find it's hw process to talk with the window. Putty and it's pageant established a standard which nearly all software copied to be compatible. Rendering a window off screen with a specific name and be able to talk over this line. I assume this has historical reasons as Windows did not have the right IPC between GUI and CLI.
  2. If it found the window it establishes a connection and forwards everything from the unix socket to the pageant in both directions (like a pipe).

The communication between WSL2(Linux) and Windows is done through the interop functionality which connects the stdin and stdout of the windows process inside of WSL2(Linux).

If you want to know more about this have a look at this talk I gave at WSL.Conf last year. Don't be afraid by the title it's kinda misleading. It mostly is about WSL2 Linux<>Windows interop and less about Go.
https://www.youtube.com/watch?v=WOLZ3sb3McA

Fun fact: The same technique is used by Docker for Windows with the WSL2 backend enabled.

I only have a single WSL instance. That being Debian 10. I did hover have that since WSL1 and migrated it to WSL2 so there's a good chance there's some configuration missing.

And thank you for the explanation. Only exe files being able to interact with the Windows processes definately justify it being an exe. Let's hope I'll eventually find a way to get the interop working.

Just a little update. So after I majorly messed up my WSL instance, I reinstalled it and now it's working flawlessly. Clearly I did something wrong on my end. Just adding this for future readers.

Your software is working great! Thanks for making it :D