WSL2からWin32-OpenSSHのssh-agentを利用する
Windows側のssh-agent事情は混乱を極めていた。
私は現在Windows HelloやFIDO2へのセキュリティ的な対応が進んでいるPowershell/Win32-OpenSSH実装を用いてる。
公式など種々で紹介されている手順とは異なりsocatを利用しない方法を提示する。
npiperelayの導入
現在メンテナンスされているalbertony/npiperelayのv1.9.2をWSL2環境上のgoから以下のようにビルドする。
GOOS=windows GOAMD64=v3 go install -trimpath -buildmode pie github.com/albertony/npiperelay@v1.9.2
私の環境におけるビルド成果物は以下の通り
$ file ~/go/bin/windows_amd64/npiperelay.exe
/home/hiroaki-m/go/bin/windows_amd64/npiperelay.exe: PE32+ executable (console) x86-64, for MS Windows, 16 sections
$ go version -m ~/go/bin/windows_amd64/npiperelay.exe
~/go/bin/windows_amd64/npiperelay.exe: go1.25.6
path github.com/albertony/npiperelay
mod github.com/albertony/npiperelay v1.9.2 h1:C5zVHDYw9KUPs1eM0ydP+rLG1MYllzYDLqV+xLjOVYk=
dep golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
build -buildmode=pie
build -compiler=gc
build -trimpath=true
build DefaultGODEBUG=containermaxprocs=0,decoratemappings=0,tlssha1=1,updatemaxprocs=0,x509sha256skid=0
build CGO_ENABLED=0
build GOARCH=amd64
build GOOS=windows
build GOAMD64=v3
$ sha256sum ~/go/bin/windows_amd64/npiperelay.exe
e7fc0d70e6c2767a079ed7452cb129637d359a70afd0b3a03b12cecf0872b729 ~/go/bin/windows_amd64/npiperelay.exe
user-wide systemdの設定
albertony/npiperelayの公式手順とは異なりsocatの代わりにsystemdが持つsocket activationを用いる方法を採用した。
~/.config/systemd/user/wsl-ssh-agent.socket を用意する。
このファイルはGnuPGのgpg-agent-ssh.socketを参考に作成した。
[Unit]
[Socket]
ListenStream=%t/wsl-ssh-agent.sock
# See the below link for why we need GSM_SKIP_SSH_AGENT_WORKAROUND:
# https://git.gnome.org/browse/gnome-session/tree/gnome-session/main.c?h=3.24.0#n419
# in order to avoid race condition this environment should be set before SSH_AUTH_SOCK
ExecStartPre=systemctl --user set-environment GSM_SKIP_SSH_AGENT_WORKAROUND="true"
# after creating and binding the service notify environment
# no need to test config file because service directly pass fd overwritting the config file
ExecStartPost=systemctl --user set-environment SSH_AUTH_SOCK="%t/wsl-ssh-agent.sock"
# before unbinding stop to export that we listen to socket
ExecStopPre=systemctl --user unset-environment SSH_AUTH_SOCK
ExecStopPost=systemctl --user unset-environment GSM_SKIP_SSH_AGENT_WORKAROUND
SocketMode=0600
DirectoryMode=0700
Accept=true
[Install]
WantedBy=sockets.target
次にwsl-ssh-agent.socketが呼び出すtemplate serviceを用意する。
このserviceはソケットへのアクセスのたびに呼び出される。
~/.config/systemd/user/wsl-ssh-agent@.service に以下のファイルを配置
[Unit]
Description=Windows SSH Agent Proxy via npiperelay
[Service]
Type=oneshot
ExecStart=/home/%u/go/bin/windows_amd64/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent
StandardInput = socket
StandardOutput = socket
StandardError = journal
設定ファイルを作成後有効化する
systemctl --user daemon-reload
systemctl --user enable --now wsl-ssh-agent.socket
環境変数の設定
sshが有効化したソケットを参照するようにするためにSSH_AUTH_SOCK環境変数を~/.bashrcなどに設定する。
export SSH_AUTH_SOCK=/run/user/$UID/wsl-ssh-agent.sock
動作確認
適切に設定できると以下のようにWSL2上からWin32-OpenSSHのssh-agentにアクセスできる
$ ssh-add -l
2048 SHA256:2FfTWKZUfOrxX6zVAF1ntvBWQwFylLcR8xnSoh8OBsE akihi@ryzen (RSA)
256 SHA256:l45uQPNTTFxWEU9igoKmYBqkB2jxUUMTBoNB8Ts11cc akihi@ryzen (ED25519)
256 SHA256:XheuPE/EMIWBlQtrzytzIhQk7I0REZZwQevbHyywhgw akihi@ryzen (ECDSA-SK)