Home

Awesome

wsl2-ssh-agent

This tool allows from WSL2 to use the ssh-agent service on Windows host.

How to use

1. Install wsl2-ssh-agent

Put wsl2-ssh-agent binary in your favorite directory in WSL2, for example, $HOME/.

curl -L -O https://github.com/mame/wsl2-ssh-agent/releases/latest/download/wsl2-ssh-agent

If you are under ARM64 architecture, download the arm64 binary instead:

curl -L -O https://github.com/mame/wsl2-ssh-agent/releases/latest/download/wsl2-ssh-agent-arm64

Change permisions so the binary is executable:

chmod 755 wsl2-ssh-agent

If you are using ArchLinux, you can install the wsl2-ssh-agent package from the AUR (maintained by @Hill-98).

2. Modify your shell's rc file

bash or zsh

Add the following line to .bashrc (or .zshrc if you are using zsh).

eval $($HOME/wsl2-ssh-agent)

fish

Add the following lines to config.fish

if status is-login
  $HOME/wsl2-ssh-agent | source
end

3. Reopen your terminal

Close and reopen the terminal and execute ssh your-machine. The command should communicate with ssh-agent.exe service.

Tip: For pageant.exe

If you want to use with the named pipe provided by pageant.exe, you can use the -pipename option. You can configure wsl2-ssh-agent as follows:

eval $($HOME/wsl2-ssh-agent -pipename $(grep -oP "IdentityAgent \"//\./pipe/\K[^\"]+" /mnt/c/.../pageant.conf))

(The author does not use pageant.exe. Let me know if it does not work.)

Troubleshooting

Make sure that ssh-agent.exe is working properly

Check the log of ssh

debug1: get_agent_identities: bound agent to hostkey
debug1: get_agent_identities: agent returned XXX keys

Check the log of wsl2-ssh-agent

# Stop the existing server if any
$ $HOME/wsl2-ssh-agent -stop

# Run in foreground mode
$ $HOME/wsl2-ssh-agent --verbose --foreground
[L] 2023/02/10 20:30:00 check the version of ssh.exe
[L] 2023/02/10 20:30:01 the version of ssh.exe: "OpenSSH_for_Windows_8.6p1, LibreSSL 3.4.3"
[L] 2023/02/10 20:30:01 ssh-agent.exe seems to be old; ignore OpenSSH extension messages
[L] 2023/02/10 20:30:01 start listening on /home/mame/.ssh/wsl2-ssh-agent.sock
[L] 2023/02/10 20:30:01 invoking [W] in PowerShell.exe
[W] 2023/02/10 21:51:09 ready: PSVersion 5.1.22621.963
[L] 2023/02/10 20:30:02 [W] invoked successfully
[L] 2023/02/10 20:30:05 ssh: connected
[L] 2023/02/10 20:30:05 ssh -> [L] (XXX B)
[L] 2023/02/10 20:30:05 ssh <- [L] (5 B) <dummy for OpenSSH ext.>
[L] 2023/02/10 20:30:05 ssh -> [L] (5 B)
[L] 2023/02/10 20:30:05 [L] -> [W] (5 B)
[W] 2023/02/10 21:51:12 [L] -> [W] -> ssh-agent.exe (5 B)
[W] 2023/02/10 21:51:12 [L] <- [W] <- ssh-agent.exe (XXX B)
[L] 2023/02/10 20:30:05 [L] <- [W] (XXX B)
[L] 2023/02/10 20:30:05 ssh <- [L] (XXX B)
[L] 2023/02/10 20:30:05 ssh -> [L] (XXX B)
[L] 2023/02/10 20:30:05 [L] -> [W] (XXX B)
[W] 2023/02/10 21:51:12 [L] -> [W] -> ssh-agent.exe (XXX B)
[W] 2023/02/10 21:51:12 [L] <- [W] <- ssh-agent.exe (XXX B)
[L] 2023/02/10 20:30:05 [L] <- [W] (XXX B)
[L] 2023/02/10 20:30:05 ssh <- [L] (XXX B)
[L] 2023/02/10 20:30:05 ssh: closed

How wsl2-ssh-agent works

Linux ssh client connects to ssh-agent via a UNIX domain socket, while ssh-agent.exe service on Windows is listening on a named pipe. This command connects those two in the following mechanism.

graph TB
subgraph WSL2
  A(ssh) <-->|UNIX domain socket| B("wsl2-ssh-agent")
end
subgraph Windows
  B <-->|stdin/stdout| C("PowerShell.exe")
  C <-->|named pipe| D(ssh-agent.exe)
end

Note

Usually, ssh and ssh-agent should be the same version. However, OpenSSH on Ubuntu 22.04 is 8.9, while Windows bundles OpenSSH 8.6 (on my machine, as of this writing).

OpenSSH has extended the ssh-agent protocol since 8.9. However, ssh-agent.exe does not understand the extended message and will not communicate properly. (Japanese article)

To address this issue, wsl2-ssh-agent does not pass the extended message to ssh-agent.exe. Instead, it swallows the message and reply a dummy SSH_AGENT_SUCCESS message to ssh client. Note that this may reduce the security strength. Please use this tool at your own risk.