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