鍵を入れたのになぜパスワードを訊かれるのか
一言でいうと
公開鍵認証が失敗する原因の大半は、暗号学ではなくファイルの権限です。sshdは、権限が緩いと鍵を静かに拒否します。
なぜ必要なのか
ssh-copy-idで鍵を入れたのに、まだパスワードを尋ねられます。クライアントのログ(ssh -vvv)を見ると、鍵を提示(Offering public key)したのに、サーバーが受け付けてくれません。サーバーのログにも、はっきりした理由がありません。
原因はたいてい、これです。
chmod 755 ~ # 홈이 그룹 쓰기 가능이면 거부된다
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
sshdがこれほど厳格なのには理由があります。authorized_keysを他のユーザーが書き込めるなら、そのユーザーが自分の鍵を1行追加して、他人のアカウントでログインできてしまいます。権限がそのまま認証ポリシーになるのです。
RHEL系には、落とし穴がもう1つあります。ホームディレクトリを手で作ったり、ファイルを別のパスからコピーしたりすると、SELinuxコンテキストが間違って鍵が拒否されます。ログに権限の問題としてはっきり記録されないので、多くの時間を取られます。restorecon -Rv ~/.sshが標準的な解決策です。
どう動くのか
鍵は2つの部分です。秘密鍵は自分の手元にだけあり、公開鍵はサーバーのauthorized_keysに1行として入ります。認証は、サーバーが出した問題を秘密鍵で署名して送る方式なので、秘密鍵がネットワークに出ていくことはありません。
鍵の種類は、事実上2つに絞られました。
ssh-keygen -t ed25519 -C 'youngju@laptop-2026' -f ~/.ssh/id_ed25519
ssh-keygen -t rsa -b 4096 -C 'youngju@laptop-2026' -f ~/.ssh/id_rsa
ssh-keygen -t ed25519-sk -f ~/.ssh/id_ed25519_sk # FIDO2 하드웨어 키
Ed25519がデフォルトで、FIPSのような組織のポリシーが要求するときだけ、RSA 4096を使います。-skは、秘密鍵がハードウェアの外に出ません。
-Cのコメントに人と機器を書く習慣が重要です。authorized_keysに20行が溜まったとき、どの行が誰のものかを知る唯一の手がかりだからです。
authorized_keysの各行には、制約を付けられます。
restrict,from="10.0.0.0/8",command="/usr/local/bin/deploy-only" ssh-ed25519 AAAAC3Nza... deploy@ci
restrictは、すべての機能をオフにする安全なデフォルトです。そのあと、必要なものだけを再び有効にします。from=は、接続元を制限します。command=は、クライアントが何を要求しても、指定したコマンドだけを実行します。デプロイ用の鍵に特に有用です。
クライアント側の設定も、ファイルに書いておくほうがよいです。
Host bastion
HostName bastion.example.com
User youngju
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ServerAliveInterval 30
Host prod-*
User deploy
ProxyJump bastion
IdentitiesOnly yes
IdentitiesOnly yesが特に重要です。ないと、エージェントに載っているすべての鍵を順番に試し、サーバーのMaxAuthTries(デフォルト6)に引っかかって、認証が失敗します。鍵を複数持つ人が経験する、代表的な問題です。
現場での姿
鍵の取り消しは、ファイルから行を消すだけでは終わりません。すでに開いているセッションは、そのまま生きています。完全な取り消しは、行の削除 → whoでセッションを確認 → 該当ユーザーのsshdセッションを終了、の順序です。最後の段階は、自分自身のセッションまで切ってしまうことがあるので、対象アカウントを必ず確認します。
ホスト鍵の警告を習慣的に無視すること。サーバーを再インストールするたびに表示されるので、そうなります。その習慣が、中間者攻撃に対する唯一の防御線を無力にします。規模が大きくなったら、SSH証明書(ホスト鍵をCAで署名)へ移行するのが正解です。
鍵があるのにログインできないとき
Permission denied (publickey)は原因が複数ありますが、確認の順序を決めておくと、たいてい1分以内に終わります。
まず、クライアントがどの鍵を送っているかを見ます。
ssh -v user@host 2>&1 | grep -E "Offering|Authentications|Server accepts"
鍵を複数持っていると、sshは順番に試しますが、サーバーのMaxAuthTries(デフォルト6)に先に引っかかって、肝心の正しい鍵を送る前に切断されます。そのときは、使う鍵を明示します。
Host prod
IdentityFile ~/.ssh/id_prod
IdentitiesOnly yes # 다른 키는 아예 시도하지 않는다
権限が少し緩いだけでも、sshdは拒否します。これが最もよくある原因です。
| 対象 | 権限 |
|---|---|
~ |
グループ・その他に書き込みなし(755以下) |
~/.ssh |
700 |
~/.ssh/authorized_keys |
600 |
| 秘密鍵 | 600 |
サーバー側のログ(journalctl -u sshd)にAuthentication refused: bad ownership or modesが残るので、アクセスできるなら、それが最も速い答えです。
サーバーの設定が、その方式を塞いでいる場合があります。PubkeyAuthentication、AuthorizedKeysFile、AllowUsers/AllowGroups、そしてPermitRootLoginを見ます。最近のディストリビューションは、古い鍵形式(ssh-rsa with SHA-1)をデフォルトで拒否するので、古い鍵が突然使えなくなることがあります。そのときは、鍵を新しく作るのが正解で、急ぐなら、PubkeyAcceptedAlgorithmsに一時的に追加します。
エージェントは、つい忘れがちです。ssh-add -lが空なら、パスフレーズで保護された鍵は使えません。エージェントフォワーディング(-A)は便利ですが、そのサーバーのrootが、自分のエージェントをそのまま使えます。ジャンプが目的なら、ProxyJumpを使います。鍵が中間サーバーにさらされません。
Host prod
ProxyJump bastion
次のラボですること
鍵を作成し、権限を合わせ、authorized_keysに登録して、実際に127.0.0.1:2222に接続します。~/.ssh/configでエイリアスを作り、command=制約を付けた鍵が、本当にそのコマンドだけを実行するかを確認します。