手順

SSH鍵の設定:パスワードなしでサーバーにログインする

更新日: · Skillaria.Top

SSH鍵の設定は3ステップです。ssh-keygen -t ed25519 で鍵ペアを作成し、ssh-copy-id user@host で公開鍵をサーバーに登録し、ログインを確認します。その後、/etc/ssh/sshd_config で PasswordAuthentication no を設定してパスワードログインを無効にし、よく使う接続先は ~/.ssh/config に登録します。

SSH鍵は2つのファイルの組です。秘密鍵は自分の手元に残し、公開鍵をサーバーに置きます。接続時にサーバーは、許可された公開鍵に対応する秘密鍵を持っているかを確認し、パスワードなしでログインを許可します。パスワードより便利で、はるかに安全です。鍵を総当たりで推測することは現実的にほぼ不可能だからです。ここでは、鍵の生成からパスワードログインの禁止まで、そして初心者がつまずきやすいエラーの解決法を説明します。

鍵認証の仕組み

鍵は公開鍵暗号方式です。公開鍵(id_ed25519.pub)は誰に見せても構いません。そこから秘密鍵を復元することはできません。秘密鍵(id_ed25519)は自分のマシンから出ることはなく、ネットワーク上で送られることもありません。

ログイン時、クライアントはどの鍵を使うかをサーバーに伝えます。サーバーはそのユーザーの ~/.ssh/authorized_keys からその公開鍵を探し、見つかれば、セッションのデータに秘密鍵で署名するようクライアントに求めます。署名は公開鍵で検証され、正しければログインが許可されます。この間、パスワードは一切送られません。

ステップ1:鍵を生成する(ssh-keygen)

自分のコンピュータ(Linux、macOS、またはOpenSSHが標準で入っているWindows 10/11)で次を実行します。

ssh-keygen -t ed25519 -C "alena@laptop"

-t は暗号アルゴリズムを、-C はコメントを指定します。コメントは公開鍵の末尾に付き、後でその鍵の持ち主を判別する助けになります。Ed25519は現在推奨される新しいアルゴリズムで、鍵が短く、高速で、安全です。サーバーが古くてEd25519に対応していない場合は、3072ビット以上のRSAを使います:ssh-keygen -t rsa -b 4096。

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/alena/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/alena/.ssh/id_ed25519
Your public key has been saved in /home/alena/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:Xq3v0m6c1y2pVv8m3N0uYv9yQm0e6dFv5gH2rZt1aBc alena@laptop

パスフレーズは必要か

パスフレーズは、ディスク上の秘密鍵を暗号化します。ノートパソコンが盗まれたり、ファイルが流出したりしても、パスフレーズがなければ鍵は使えません。個人用の鍵にはパスフレーズを設定するのが望ましいです。毎回入力する手間を省くには ssh-agent を使います。ssh-agentは、復号した鍵をセッションの終わりまでメモリに保持します。

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add -l      # 読み込まれている鍵の一覧

パスフレーズのない鍵は、CIやバックアップスクリプトのような自動処理に使われます。そうした鍵は、サーバー側で利用範囲を制限しておくと安全です(後述)。

ステップ2:公開鍵をサーバーに登録する(ssh-copy-id)

最も簡単な方法は ssh-copy-id です。パスワードで一度だけログインし、サーバーの ~/.ssh/authorized_keys に公開鍵を追記して、正しい権限も設定します。

ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@203.0.113.10
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/alena/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
deploy@203.0.113.10's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'deploy@203.0.113.10'"
and check to make sure that only the key(s) you wanted were added.

サーバーが標準以外のポートを使っている場合は、-p 2222 を追加します。

ssh-copy-id が使えない場合

Windowsには ssh-copy-id がありません。次のコマンドで鍵を手動で登録できます。

cat ~/.ssh/id_ed25519.pub | ssh deploy@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

クラウドプロバイダーでは、サーバー作成時に公開鍵を指定することがよくあります。その場合、cloud-initが authorized_keys に書き込みます。

ステップ3:ログインを確認する

ssh deploy@203.0.113.10

パスワードを求められなければ(または鍵のパスフレーズだけを求められれば)設定は成功です。新しいサーバーに初めて接続するときは、SSHがホスト鍵のフィンガープリントを表示し、信頼するかを尋ねます。yes と答えるとフィンガープリントが ~/.ssh/known_hosts に保存され、以後サーバーの鍵が変わると警告が出ます。

クライアントがどの鍵を試し、サーバーがなぜ拒否したかを確認するには、詳細モードで接続します。

ssh -v deploy@203.0.113.10

~/.ssh/config:サーバーに短い名前を付ける

サーバーが増えると、毎回ユーザー名、IP、ポート、鍵のパスを入力するのは面倒です。これらは ~/.ssh/config に書けます。

Host prod
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Host bastion
    HostName bastion.example.com
    User alena

Host db-internal
    HostName 10.0.0.15
    User admin
    ProxyJump bastion

Host *
    ServerAliveInterval 60
    AddKeysToAgent yes

これで ssh prod と入力するだけで済みます。scp、rsync、Gitもこの名前を理解します。例:rsync -av ./site/ prod:/var/www/。

  • IdentitiesOnly yes:指定した鍵だけを使います。この行がないと、クライアントはagentにあるすべての鍵を順に試します。その結果、正しい鍵に届く前にサーバーの試行回数の上限に達して切断されることがあります。
  • ProxyJump:踏み台サーバーを経由して、内部のサーバーに1つのコマンドで接続します。
  • ServerAliveInterval:60秒ごとにキープアライブを送り、アイドル時に接続が切れないようにします。

設定ファイルの権限は 600 である必要があります。そうでないとSSHが読み込みを拒否することがあります:chmod 600 ~/.ssh/config。

エージェントフォワーディング:いつ使い、何が危険か

サーバーから、さらに別のマシンに接続したい場合があります。たとえば、プライベートリポジトリから git pull を実行する場合です。その際、秘密鍵をサーバーにコピーしてはいけません。代わりに ssh -A または ForwardAgent yes を使うと、セッション中だけサーバーがローカルのagentを利用できます。ただし、そのサーバーのrootユーザーは、あなたが接続している間、同じagentを使えてしまいます。そのため、フォワーディングは信頼できるホストに対してのみ有効にし、中継サーバー経由で接続する場合は ProxyJump を使ってください。ProxyJump はagentを公開しません。

ステップ4:パスワードログインを無効にする

パスワードログインが許可されている限り、サーバーは総当たり攻撃の対象になります。鍵でログインできることを確認したら、パスワードを無効にします。重要なこと:新しいウィンドウで接続できることを確認するまで、現在のセッションを閉じないでください。閉じると、サーバーから締め出されるおそれがあります。

/etc/ssh/sshd_config を開きます(メイン設定が Include ディレクティブで別のファイルを読み込んでいる場合は、/etc/ssh/sshd_config.d/ にファイルを作成します)。次の内容を設定します。

PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no

PermitRootLogin no は、rootでの直接ログインを禁止します。管理者は自分のユーザーでログインし、sudo で権限を上げます。どうしてもrootでのログインが必要な場合は、PermitRootLogin prohibit-password を使うと、鍵による認証だけを許可できます。

構文を確認し、サービスを再読み込みします。

sudo sshd -t
sudo systemctl reload ssh      # Debian/Ubuntu。RHEL系では sshd

設定が正しければ sshd -t は何も表示しません。新しいターミナルで、鍵によるログインが機能すること、そしてパスワードによるログインが拒否されることを確認します。

$ ssh -o PubkeyAuthentication=no deploy@203.0.113.10
deploy@203.0.113.10: Permission denied (publickey).

追加の防御

パスワードの無効化は最も重要な対策です。さらに、ファイアウォールで22番ポートへのアクセスを制限したり(ufw allow from 198.51.100.0/24 to any port 22)、fail2ban を導入したりするのが一般的です。fail2banは、連続して失敗した接続元のIPを一時的にブロックします。SSHの防御状態は sudo fail2ban-client status sshd で確認できます。

自動処理に使う鍵は、authorized_keys の鍵の前にオプションを付けて制限できます。たとえば from="198.51.100.7",no-port-forwarding,no-pty ssh-ed25519 AAAA... backup と書くと、そのアドレスからの接続だけを許可し、対話的なシェルを使えないようにできます。

よくあるエラーと対処法

Permission denied (publickey)

最も多いエラーです。原因は、よくある順に次のとおりです。

  1. サーバー側の権限が不正。ディレクトリやファイルが他のユーザーから書き込み可能だと、sshdは authorized_keys を無視します。対処法:chmod 700 ~/.ssh、chmod 600 ~/.ssh/authorized_keys を実行し、ホームディレクトリがグループやその他のユーザーから書き込み可能になっていないことを確認します。
  2. 所有者が不正。sudo でファイルを作成すると、所有者がrootになります。対処法:sudo chown -R deploy:deploy /home/deploy/.ssh。
  3. 鍵が別のユーザーに登録されている。rootに対して鍵をコピーしたのに、deploy としてログインしようとしている、またはその逆です。
  4. クライアントが違う鍵を提示している。ssh -v の出力で、Offering public key の行を見ると、試している鍵が分かります。-i または IdentityFile で正しい鍵を指定してください。
  5. コピー時に鍵が壊れた。公開鍵は1行である必要があります。クリップボードから貼り付けるときに改行が入ると壊れます。

サーバー側の拒否理由はログに出ます。sudo journalctl -u ssh -n 30 で確認してください(RHELでは -u sshd)。Authentication refused: bad ownership or modes for directory /home/deploy/.ssh のような行が見つかることがあります。

UNPROTECTED PRIVATE KEY FILE

他のユーザーが読める秘密鍵は、クライアントが使用を拒否します。対処法:chmod 600 ~/.ssh/id_ed25519。

REMOTE HOST IDENTIFICATION HAS CHANGED

サーバーのホスト鍵が、known_hosts に保存されたものと一致しません。サーバーを再構築した場合やIPが変わった場合に起こりますが、中間者攻撃でも同じ表示になります。サーバーが本当に作り直されたのかを確認してから、古い記録を削除します:ssh-keygen -R 203.0.113.10。

Too many authentication failures

agentがサーバーに多くの鍵を提示したため、サーバーの MaxAuthTries の上限に達して切断されました。解決法は、~/.ssh/config に IdentitiesOnly yes と明示的な IdentityFile を書くことです。

まとめ

SSH鍵の設定は5分で済みます。ssh-keygen -t ed25519、ssh-copy-id、ログインの確認を行い、2つ目のセッションを開いたままにして、PasswordAuthentication no を設定し、sshdを再読み込みします。~/.ssh/config を使えば長いコマンドを省けます。そして 700 と 600 の権限を守れば、「Permission denied」の大半は解決します。SSH、rsync、ファイアウォールとfail2banによるサーバー保護は、Linuxコースで実践を通して解説しています。

よくある質問

1つのSSH鍵をすべてのサーバーで使ってもいいですか?

技術的には可能で、そうしている人も多くいます。ただし、仕事、個人用プロジェクト、CIなど用途が違うなら、鍵は分けるのが望ましいです。1つの鍵が漏れても、すべてのアクセスが危険にさらされることはありません。

WindowsでSSH鍵はどこに保存されますか?

標準のOpenSSHは C:\Users\ユーザー名\.ssh\ に保存します。そこには id_ed25519、id_ed25519.pub、known_hosts、config があります。PowerShellでも同じ ssh-keygen コマンドで生成できます。

既存の鍵のパスフレーズを変更するにはどうすればいいですか?

ssh-keygen -p -f ~/.ssh/id_ed25519 を実行します。古いパスフレーズと新しいパスフレーズを求められます。鍵そのものは変わらないので、サーバーに再登録する必要はありません。

鍵によるアクセスを取り消すにはどうすればいいですか?

サーバーの ~/.ssh/authorized_keys から、その公開鍵の行を削除します。鍵の末尾のコメントがあると、該当の行を見つけやすくなります。

秘密鍵しか残っていない場合、公開鍵はどうやって取り出せますか?

ssh-keygen -y -f ~/.ssh/id_ed25519 を実行すると、秘密鍵から計算された公開鍵が表示されます。

動画でこのテーマを学ぶ

このテーマはコース「Linux: с нуля до уверенного администрирования」で実践とともに詳しく解説しています。

コースへ