Home Setting up shared SSH key agent between Windows 11 and WSL2
Post
Cancel

Setting up shared SSH key agent between Windows 11 and WSL2

TLDR:

A guide on how to setup a shared ssh-agent and ssh keys between a Windows host machine and a linux WSL (Windows subsystem for linux) instance. Using socat, npiperelay and some bash scripting one can use the windows SSH agent inside the WSL container, automatically with no additional authentication.

Disclaimer:

This is heavily (entirely?) derived from blog-posts/instructions from the following sources:

pscheit.medium.com/use-an-ssh-agent-in-wsl-with-your-ssh-setup-in-windows-10

gist.github.com/WillianTomaz/

stuartleeks.com/posts/wsl-ssh-key-forward-to-windows/

More updated fork of original npiperelay:
github.com/albertony/npiperelay

How to update Windows’ OpenSSH client:
github.com/PowerShell/Win32-OpenSSH

Not used but potentially interesting:
Use the windows OpenSSH directly from linux

Background:

Recently, I acquired a new computer with a fresh installation of Windows. While setting up my development environment, I took the opportunity to reevaluate best practices and eliminate past workarounds.

My primary development workflow revolves around Linux, and my go-to tools consist of the following:

  • VSCode
  • WSL2 - Ubuntu LTS
  • Docker Desktop
  • SSH keys for github and remote servers

It’s that last topic that is the point of issue of this blog post. Namely in 2023 what is the current best practice methodology for setting up SSH keys on Windows?

On the one hand we have Windows with their build-in SSH agent, allowing one to generate and add keys once, then letting the Windows registry store them forevermore. This is nice because it puts the keys behind Microsoft’s user authentication barrier, allowing for technically password protected private keys, and only have to enter the password once, for all time.

This may not be the most secure, but for my personal github repositories, it is pretty convenient.

However, since I do most of my development in Linux, I need to mirror all of my GitHub/remote server keys to my WSL instance. The common and robust approach is to use keychain in Ubuntu and add the private keys on WSL startup. Although this requires entering the SSH private key password(s) at each startup, it’s manageable if you don’t restart the computer frequently.

But what if we could automate this process and have the Ubuntu WSL instance communicate with the Windows OpenSSH agent to obtain the keys automatically?

It turns out this is possible with some configuration.

How:

The Windows OpenSSH agent uses a named pipe in order to communicate with ssh.exe and provide authentication. What is needed is a way to allow our WSL instance to talk to that pipe. Luckily there is a cool project that does that:

npiperelay

This program takes a Windows named pipe and converts it to a unix socket that can be referenced from within WSL. Then one just needs to reference that socket and we should have all out Windows keys in our WSL instance.

Unfortunately, depending on the versions of OpenSSH in Windows on the host machine, and the version in the WSl container there can be incompatibilities. This ends up giving funky behavior where ssh-add -l correctly lists all the Windows SSH keys, but when testing with ssh -T [email protected] it just does not work.

After struggling with this for a couple hours I realized that the Windows ssh client was on version 8.6 while the Ubuntu was on 8.9. This is somehow a version mismatch, and can be fixed by updating the Windows client/agent to the newest (beta) version.

There is a concern is how reliable method will be going forward.

Step-by-Step Instructions:

On the Windows side:

  1. Install the beta version of OpenSSH via elevated powershell:
1
2
3
4
5
6
7
8
9
10
11
# Uninstall the OpenSSH Client/Server if currently installed (if previously installed):
Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Remove-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# Use winget to install the OpenSSH beta From microsoft:
winget install "openssh beta"

# Setup the OpenSSH service to auto start as normal.
Get-Service ssh-agent
Get-Service -Name ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
  1. If you have not added keys previously add them now via ssh-add, and confirm they are added with ssh-add -L You should see the keys that you are expect.

  2. Build and install npiperelay as described here:
    github.com/albertony/npiperelay
    For the rest of these instructions I placed the executable in: c:/Users/username/.ssh/bin/npiperelay.exe

On the WSL side (Ubuntu 22.04):

  1. Create a symbolic link to the npiperelay.exe on Windows:
    1
    2
    
    mkdir -p ~/.local/bin
    ln -s  /mnt/c/Users/username/.ssh/bin/npiperelay.exe ~/.local/bin/npiperelay.exe
    
  2. Install socat:
    1
    
    sudo apt-get -y install socat
    
  3. Add the following to your .bashrc. This adds the symbolic link to your path, along with a helper script to start the pipe-to-socket connection on startup (as per github.com/albertony/npiperelay):
    1
    2
    3
    4
    5
    6
    7
    
    PATH=$PATH:~/.local/bin
    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 socat UNIX-LISTEN:${SSH_AUTH_SOCK},fork EXEC:"npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork & ) >/dev/null 2>&1
    fi
    
  4. Confirm that your connection works with ssh-add -L and ssh -T [email protected]

A possible alternative:

One of the options I found when I started going down this path was not using the ssh.exe from wsl at all. Instead one could run the windows SSH executables directly from linux. I initially ran into issues with this, but that may have been caused by the SSH version incompatibility previously mentioned:
Use the Windows OpenSSH directly from linux

This post is licensed under CC BY 4.0 by the author.
Trending Tags
Contents

-

-

Trending Tags