この手順で変わることと前提条件
この記事の手順を終えると、サーバーへのSSHログインは秘密鍵を持つ端末からだけ通るようになります。パスワードの総当たり攻撃は成立しなくなり、rootでの直接ログインも拒否されます。公開鍵認証では、手元の秘密鍵と、サーバーに置いた公開鍵の組み合わせで本人確認をします。秘密鍵そのものがネットワークに流れることはありません。
作業には次の環境が必要です。
- OpenSSHサーバー(sshd)が動いているLinuxサーバー。Ubuntu、Debian、RHEL系(AlmaLinux、Rocky Linuxなど)を想定しています。
- sudoを実行できる一般ユーザーのアカウントと、そのユーザーのパスワード。
- OpenSSHクライアントが入った手元の端末。Linux、macOS、Windows 10/11のいずれでも使えます。
- 可能であれば、クラウドやVPSの管理画面から使えるシリアルコンソールなどの、SSHを使わない接続手段。
先に知っておくべきつまずきやすい箇所
締め出し事故の多くは、次の3つが原因です。どれも手順の中で確認するので、先に目を通してください。
1つ目は、公開鍵ログインを確認する前にパスワード認証を無効にしてしまうことです。この記事では、パスワードでログインしたセッションを1本開いたままにします。設定の変更後は、別の端末から新しい接続を試します。sshdを再読み込みしても、既に確立しているセッションは切れません。そのため、新しい設定で失敗しても元のセッションから戻せます。
2つ目は、設定ファイルの読み込み順です。sshd_configでは、同じ項目が複数回書かれていると最初に現れた値が有効になります。最近のUbuntuやDebian、RHEL 9系では、ファイル冒頭のIncludeで/etc/ssh/sshd_config.d/内のファイルを先に読みます。クラウドのイメージにはこの中にPasswordAuthentication yesを書いたファイル(例: 50-cloud-init.conf)が置かれていることがあります。本体の記述を書き換えても効かないのはこのためです。
3つ目は、sudoのパスワードです。SSHで鍵を使うようになっても、sudoは引き続きサーバー上のユーザーのパスワードを要求します。パスワードを忘れると、rootログインを無効にした後は管理作業ができなくなります。
手順1: 手元の端末で鍵ペアを作る
手元の端末で次のコマンドを実行します。鍵の種類にはEd25519を指定します。Ed25519は鍵が短く、現在のOpenSSHで広く使われている方式です。
ssh-keygen -t ed25519 -C 'yourname@laptop'保存先を聞かれたら、既定の~/.ssh/id_ed25519のままEnterを押します。既に同じ名前の鍵がある場合は上書きの確認が出ます。その場合は「n」と答えて、別のファイル名を指定してください。上書きすると、その鍵を使っていた他のサーバーに入れなくなります。
続けてパスフレーズを設定します。パスフレーズは秘密鍵ファイルを暗号化するためのものです。端末の紛失やファイルの流出があっても、すぐには悪用されません。この操作で、秘密鍵id_ed25519と公開鍵id_ed25519.pubの2つのファイルができます。サーバーに渡すのは.pubの付いた公開鍵だけです。
手順2: 公開鍵をサーバーに登録する
LinuxとmacOSではssh-copy-idを使います。この時点ではまだパスワードでログインできるので、パスワードを入力して登録します。
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]このコマンドは、サーバー上の~/.ssh/authorized_keysに公開鍵を追記します。ディレクトリがなければ作成し、権限も適切に設定します。
Windowsにはssh-copy-idがありません。PowerShellで次のように実行します。
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh [email protected] 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'sshdは権限の緩いファイルを信用しません。~/.sshは700、authorized_keysは600で、所有者がログインするユーザー本人である必要があります。ホームディレクトリにグループや他人の書き込み権限がある場合も鍵は拒否されます。
手順3: 公開鍵でログインできることを確かめる
ここで作業用のセッションを1本開き、以降の作業が終わるまで閉じずに置いておきます。このセッションが戻し用の命綱です。
別のターミナルから、鍵だけを使うように指定して接続します。
ssh -o PreferredAuthentications=publickey [email protected]パスフレーズを聞かれて、パスワードを聞かれずにログインできれば成功です。失敗した場合はssh -vを付けて再実行し、どの鍵を送ったかを確認します。サーバー側ではログも確認します。Debian/Ubuntuではsudo journalctl -u ssh、RHEL系ではsudo journalctl -u sshdを使います。Authentication refused: bad ownership or modesと出る場合は、手順2の権限を見直してください。この確認に成功するまで次の手順に進まないでください。
手順4: sshdの設定でパスワード認証とrootログインを無効にする
作業用セッションで、元の設定をバックアップします。
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak次に、設定を書くファイルを決めます。grep -i '^Include' /etc/ssh/sshd_configでsshd_config.dを読み込む行が表示されれば、そのディレクトリに新しいファイルを作ります。ファイルは名前の順に読まれ、先に読まれた値が有効になります。既存のファイルより先に読まれるよう、01-hardening.confのような名前にします。
sudo nano /etc/ssh/sshd_config.d/01-hardening.conf中身は次の4行です。
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin noKbdInteractiveAuthenticationは、キーボード対話型の認証を止める設定です。この設定を残しておくと、PAM経由で実質的にパスワード入力が通る場合があります。古いOpenSSHでは同じ役割の項目をChallengeResponseAuthenticationと呼んでいます。Include行がない環境では、sshd_config本体の該当行を直接書き換えてください。各項目の意味はOpenSSH公式のsshd_configマニュアルで確認できます。
手順5: 構文と実効値を確認してから反映する
反映する前に、2つの確認をします。
sudo sshd -t
sudo sshd -T | grep -Ei '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin) 'sshd -tは構文を検査します。何も表示されなければ問題ありません。sshd -Tは、全ファイルを読み込んだ結果の実効値を表示します。passwordauthentication noとpermitrootlogin noが表示されることを確認してください。yesのままなら、先に読まれる別のファイルに同じ項目があります。grep -ri passwordauthentication /etc/ssh/で探し、手順4のファイル名を調整してください。
確認できたら設定を再読み込みします。サービス名はDebian/Ubuntuではssh、RHEL系ではsshdです。
sudo systemctl reload ssh手順6: 新しい接続で結果を確かめる
作業用セッションは閉じずに、別のターミナルから3つの接続を試します。1つ目は手順3と同じ鍵でのログインで、成功する必要があります。2つ目はssh -o PubkeyAuthentication=no [email protected]で、Permission denied (publickey)と表示されて拒否されれば正しい状態です。3つ目は[email protected]への接続で、これも拒否されることを確認します。最後に、鍵でログインしたセッションでsudo -vを実行し、管理者権限を使えることも確かめます。
失敗したときの戻し方
鍵でのログインが失敗した場合は、開いたままの作業用セッションで追加したファイルを削除し、設定を元に戻します。
sudo rm /etc/ssh/sshd_config.d/01-hardening.conf
sudo sshd -t && sudo systemctl reload ssh本体を編集した場合は、バックアップを戻します。
sudo cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshパスワードでログインできる状態に戻ったら、手順3の原因調査からやり直します。作業用セッションも切れてしまった場合は、クラウドやVPSのシリアルコンソール、データセンターのKVMなど、SSHを使わない経路でログインして同じ操作をします。こうした経路が用意されていないサーバーでは、作業の前に手段を確保してください。
作業後に決めておくこと
今後は秘密鍵が唯一のログイン手段になります。まず、鍵を失ったときの復旧経路を決めます。別の端末で作った2本目の公開鍵をauthorized_keysに登録しておくか、コンソール接続の手順を管理者間で共有してください。退職や端末の廃棄があったときは、該当する公開鍵の行をauthorized_keysから削除します。これを運用手順に組み込んでおくと、鍵の棚卸しが続けられます。OpenSSHの既知の脆弱性や推奨設定は時期によって変わります。執筆時点の内容を前提にせず、利用しているディストリビューションのセキュリティアドバイザリとOpenSSH公式のセキュリティ情報を定期的に確認してください。