Skip to content

Instantly share code, notes, and snippets.

@zoredache
Last active June 26, 2023 00:57
Show Gist options
  • Save zoredache/d3b2d9e6a21f4cab6b31c9930bbc78f0 to your computer and use it in GitHub Desktop.
Save zoredache/d3b2d9e6a21f4cab6b31c9930bbc78f0 to your computer and use it in GitHub Desktop.
Forward a Windows agent from Windows into WSL2.

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

  • Install the openssh client on windows, run some kind of agent on Windows and add your keys. Make sure you can see your keys on the Windows side by running ssh-add.exe -L
  • Setup your favorite WSL distro configure for WSL2.
  • In the WSL2 distro install OpenSSH. Possibly adjusting your /etc/ssh/sshd_config to have WSL2 listen on an alternate port. I run my WSL2 OpenSSH on 2200.
  • Configure your WSL2 environment to use systemd
  • Deploy the public key from your Windows agent into your WSL2 ~/.ssh/authorized_keys. Verify that you can ssh into your WSL2 environment without password prompts.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment