SSHサーバーのセキュリティ強化:rootログインの無効化と公開鍵認証の設定方法

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

問題の本質:あなたのSSHサーバーは今この瞬間も狙われている

サーバーのポート22がインターネットに開放されているなら、すでにスキャンされています。「かもしれない」ではなく、今まさに起きていることです。公開されているLinuxサーバーで次のコマンドを実行してみてください:

sudo journalctl -u ssh --since "1 hour ago" | grep "Failed password" | wc -l

おそらく数十件、場合によっては数百件のログイン失敗が確認できるはずです。ボットは常にインターネット上のSSHポートをスキャンし、認証情報を総当たりで試し続けています。こうした攻撃を助長する最大の脆弱性は2つ——SSH経由でのrootログインを許可していること、そして暗号鍵の代わりにパスワード認証に頼っていることです。

パスワードはブルートフォースで破られる可能性があります。rootアカウントが乗っ取られれば、攻撃者は追加の手順なしにマシンを完全に掌握できます。この2つが重なると、簡単に侵害できるサーバーの出来上がりです。

根本原因:デフォルトのSSH設定がなぜ危険なのか

rootログインは最高権限アカウントを危険にさらす

ほとんどのLinuxディストリビューションは、デフォルトでrootのSSHログインを許可しています(少なくとも明示的にはブロックしていません)。rootログインが許可されている場合、攻撃者に必要なのはパスワード一つだけです。権限昇格のステップは不要——一度の成功で全てを掌握されてしまいます。

代わりにsudo権限を持つ一般ユーザーに切り替えましょう。これにより第二の防衛層が加わります。攻撃者がユーザーの認証情報を入手しても、実際の被害を与えるにはさらにsudoパスワードが必要になります。

パスワード認証は推測される可能性がある

強固なパスワードでも、十分な時間と計算リソースがあれば解読できます。SSHの公開鍵認証は非対称暗号を使用します——秘密鍵はあなたのマシンに、公開鍵はサーバーに置きます。秘密鍵ファイルがなければ、どれだけ計算能力があってもログインは数学的に不可能です。

私の本番Ubuntu 22.04サーバーでは、その差は明確に計測できました。公開鍵認証に切り替える前、サーバーは毎時200〜400件のパスワード認証失敗を処理していました。各試行はSSHハンドシェイクと鍵導出処理を発生させ、実際のCPU負荷となっていました。パスワード認証を完全に無効化した後、そのバックグラウンドノイズは消えました。

実践:SSHサーバーを段階的に強化する

ステップ1:sudo権限を持つ非rootユーザーを作成する

rootログインを無効化する前に、別のアクセス手段を確保してください。一般ユーザーがいない場合は作成します:

# サーバー上で実行
sudo adduser deployuser
sudo usermod -aG sudo deployuser

次のステップに進む前に、そのユーザーがsudoを使えることを確認してください:

su - deployuser
sudo whoami
# 出力されるはず: root

ステップ2:ローカルマシンでSSH鍵ペアを生成する

この操作はサーバーではなく、ローカルのワークステーションで行います:

ssh-keygen -t ed25519 -C "deployuser@myserver" -f ~/.ssh/myserver_ed25519

RSAよりもed25519を使用してください——高速で、鍵が短く(RSA-4096の700文字以上に対して68文字)、かつ同等のセキュリティを持ちます。-Cフラグは鍵を識別するコメントを追加します。パスフレーズを求められたら設定しましょう。これにより秘密鍵ファイルがローカルで暗号化されるため、たとえラップトップを盗まれても、パスフレーズなしでは鍵は使えません。

この操作で2つのファイルが生成されます:

  • ~/.ssh/myserver_ed25519 — 秘密鍵(絶対に共有しないこと)
  • ~/.ssh/myserver_ed25519.pub — 公開鍵(これをサーバーに置く)

ステップ3:公開鍵をサーバーにコピーする

最も簡単な方法:

ssh-copy-id -i ~/.ssh/myserver_ed25519.pub deployuser@your-server-ip

ssh-copy-idが使えない場合(macOSやWindowsでは一般的)、手動で行います:

# サーバー上でdeployuserとしてログインした状態で実行
mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# このファイルに公開鍵の内容を貼り付ける
nano ~/.ssh/authorized_keys

パスワード認証を無効化する前に、公開鍵でのログインが機能することを確認してください:

ssh -i ~/.ssh/myserver_ed25519 deployuser@your-server-ip

パスワードを求められずに(鍵のパスフレーズは除く)ログインできれば、次のステップに進んでも大丈夫です。

ステップ4:SSHの設定でrootログインとパスワード認証を無効化する

SSHデーモンの設定ファイルを編集します:

