ssh-agentの使い方と注意点の備忘録
リモートサーバー上でGitリポジトリ操作するとき、クライアント端末に保管してあるGit用のSSH鍵をリモートサーバーにコピーして、git clone ..
してましたが、もちろん良くない。
ssh-agentの仕組みと使い方が、やっと分かってきたので備忘録残しときます。
試した環境
- クライアントは、Windows11 + VSCode + Remote-SSH
- リモートサーバーは、Ubuntu20.04
- リポジトリは、GithubとホスティングしているGitLabの2つ
ssh-agentについて
このエージェントは、クライアント端末上でサービスとして稼働していて、SSH鍵を登録しておくことができる。
リモートサーバー上で必要になった時に、このエージェントが登録した鍵を提供してくれて、リモートでSSH鍵が使える。リモート上にSSH鍵は存在しないので、セキュアであるという仕組み。
Windows11クライアントでssh-agentをセットアップする
ssh-agentはサービスとして常時稼働させておく。Windows11の場合は、すでにインストールされているので、管理者権限でPowerShellを起動して開始設定を行う。
この操作は1回だけやればOK。サービスとして以降常駐することになる。
普段はVSCode + Remote-SSHでログインしてるけど、サービスで稼働しているので常に利用できるようになる。
登録したら、Get-Service ssh-agent
でRunningになっているか確認する。
> Get-Service ssh-agent | Set-Service -StartupType Automatic
> Start-Service ssh-agent
> Get-Service ssh-agent
Status Name DisplayName
------ ---- -----------
Running ssh-agent OpenSSH Authentication Agent
ssh-agentにSSH鍵を登録する
ssh-addコマンドでSSH鍵を複数登録する。
SSH鍵や接続情報は%USERPROFILE%\.ssh\
で管理しているはずなので、ここにあるSSH鍵のパスを指定して登録する。ここで登録する必要がある鍵は、あくまでリモートサーバー上で必要になる鍵だけでOK。
> ssh-add /path/to/ssh-key-file
クライアント端末で、現在登録されている鍵の確認する。表示される内容は鍵の種類で異なる。SSH鍵ファイルの末尾にあるコメントも出力される。後述するフィルタ機能で重要になるので、なるべく特定できるコメントになるようにしておく。
> ssh-add -l
4096 SHA256:xxxxxxxxxxxxx hoge@hoge.com (RSA)
2048 SHA256:xxxxxxxxxxxxx huga@huga.com (RSA)
ちなみに、削除する方法は、-d {鍵}
や-D
で一括削除できる。
> ssh-add -d /path/to/ssh-key-file
> ssh-add -D
リモートサーバーへのSSH接続設定
リモートサーバーへSSH接続する際、SSHエージェントをリモートへ転送する設定を行う必要がある。
接続情報が%USERPROFILE%\.ssh\config
に保存されている場合、各ホストの接続情報にForwardAgent yesを追加しておくと、リモートサーバーにSSHログインしたときに、自動的にエージェントが転送されて、登録した鍵を参照することができる。
Host remote-server
HostName XXX.XXX.XXX.XXX
Port 22
User hoge
IdentityFile ~/.ssh/hoge
ForwardAgent yes
全設定でまとめて転送する場合は
Host *
ForwardAgent yes
を追加しておくと良い。
リモートサーバー上で鍵の確認
ここまで設定できたら、リモートサーバーにSSHログインして、鍵が見えている確認する。
ssh-add -lコマンドを実行して、クライアント端末で実行したときの同じ情報が表示されればOK。
> ssh remote-server
hoge@xxx: ~$ ssh-add -l
4096 SHA256:xxxxxxxxxxxxx hoge@hoge.com (RSA)
2048 SHA256:xxxxxxxxxxxxx huga@huga.com (RSA)
- VSCode上でコマンドパレットを起動
- Remote-SSH: ホスト上のVS Code Serverを強制終了するを実行
- 該当するホストを選択して、起動中のプロセスを削除する
- もう一度Remote-SSHでログインしなおす
で解消できる。
リモートサーバー上でGitの操作確認
Githubに接続するために必要なSSH鍵をssh-addで登録してある状態で、リモート端末上で、Githubのリポジトリからクローン等できることを確認する。
> git clone ssh://git@github.com/user/repository.git
Cloning into 'repository'...
remote: Enumerating objects: xxx, done.
remote: Counting objects: 100% (xxx/xxx), done.
:
Resolving deltas: 100% (xx/xx), done.
上記は、リモートサーバー上にSSH鍵はもちろんconfigファイルがなくてもクローン出来るようになるので、セキュアである。
ポート番号がデフォルト22番じゃないGitリポジトリサーバー
Gitリポジトリサーバーをホスティングしている場合などで、ポート番号がデフォルト22番じゃない場合。例えば、hoge.huga.com:1234で稼働している場合は、
> git clone ssh://git@hoge.huga.com:1234/user/repository.git
ポート番号を付けてクローンする。
Githubアカウントを仕事用、プライベート用2つ持っている。ssh-agent設定だけでは片方の接続に失敗する
Githubへの接続ユーザは、全ユーザgitである。じゃあどうやって識別しているのかというと、GithubはSSH公開鍵で識別している。なので、2つのアカウントで同じ鍵を登録することはできない。
ローカル端末では以下のようにして、仕事用/プライベート用のGithub接続情報をconfigファイルに定義していれば、Host識別子でssh接続することで切り替わるので問題ない。
Host github.job
User git
HostName github.com
IdentityFile ~/.ssh/user1.key
IdentitiesOnly yes
Host github.private
User git
HostName github.com
IdentityFile ~/.ssh/user2.key
IdentitiesOnly yes
ssh -T
で接続テストしてみると、アカウントが切り替わっていることが分かる。
# 仕事用
ssh -T git@github.job
Hi user1 ! You've successfully authenticated, but GitHub does not provide shell access.
# プライベート用
ssh -T git@github.private
Hi user2 ! You've successfully authenticated, but GitHub does not provide shell access.
ところが、この2つの鍵をssh-addで登録した後、リモートサーバーでGithubに接続するとうまく動作しない。正確にいうと、後で登録したSSH鍵を使うGithubアカウントのアクセスがうまくいかない。下記の場合、user2の鍵を使うアクセスがNG。
> ssh-add ~/.ssh/user1.key
> ssh-add ~/.ssh/user2.key
おそらく、user1.key, user2.keyと順番に試しているのか、1つ目の鍵でアクセスできたが認証に失敗?してuser2.keyを試してくれないような感じだと思われる。
解決方法は、
- ssh-agent-filterインストールする(リモートサーバー)
- 鍵のフィルタリングするコマンドをcore.sshcommandオプションで追加する
まずリモートサーバーにssh-agent-filterをインストールするが、おそらくgitと一緒にインストールされている可能性が高い。
> sudo apt install ssh-agent-filter
次にクローンするときにgit configのオプションを追加する。めんどくさいが1回だけなので、我慢する。
--config
でユーザ名、メールアドレス、SSH鍵のフィルタリングを指定してクローンすると、git configのローカル設定としてリポジトリに登録される。
> git clone \
--config user.name="user2" \
--config user.email="user2@huga@huga.com" \
--config core.sshcommand="afssh --comment huga@huga.com --" \
git@github.com/user2/repository.git
ユーザ名とかメールアドレスのスイッチングは.gitconfig
でもできるが、こちらの方がシンプルで分かりやすい。うっかり、会社のメールアドレスで、プライベートリポジトリをコミットするなどの誤爆をしなくて済む。
SSH鍵が複数あるローカルPCの場合
core.sshcommandのところで直接利用する鍵を指定する。
> git clone \
--config user.name="user2" \
--config user.email="user2@huga@huga.com" \
--config core.sshcommand="ssh -i ~/.ssh/github-key1 -F /dev/null" \
git@github.com/user2/repository.git
Discussion