Windows と WSL2 で同じ SSH key を使用する方法

スタッフブログ

皆様どうも、こんにちは!
こまりの情報処理技術者、桑木です。

WSL2はただ単にWindowsから使えるLinux環境と言うだけでなく、とてもシームレスにコマンド実行やファイルの参照ができるので、WindowsにLinuxが融合したかのような使い心地を得ることができます。

しかし、アプリケーションレベルではやっぱり別環境なので、SSHの設定などはそれぞれ個別にする必要があります。とはいえ、複数の鍵を作ったり、同じ鍵をコピーしたりはしたくありません。

そこで、今回の記事ではWindowsにssh-agentを設定することで、WSL2でSSH接続するときの認証をWindows側に転送して肩代わりさせる方法を説明します。

手順

ひとまず先に手順だけ載せます。

Chocolateyをインストールしていない場合は、手順に従ってインストールしてください。色々書かれていますが、Step2.2のコマンドを管理者権限のpowershellにコピペして実行するだけです。Chocolateyはnpiperelayをインストールするために使うだけなので、npiperelayを他の方法でインストールできるならChocolateyは不要です。

管理者権限のpowershellで以下のコマンドを実行します。

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
choco install -y npiperelay
ssh-add

WSL2の~/.bash_profileに次の記述を追加します。

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

上記の.bash_profileがなければ作成します。
その場合は上の記述とは別に、次の行を先頭に記述します。既に.bash_profileが存在する場合は、同じ意味の記述がしてあるはずなので不要です。

test -r ~/.bashrc && . ~/.bashrc

WSL2で次のコマンドを実行します。

sudo apt install -y socat

WSL2再起動後に次のコマンドを実行してWindows側と同じものが表示されればOKです。

ssh-add -l

解説(Windows側)

SSHエージェントとはなんぞや、ということに関してはqiitaの記事なんかが詳しいので参考にしてください。
ここでは前述の手順の意味を解説をします。

OpenSSHサービス(SSHエージェント)の常駐

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent

Windowsに登録されている「OpenSSH Authentication Agent」サービスの「スタートアップの種類」が初期状態では「無効」になっているので、「自動」に設定してWindows起動時に自動的に起動するようにしています。

これはWindows起動時の動作を設定しただけなので、今回に限り手動でも起動してやります。

このサービスが起動すると、Windowsについてくるssh-agent.exeが常駐して名前付きパイプ\\.\pipe\openssh-ssh-agentがオープンされます。

SSHエージェントにSSHキーの登録

ssh-add

SSHエージェントにSSHキーを登録します。id_rsa的なファイルをパラメータで指定すれば、それが登録されます。省略した場合は、ユーザディレクトリ/.ssh/にあるid_rsa, id_dsa, id_ecdsa, id_ecdsa_sk, id_ed25519, id_ed25519_skなどが登録されるようです。

手順前後しますが、

ssh-add -l

SSHエージェントに登録されているSSHキーの一覧を表示します。WindowsとWSL2の両方で、このコマンドで同じものが表示されればSSHエージェントが正しく機能していることが確認できます。

名前付きパイプのリレーに使うコマンドのインストール

choco install -y npiperelay

WSL2からWindowsの名前付きパイプを参照するために後で必要になるnpiperelay.exeをインストールします。chocoでインストールすればPATHも通るようなので、インストール先を気にする必要もなさそうです。

解説(WSL2側)

UNIXドメインソケットのリレーに使うコマンドのインストール

sudo apt install -y socat

WSL2側にも、UNIXドメインソケットをリレーするために必要になるsocatをインストールします。

.bash_profile, .bashrc

ログイン時に自動的に実行されるファイルです。今回の場合は.bash_profileに後で説明するコマンドを記述して、ログイン時に自動実行させます。WSL2のUbuntuは、初期状態では.bash_profileが存在しないので作成しますが、.bash_profileが存在する場合は.bashrcが実行されません。

.bashrcは初期状態でも存在していて、シェルを色々ユーザフレンドリーにしてくれるスクリプトが記述されています。これが実行されないとユーザフレンドみが足りなくなります。

test -r ~/.bashrc && . ~/.bashrc

そこで.bash_profileの中から.bashrcを実行するコマンドを記述しておきます。

UNIXドメインソケットと連携

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

環境変数SSH_AUTH_SOCKに適当なパスを指定します。WSL2側のsshコマンドはSSH_AUTH_SOCKが設定されていれば、そこに指定されたUNIXドメインソケットを通してSSHエージェントとやりとりします。

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

SSH_AUTH_SOCKで指定したUNIXドメインソケットが存在するかどうか判定して、存在しなければsocatを実行して作成します。

このソケットに接続があればnpiperelayが起動されて、その標準入出力とUNIXドメインソケットの入出力がリレーされます。npiperelayは、Windowsの名前付きパイプと標準入出力をリレーするコマンドですが、結果的にこれでWindowsの名前付きパイプとWSL2のUNIXドメインソケットが接続されている状態になります。

まとめ

  • WindowsにUNIXドメインソケットはないが、ほとんど同じ機能の名前付きパイプ(named pipe)がある
  • ssh-agentをWindowsに移植する際に名前付きパイプを使用するように変更された
  • WindowsとWSL2の連携は良くできているものの、残念ながらWSL2から直接名前付きパイプを参照する方法がない
  • 標準入出力ならシームレスに連携できる
  • よって、UNIXドメインソケットと名前付きパイプを標準入出力経由で接続すればOK

参考