sudo nano /etc/ssh/sshd_config

以下のディレクティブを見つけて更新します(存在しない場合は追加):

# rootログインを完全に無効化
PermitRootLogin no

# パスワード認証を無効化
PasswordAuthentication no

# 空のパスワードを無効化
PermitEmptyPasswords no

# 特定のユーザーのみ許可(任意だが推奨)
AllowUsers deployuser

# チャレンジレスポンス認証を無効化(PAMのキーボードインタラクティブを含む)
# OpenSSH 8.7以降はKbdInteractiveAuthenticationに名称変更 — 安全のため両方設定
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no

# 切断された接続を検出するためのキープアライブ設定
ClientAliveInterval 300
ClientAliveCountMax 2

Ubuntu 22.04以降では注意が必要です。sshd_config.d/ディレクトリにオーバーライドファイルがないか確認してください:

ls /etc/ssh/sshd_config.d/
cat /etc/ssh/sshd_config.d/*.conf 2>/dev/null

Ubuntu 22.04には/etc/ssh/sshd_config.d/50-cloud-init.confが同梱されており、PasswordAuthentication yesを再有効化します。上書きするか削除してください:

sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config.d/50-cloud-init.conf
# その行だけが含まれているなら削除してもよい
# sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf

ステップ5:設定を検証してSSHをリロードする

リロード前に必ず設定をテストしてください——構文エラーがあるとロックアウトされる可能性があります:

sudo sshd -t
# 出力なし = エラーなし

sudo systemctl reload ssh
# ディストリビューションによっては: sudo systemctl reload sshd

現在のSSHセッションは開いたままにしてください。新しいターミナルウィンドウを開いてログインをテストします:

ssh -i ~/.ssh/myserver_ed25519 deployuser@your-server-ip

パスワードログインが拒否されることも確認してください:

ssh deployuser@your-server-ip
# すぐに表示されるはず: Permission denied (publickey)

ステップ6:任意——デフォルトのSSHポートを変更する

ポート22を変更しても実質的なセキュリティ向上にはなりませんが、ログのノイズを劇的に減らす効果があります。ボットは主にポート22をスキャンするため、非標準ポートに移すと自動化された攻撃を私の経験では90%以上削減できます:

# /etc/ssh/sshd_config に記述
Port 2222

UFWを使用している場合:

sudo ufw allow 2222/tcp
sudo ufw delete allow ssh  # ポート22のルールを削除
sudo ufw status

カスタムポートで接続する:

ssh -p 2222 -i ~/.ssh/myserver_ed25519 deployuser@your-server-ip

毎回ポートを入力しなくて済むよう、ローカルの~/.ssh/configにエントリを追加します:

Host myserver
    HostName your-server-ip
    User deployuser
    Port 2222
    IdentityFile ~/.ssh/myserver_ed25519

これでssh myserverだけで接続できるようになります。

ステップ7:変更が反映されたことを確認する

実行中のSSH設定を確認します:

sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|port'

期待される出力:

port 2222
permitRootLogin no
passwordauthentication no

認証ログを確認して、ブルートフォース試行がパスワード段階ではなく鍵の段階で拒否されていることを確認します:

sudo tail -f /var/log/auth.log | grep sshd

ボーナス:複数のSSH鍵をすっきり管理する

複数のサーバーを管理する場合、鍵を整理しておくと混乱を防げます:

# ~/.ssh/config
Host production
    HostName 203.0.113.10
    User deployuser
    Port 2222
    IdentityFile ~/.ssh/prod_ed25519

Host staging
    HostName 203.0.113.20
    User deployuser
    Port 22
    IdentityFile ~/.ssh/staging_ed25519

設定ファイルのパーミッションを正しく設定します:

chmod 600 ~/.ssh/config

達成できたこと

完了です。SSHサーバーへのアクセスには暗号鍵が必要になりました。パスワードへのブルートフォース攻撃はもう通用しません。rootログインはブロックされ、万が一ユーザーアカウントが侵害されても被害を最小限に抑えられます。ポートも変更すれば、自動スキャンのノイズを90%以上削減できます。

この3つのステップ——専用の非rootユーザー、公開鍵認証、パスワードログインの禁止——でSSHの主要な攻撃面をカバーできます。可能であれば既知のIPアドレス範囲にSSHアクセスを制限するファイアウォールルールも追加すると、デフォルト設定と比べてサーバーのセキュリティは格段に向上します。

最後に一点:秘密鍵のバックアップを安全な場所に保管してください。バックアップなしで鍵を紛失すると、ロックアウトされてしまいます。パスワードマネージャーのセキュアノートや暗号化されたUSBドライブが有効な選択肢です。

Share: