🗂

WSL2内のSSHクライアントから、Windows側のSSHエージェントに格納された秘密鍵を使ってSSH接続する。

に公開

wsl内で秘密鍵を共有したりしてすべてを完結するならそれはそれで簡単ではあるが、敢えてここではwindowsのsshエージェントのサービスと共有してみる。

Windowsの ssh-agentサービスを有効にする

まずここから。

powershell管理者モードで

Get-Service ssh-agent

とすると

PS C:\Windows\system32> Get-Service ssh-agent

Status   Name               DisplayName
------   ----               -----------
Stopped  ssh-agent          OpenSSH Authentication Agent

こんな風に停止しているのがわかる。これを活性化する

Set-Service -Name ssh-agent -StartupType Manual
Start-Service -Name ssh-agent

再度Get-Serviceしてみる


Runningになっている

秘密鍵を作成するか、あるいは転送してくる

windows側でssh-addとかすると基本的にUSERPROFILE.ssh 以下に配置されるので、このディレクトリをベースに考える事にする。鍵を外部から持ってくるにせよ、ssh-keygenして適当に鍵作ればディレクトリーが作成されるのでそのディレクトリの中に放りこんじゃえば早いかも。

ここで一度ssh-addしてみる

$USERPROFILE/.sshに置いたなら

ssh-add "$env:USERPROFILE\.ssh\鍵名"

これでagentに鍵が登録される。windows側のsshからは普通に鍵接続できると思う。

agentを自動起動する

Set-Service -Name ssh-agent -StartupType Automatic

この時点で一度windows再起動して、ssh-agentの自動起動を確認しておこう。

起動したら再度

Get-Service ssh-agent

してRunningになっているのを確認する

PS C:\WINDOWS\system32> Get-Service ssh-agent

Status   Name               DisplayName
------   ----               -----------
Running  ssh-agent          OpenSSH Authentication Agent

のように

wsl2側の作業

たとえ、windows側でagentに鍵がセットされていたとしてもwsl2は空間が分離されているのでアクセスは不可能だ。これをnpiperelayを用いてsocketを通じて何とか共有してみよう。

npiperelayのinstall

ここでもchocoでインストールしている

choco install npiperelay

ここで

C:\ProgramData\chocolatey\lib\npiperelay\tools
 ShimGen has successfully created a shim for npiperelay.exe

こんな具合のpathにインストールされる。

このpathは後で重要になる

wsl側でsocatをinstall

sudo apt install socat

wsl2から接続してみる

まずnpiperelay.exeまでのpathを確認しておく。cドライブのProgramDataとかに入っているなら /mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe なんかがwsl2からのアクセスパスになるはずだ。以下はfileコマンドでの確認

$ file /mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe
/mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows, 5 section

このようにwindowsバイナリである事が示された。

ここで /mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe にバイナリが存在していたので、以下のようなコマンドを起こしてみよう。これをcon.shとかにして適当に起動する

#!/bin/sh
SOCKET_PATH="$HOME/.ssh/ssh-agent.sock"
rm -f "$SOCKET_PATH"

NPIPERELAY_PATH=/mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.ex
e
socat UNIX-LISTEN:"$SOCKET_PATH",fork EXEC:"$NPIPERELAY_PATH -ei -s //./pipe/ope
nssh-ssh-agent"

するとアクセスしっぱなしになるので、別ターミナルを起動し

export SSH_AUTH_SOCK="$HOME/.ssh/ssh-agent.sock"

とかして

ssh-add -l

すると

$ ssh-add -l
2048 SHA256:CTky91Xtze79QenmzOz3vguGproXJmRw/KmWcZKPPM4 C:\Users...

みたいな感じでキーがリストされてくるはずだ、こうなれば後はもう動いてるのでsshで接続するだけ。

再起動後のオペレーション

結局再起動した時どうなるかが重要だよな

再起動した状態としては

  • windowsでssh-agentが起動している
    • しかしssh-addはされておらず鍵は入っていない
  • wsl2に関しては何もしていない

ここで、まずpowershellを起動し

ssh-add "$env:USERPROFILE\.ssh\鍵名"

して鍵をストアしたらwsl2の中に .config/wsl/ssh-agent-bridge.sh こんなのを作ってcon.shみたいなのを移す。ここでは $HOME/.sshにsocketが入るのを想定しているのでもし.sshがなければ作成した方がいい(というかscriptをいじってなんとかしてもいいけど)

#!/bin/bash
SOCKET="$HOME/.ssh/ssh-agent.sock"
NPIPERELAY="/mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe"

if [ ! -S "$SOCKET" ]; then
  rm -f "$SOCKET"
  nohup socat UNIX-LISTEN:"$SOCKET",fork EXEC:"$NPIPERELAY -ei -s //./pipe/openssh-ssh-agent" >/dev/null 2>&1 &
  sleep 0.3
fi

export SSH_AUTH_SOCK="$SOCKET"

これでwindows側でssh-addが最初にされていれば、これでagentを媒介して接続ができる

しかしwindowsでssh-addするのがキツい

って場合はセキュリティー的な低下を見るのであるが、まず鍵からパスフレーズを抜きとらないといけない

powershellより

ssh-keygen -p -f "$env:USERPROFILE\.ssh\id_rsa" -N '""'

とするとパスフレーズを聞かれ成功するとパスフレーズが削除される

PS C:\WINDOWS\system32> ssh-keygen -p -f "$env:USERPROFILE\.ssh\id_rsa" -N '""'
Enter old passphrase:
Your identification has been saved with the new passphrase.

ここで一度再起動をかけてみよう

そしてwindowsからssh-addすれば

ssh-add $env:USERPROFILE\.ssh\id_rsa
Identity added: C:\Users\...

となるはずだ。

無パスワードなら自動化できる

Start-Service ssh-agent
ssh-add "$env:USERPROFILE\.ssh\id_rsa"

こんなのを c:\Users<ユーザー名>\Scripts とかに配置するとして、taskschd.mscを起動

基本タスクの作成から名前をAutoSSHAddとかにして、ログオン時にする

プログラムの開始よりプログラムはpowershellで、引数を

-WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\<ユーザー名>\Scripts\ssh-add.ps1"

とかにする

トラブルシュートはしないが、これでagent経由でsshできるはずだ

最後に

wsl2で閉じているよりwindows内部のagentを経由した方がwindowsで作業する人にとっては便利な事も多いはずである。たとえばvscodeでsshを経由したりとか。設定の難易度が若干高いがやる価値が無いとも思えない。ただし、完全自動化はおそらくパスフレーズを抜き取る必要があるので、鍵を取られないようにするとかいう事は絶対条件ではある。あるいは取られたときの被害を最小に抑える努力をするとか

Discussion