TT Lab
はじめる
学ぶ 学習パス コース

SSHとファイル転送

鍵を入れたのになぜパスワードを訊かれるのか

TT Labで続きを見る

一言でいうと

公開鍵認証が失敗する原因の大半は、暗号学ではなくファイルの権限です。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

クライアント側の設定も、ファイルに書いておくほうがよいです。

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=制約を付けた鍵が、本当にそのコマンドだけを実行するかを確認します。