sshdのハードニング
目標
drop-in設定ファイルでsshdをハードニングし、sshd -tとsshd -Tで検証したあと、鍵での接続は維持され、パスワード認証は拒否されるかを、実際に確認します。
なぜ重要なのか
リモートサーバーのsshdを変更することは、乗っている木の枝を切ることです。そのため、順序が決まっています: セッションを維持 → 修正 → sshd -t → リロード → 新しいセッションで確認 → そのあとに既存のセッションを終了。そして、最近のディストリビューションは、Include /etc/ssh/sshd_config.d/*.confで設定を分割します。同じキーが複数回現れると最初の値が勝つので、「変更したのに効かない」がよくあります。sshd -Tで最終的な適用値を確認する習慣が、この問題を根本から断ちます。\n\n## このラボは仮想マシンで動きます\n\nsshdが実際のsystemdサービスとして動いているので、systemctl reload sshで設定を読み直させ、新しいセッションで接続して確認できます。以前はPodで動いていてsystemctlがなく、pkill sshdでプロセスを直接扱う必要がありました。\n\n環境を構築するときに、1つを事前に処理しておきました。Ubuntu 24.04ではssh.socketが有効で、その状態では、待ち受けるポートをsystemdが決めます。sshd_configのPortは無視されます。設定を変更して再起動しても、ポート22でしか待ち受けず、エラーも警告も出ません。ラボ用のポート2222を開くために、ソケットアクティベーションを無効にして、ssh.serviceを有効にしてあります。実際のサーバーで「ポートを変えたのに開かない」に出会ったら、まずここを見てください。\n\nポート22はそのままにしておきます。設定を間違えて書いても、戻れる道を残しておくためです。実際のサーバーでも、同じ理由で、新しいポートを先に開いて確認してから、古いポートを閉じます。
ステップ
/root/hardenディレクトリを作成し、現在の有効な設定の全体を/root/harden/baseline.txtに保存してください。/etc/ssh/sshd_config.d/90-labhub.confを作成し、次の値を入れてください。PasswordAuthentication no、KbdInteractiveAuthentication no、PubkeyAuthentication yes、MaxAuthTries 3、LoginGraceTime 30、X11Forwarding no、PermitEmptyPasswords no、LogLevel VERBOSE- 構文検査を実行して合格することを確認し、終了コードを
/root/harden/syntax.txtにrc=0の形式で書いてください。 - 最終的な適用値のうち、
passwordauthentication、kbdinteractiveauthentication、maxauthtries、logingracetimeの4行だけを選んで、/root/harden/effective.txtに保存してください。 - 同じファイルの末尾に
Match User backupブロックを追加して、ForceCommand internal-sftpとAllowTcpForwarding noを入れてください。そして、その条件での有効な設定を/root/harden/match.txtに保存してください。ファイルにforcecommand internal-sftpが表示される必要があります。 /root/.ssh/authorized_keysで、id_labhubの鍵が入っている行の先頭に、restrict,pty,from="127.0.0.0/8"オプションを付けてください。(ptyを再び有効にしないと、シェル接続が維持されません。)- sshdを再び起動したあと、次の2つを確認してください。
- 鍵での接続が引き続き成功する → 結果を
/root/harden/still-works.txtに保存 - パスワード認証だけを要求すると拒否される → そのエラー出力を
/root/harden/password-denied.txtに保存
- 鍵での接続が引き続き成功する → 結果を
/root/harden/checklist.txtを次の5行で作成してください。値はsshd -Tの出力が基準です。passwordauthentication=no/kbdinteractiveauthentication=no/pubkeyauthentication=yes/maxauthtries=3/logingracetime=30
参考
sshd -tは構文検査、sshd -Tは有効な設定の出力、sshd -T -C user=backup,host=x,addr=127.0.0.1は条件付きの有効な設定です。- sshdの再起動は、
pkill -x sshd; sleep 1; /usr/sbin/sshdの形で行います。ラボ環境のsshdは、ポート2222の設定をすでに持っています。 - パスワード認証の拒否の確認は、
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -p 2222 root@127.0.0.1 trueで行います。失敗メッセージを保存してください。 - よくある間違い1: ステップ6で
restrictだけを付けて、ptyを再び有効にしないために、シェル接続が壊れる場合です。 - よくある間違い2: ステップ7で、sshdを停止するだけで再び起動しないために、以降のステップがすべて失敗する場合です。
現在の有効な設定の記録
/root/hardenディレクトリを作成し、現在の有効な設定の全体を/root/harden/baseline.txtに保存してください。
sshdには、最終的な適用値をすべて出力する拡張テストモードがあります。構文検査とは別のオプションです。
drop-in設定の作成
/etc/ssh/sshd_config.d/90-labhub.confを作成し、次の値を入れてください。
PasswordAuthentication no、KbdInteractiveAuthentication no、PubkeyAuthentication yes、MaxAuthTries 3、LoginGraceTime 30、X11Forwarding no、PermitEmptyPasswords no、LogLevel VERBOSE
sshd_config.dの下に、.confファイルとして作成します。ファイル名の先頭の数字が、読み込む順序を決めます。
構文検査に合格
構文検査を実行して合格することを確認し、終了コードを/root/harden/syntax.txtにrc=0の形式で書いてください。
構文だけを検査するオプションは、成功すると何も出力しません。終了コードで判断してください。
適用値の確認
最終的な適用値のうち、passwordauthentication、kbdinteractiveauthentication、maxauthtries、logingracetimeの4行だけを選んで、/root/harden/effective.txtに保存してください。
拡張テストモードの出力は、すべて小文字のキーです。必要な4つだけを選び出してください。
Matchブロックの条件付き適用
同じファイルの末尾にMatch User backupブロックを追加して、ForceCommand internal-sftpとAllowTcpForwarding noを入れてください。そして、その条件での有効な設定を/root/harden/match.txtに保存してください。ファイルにforcecommand internal-sftpが表示される必要があります。
拡張テストモードに接続条件を渡すオプションがあります。user、host、addrの3つの値をカンマでつないで書きます。
authorized_keysのオプション強化
/root/.ssh/authorized_keysで、id_labhubの鍵が入っている行の先頭に、restrict,pty,from="127.0.0.0/8"オプションを付けてください。(ptyを再び有効にしないと、シェル接続が維持されません。)
接続元を制限するオプションと、すべての機能をオフにするオプションを、一緒に使います。ループバックのアドレス帯を許可しないと、接続が維持されません。
先に確認すること: このステップは、~/.ssh/id_labhubの鍵を扱います。その鍵は前のラボ(SSH鍵認証)で作成したものですが、ラボごとに新しい環境が起動するので、ここにはありません。ls ~/.sshで確認して、なければ先に作成してください。
ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_labhub
cat ~/.ssh/id_labhub.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
再起動後の実際の検証
sshdを再び起動したあと、次の2つを確認してください。
- 鍵での接続が引き続き成功する → 結果を
/root/harden/still-works.txtに保存 - パスワード認証だけを要求すると拒否される → そのエラー出力を
/root/harden/password-denied.txtに保存
設定を反映するには、sshdを再び起動する必要があります。この環境にはsystemctlがないので、プロセスを直接扱ってください。
ハードニングのチェックリスト
/root/harden/checklist.txtを次の5行で作成してください。値はsshd -Tの出力が基準です。
passwordauthentication=no / kbdinteractiveauthentication=no / pubkeyauthentication=yes / maxauthtries=3 / logingracetime=30
値は、sshd -Tの出力からそのまま持ってくればよいです。小文字に統一してください。