概要
┌────────────┐ ┌────────────────┐
│ ローカル │ │ ssh-agent (記憶) │
│ クライアント───接続──▶(UNIX ソケット)───ssh(署名)│
│ (ターミナル等) │ │ │
└────────────┘ └────────────────┘
↑ │
│ │ ssh-add によって秘密鍵を登録
│ │ (一度パスフレーズ入力)
│ ↓
環境変数 ssh-agent が鍵保持
SSH_AUTH_SOCK (メモリ上)
-
ssh-agent は、公開鍵認証で使う 秘密鍵を一時的に保持(キャッシュ)するプログラム (man.openbsd.org)
-
鍵は登録時に
ssh-addを使って登録 (manpagez.com) -
sshコマンド (OpenSSH) は、環境変数SSH_AUTH_SOCKでエージェントのソケットを見つけて、エージェントに署名を依頼する(man.openbsd.org)
コマンド
SSH agentが起動しているか確認
echo $SSH_AUTH_SOCK
SSH agentの起動
eval "$(ssh-agent -s)"
- eval
- 引数の文字列を現在のシェルに設定
- -sオプション
- Bourne 系シェル(bash, sh, zsh など)で評価可能な形式で環境変数を出力 するためのオプション
// -sオプション付きの実行で以下のような結果が得られる
SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.1234; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1234; export SSH_AGENT_PID;
echo Agent pid 1234;
// evalで評価すると、現在のシェルに以下のように環境変数が設定される
export SSH_AUTH_SOCK=/tmp/ssh-XXXX/agent.1234
export SSH_AGENT_PID=1234
秘密鍵の登録
//SSH agentに秘密鍵を追加
//デフォルトで以下が追加
// ~/.ssh/id_rsa, .ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519, and ~/.ssh/identity
ssh-add
//登録する秘密鍵を指定する場合
ssh-add ~/work_keys/my_project_key
登録済みの鍵を確認
ssh-add -l
登録済みの鍵を削除
ssh-add -d ~/.ssh/id_rsa # 指定した鍵だけ削除
ssh-add -D # 全ての鍵を削除
詳細
ssh-agent の起動と仕組み
-
コマンドの構文(マニュアルより):
ssh-agent [オプション] [command …] ssh-agent -k // 終了用 -
起動時に Unix ドメインソケット を作成し、そのパスを
SSH_AUTH_SOCK環境変数に設定。 (man.openbsd.org) -
プロセス ID は
SSH_AGENT_PID環境変数に格納される。 (man.openbsd.org) -
-t lifeオプションで、登録する鍵の 最大有効期間 (lifetime) を指定可能。指定しなければ “無期限 (forever)” がデフォルト。 (man.openbsd.org) -
エージェントに登録された鍵は、
ssh-addコマンドを使って追加/削除/照会できる。 (man.archlinux.org) -
ssh-agent起動時にサブコマンドを指定すると、そのコマンドを子プロセスとして実行し、コマンド終了時にエージェントも終了。 (man7.org)
セキュリティと認証に関する設計
-
秘密鍵 (パスフレーズ付き) をファイルから都度読み込む代わりに メモリ上にキャッシュ → 繰り返しパスフレーズを入力する手間を省きつつ、ファイル上の秘密鍵を常にアンロックしたままにせず安全性をある程度保てる。 (docs.oracle.com)
-
sshクライアント (OpenSSH) はSSH_AUTH_SOCKでエージェントを参照し、署名 (認証) を依頼。これにより、ユーザーが毎回秘密鍵を指定/読み込む必要がない。 (man.openbsd.org) -
エージェント転送 (agent forwarding):リモートマシンへの SSH 接続時に
-Aを使ってエージェントソケットを転送できる (マニュアルに注意書きあり) (man.openbsd.org) -
SIGUSR1が送られたとき、エージェントはすべての鍵を消去できる (マニュアル実装により) ※これは人によっては “キャッシュのクリア” に使える。 (mankier.com)
ユースケース
-
対話セッション (ローカル開発)
-
ユーザーがログイン/ターミナルを開いた時に
ssh-agentを起動 (例:eval $(ssh-agent -s))。 -
ssh-addで秘密鍵を登録 (パスフレーズ入力)。 -
以降は Git, SSH 接続などで毎回鍵を指定せずに認証ができる。
-
[ ローカル・端末セッション ]
│
▼ ssh-agent 起動 (例: `eval $(ssh-agent -s)`)
│
├── 環境変数設定
│ ├ SSH_AUTH_SOCK → /tmp/ssh-XXXX/agent.PID
│ └ SSH_AGENT_PID → <PID>
│
▼
ssh-agent プロセス (メモリ上に待機)
│
├── 鍵登録 (ssh-add)
│ └ 秘密鍵 (パスフレーズあり) をメモリにロード
│
▼
他のクライアント (ssh, git など)
│
└─→ `ssh` が `SSH_AUTH_SOCK` を通じて署名を依頼 → ssh-agent が署名 → 認証