SSH鍵認証の設定:Ed25519・ssh-agentとサーバーのセキュリティ
EdwardMoon
SSH鍵認証は、単にパスワードを不要にする方法ではありません。サーバーの身元確認、秘密鍵の保護、公開鍵の配布、新しいセッションでの検証、ログインポリシーの強化をつなぐ信頼の手順です。秘密鍵はクライアントの外へコピーせず、パスフレーズとssh-agentで保護します。
このガイドではEd25519を基本とし、FIPSモードでのRSAという選択肢、known_hostsの検証、authorized_keysの権限、sshdの設定確認、鍵の失効、障害復旧までを運用の順序で説明します。

2種類の検証を区別する
| 検証対象 | 保存場所 | 検証に失敗した場合のリスク |
|---|---|---|
| 本物のサーバーか | クライアントのknown_hosts | 中間者が用意したサーバーに接続する可能性 |
| 許可されたユーザーか | サーバーのauthorized_keys | 盗まれた鍵や未承認の鍵でログインされる可能性 |
公開鍵によるユーザー認証だけでは安全性を判断できません。信頼できるコンソール、資産管理システム、別の通信経路でサーバーのhost keyのフィンガープリントを確認し、接続先をすり替える攻撃を検出できるようにします。
クライアントでパスフレーズ付きの鍵を作成する
一般的な環境では、Ed25519が扱いやすく安全な既定の選択肢です。ただしFIPSモードでは許可されない場合があるため、その方針では十分な長さのRSA鍵を使用します。既存の鍵を上書きしないように、用途別のファイル名を指定してください。
install -d -m 0700 ~/.ssh
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_ops -C 'ops-admin@client'
chmod 0600 ~/.ssh/id_ed25519_ops
chmod 0644 ~/.ssh/id_ed25519_ops.pub
FIPS環境でRSAを使用する
ssh-keygen -t rsa -b 3072 -o -a 100 -f ~/.ssh/id_rsa_ops -C 'ops-admin@client'
秘密鍵をサーバー、チケット、メッセンジャー、Gitリポジトリへアップロードしないでください。サーバーへ配布するのは、拡張子が.pubの公開鍵1行だけです。
ssh-agentで鍵のロック解除状態を管理する
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_ops
ssh-add -l
別の経路でサーバーのhost keyを検証する
サーバーのコンソールで公開host keyのフィンガープリントを表示し、クライアントが初回接続時に表示する値と照合します。ssh-keyscanは鍵を収集するだけで、その鍵が本物のサーバーのものかを証明しません。結果を未検証のまま信頼しないでください。
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
sudo ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
ssh-keyscan -t ed25519 server.example.com > /tmp/server.hostkey
ssh-keygen -lf /tmp/server.hostkey
install -m 0600 /tmp/server.hostkey ~/.ssh/known_hosts.ops
rm -f /tmp/server.hostkey
両方の出力のSHA256フィンガープリントが、別経路で確認した値と完全に一致した場合にのみ、known_hostsファイルを使用します。不一致なら接続を中止し、DNS、IP、再インストールの記録を調べてください。
公開鍵をauthorized_keysへ配布する
初回設定では、現在許可されているパスワード認証またはコンソールで接続し、公開鍵を追加します。ssh-copy-idを利用できれば、重複や権限の処理が容易です。
ssh-copy-id -i ~/.ssh/id_ed25519_ops.pub ops@server.example.com
ssh-copy-idがない場合の手動配布
cat ~/.ssh/id_ed25519_ops.pub | ssh ops@server.example.com 'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys'
# ここからはサーバーのopsユーザーのセッションで実行する。
chmod 0700 ~/.ssh
chmod 0600 ~/.ssh/authorized_keys
restorecon -RFv ~/.ssh
SELinuxが有効なRHEL系では、ファイル権限に加えてコンテキストも正しく設定する必要があります。ホームディレクトリが他のユーザーから書き込み可能になっていないかも確認してください。
クライアントの別名と使用する鍵を明示する
Host prod-app-01
HostName server.example.com
User ops
IdentityFile ~/.ssh/id_ed25519_ops
IdentitiesOnly yes
UserKnownHostsFile ~/.ssh/known_hosts.ops
chmod 0600 ~/.ssh/config
ssh -v prod-app-01
パスワードログインを無効にする前の確認
現在の管理者セッションを閉じずに、別端末で公開鍵ログインを確認します。コンソールからの復旧手段とsudo権限を検証するまでは、PasswordAuthenticationを無効にしないでください。
ssh -o PreferredAuthentications=publickey -o PasswordAuthentication=no prod-app-01
sudo -v
whoami
sshdの構文と実効設定を確認する
sudo sshd -t
sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '
鍵認証の確認後、drop-inファイルでポリシーを分けます。ディストリビューションのinclude順序やMatchブロックによって最終値が変わるため、ファイルの記述だけでなくsshd -Tの出力を確認してください。
sudo install -d -m 0755 /etc/ssh/sshd_config.d
sudo tee /etc/ssh/sshd_config.d/20-key-auth.conf >/dev/null <<'CONF'
PubkeyAuthentication yes
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
CONF
sudo sshd -t
sudo sshd -T | grep -E "^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin) "
sudo systemctl reload sshd
ssh -o PreferredAuthentications=publickey prod-app-01
sudo journalctl -u sshd --since '-10 minutes' --no-pager
鍵の利用範囲を制限し、失効させる
自動化用の鍵は、人が使う汎用管理者鍵と分離します。必要に応じてauthorized_keysのオプションで接続元や機能を制限してください。トンネリングやPTYなど、サービスが必要とする動作を妨げる場合があるため、試験環境で先に確認します。
from="198.51.100.0/24",restrict ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... deploy-key
鍵の漏えいやユーザーの退職時には、該当する公開鍵の行を削除します。一元的な失効管理が必要なら、OpenSSH KRLを作成してsshdのRevokedKeysで参照できます。既存のKRLがある場合は-uで失効済みの一覧を保持して更新し、同じファイルシステム上の一時ファイルで完成させてからアトミックに置き換えます。sshdがKRLを読み取れないと、すべての公開鍵認証が拒否される場合があるため、既存の管理者セッションと復旧用コンソールを維持してください。Matchブロックを使うサーバーでは、sshd -T -C user=ops,host=client.example.com,addr=198.51.100.10のように実際の接続条件も指定して確認します。
KRL_STAGE_DIR=$(sudo mktemp -d /etc/ssh/krl-stage.XXXXXX)
if sudo test -f /etc/ssh/revoked.krl; then
sudo cp -p /etc/ssh/revoked.krl "$KRL_STAGE_DIR/revoked.krl"
sudo ssh-keygen -k -u -f "$KRL_STAGE_DIR/revoked.krl" compromised_key.pub
else
sudo ssh-keygen -k -f "$KRL_STAGE_DIR/revoked.krl" compromised_key.pub
fi
sudo chown root:root "$KRL_STAGE_DIR/revoked.krl"
sudo chmod 0644 "$KRL_STAGE_DIR/revoked.krl"
sudo mv "$KRL_STAGE_DIR/revoked.krl" /etc/ssh/revoked.krl
sudo rmdir "$KRL_STAGE_DIR"
sudo restorecon /etc/ssh/revoked.krl
sudoedit /etc/ssh/sshd_config.d/20-key-auth.conf
# 上記ファイルのグローバル設定に次の1行を追加する。
# RevokedKeys /etc/ssh/revoked.krl
sudo sshd -t
sudo sshd -T | grep "^revokedkeys "
sudo systemctl reload sshd
トラブルシューティング
ssh -vvv prod-app-01
ssh-add -l
ssh-keygen -lf ~/.ssh/id_ed25519_ops.pub
sudo journalctl -u sshd -b --no-pager
sudo namei -l /home/ops/.ssh/authorized_keys
sudo ls -ldZ /home/ops /home/ops/.ssh /home/ops/.ssh/authorized_keys
sudo sshd -T
- Offering public keyの後に拒否されたら、ユーザー、公開鍵の行、権限、SELinuxコンテキストを確認する。
- Too many authentication failuresの場合は、IdentitiesOnlyとIdentityFileを明示する。
- REMOTE HOST IDENTIFICATION HAS CHANGEDが出たら、記録を無条件に削除せず、サーバーの再インストールやDNS変更を確認する。
- 設定変更後に接続できなくなったら、既存セッションかコンソールでdrop-inを戻し、sshd -tを実行する。
公式資料と関連する運用ガイド
- Red Hat:OpenSSHによる安全な通信の構成
- OpenSSH sshd_configマニュアル
- OpenSSH ssh-keygenマニュアル
- Ansible PlaybookとSSH自動化のセキュリティ
- Kubesprayの管理アカウントとhost keyの検証
SSH鍵認証では、鍵の生成以上にライフサイクル管理が重要です。秘密鍵をクライアントだけに保管し、サーバーのフィンガープリントを検証し、新しいセッションで接続を確認してからポリシーを強化します。漏えいした鍵を即座に失効できる体制があって初めて、パスワード不要の接続が実際のセキュリティ向上につながります。