Linuxセキュリティの基盤となるフレームワーク
Linuxのターミナルでパスワードを入力したり、sudoコマンドを実行したりする際、対話しているのは単一のアプリケーションだけではありません。実際には、Pluggable Authentication Modules(PAM)と呼ばれる仕組みを介しています。PAMは、認証ロジックを集約するエンジンのようなものです。SSHやFTPなどの各サービスが個別にパスワードチェックのコードを書く代わりに、PAMのモジュールライブラリにそのタスクを委託しています。
私はこれまで数多くのLinuxインスタンスを管理してきましたが、身をもって学んだ教訓があります。それは「PAMは強力であると同時に、非常に危険である」ということです。設定ファイルの文字を一つ打ち間違えるだけで、rootユーザーを含むすべてのユーザーがシステムからロックアウトされる可能性があります。このガイドでは、PAMの仕組みを解き明かし、カスタムセキュリティポリシーを安全に実装する方法を解説します。
クイックスタート:現在の設定を確認する
セキュリティスタックを変更する前に、ルールがどこに記述されているかを知る必要があります。PAMの設定ファイルはすべて /etc/pam.d/ に配置されています。通常、これらのファイルは制御対象のサービス名が付けられています。
現在どのアプリケーションがPAMを使用しているかを確認するには、次のコマンドを実行します。
ls /etc/pam.d/
よく使われるファイルには sshd、sudo、common-auth などがあります。SSHがログインをどのように処理しているかを確認するには、その設定ファイルを調べてみましょう。
cat /etc/pam.d/sshd
標準的なPAMのエントリは次のようになります。
auth required pam_unix.so shadow nodelay
構文は [タイプ] [コントロール] [モジュールパス] [引数] という厳格な4つのパターンに従います。この4つの列の意味を理解すれば、システム全体の見通しが良くなります。
アーキテクチャ:PAMはどのように判断を下すのか
コアとなるアクセス制御を効果的にカスタマイズするには、4つの管理グループと、成否を左右するロジックフラグを理解する必要があります。
4つの管理グループ
- auth: 本人確認を行います。通常、パスワードの入力を求めたり、暗号鍵を検証したりします。
- account: ユーザーが現在システムへのアクセスを許可されているかを確認します。アカウントの期限切れや、制限時間外のログイン試行などをチェックします。
- password: 認証情報の更新を処理します。パスワードの複雑さ(数字や記号の混在など)を強制したり、
/etc/shadowファイルを更新したりします。 - session: 環境をセットアップします。ホームディレクトリのマウント、環境変数の設定、セッション時間のログ記録などのタスクを処理します。
コントロールフラグ:ロジックの定義
コントロールフラグは、モジュールが成功または失敗したときにPAMが何を行うかを決定します。設定ミスの多くはここで発生します。
- required: モジュールの成功が必須です。失敗した場合でも、ユーザーにはすぐには通知されず、PAMはスタック内の他のモジュールを実行し続けます。これにより、どこで失敗したかを推測されにくくします。
- requisite: これも必須条件ですが、失敗した瞬間にPAMは即座に認証を中止し、試行を拒否します。
- sufficient: このモジュールが成功し、かつそれ以前の「required」モジュールで失敗がなければ、残りのスタックをチェックせずに即座にアクセスを許可します。
- optional: スタック内の他のモジュールで明確な合否が決まらない場合にのみ、結果に影響を与えます。
実践的なセキュリティポリシー
理論だけでなく、PAMを使えばわずか数行のコードで現実のセキュリティ課題を解決できます。影響の大きい2つの設定を見てみましょう。
1. pam_faillockによるブルートフォース攻撃の無効化
自動化されたスクリプトは常にSSHポートを狙っています。pam_faillock を使用すると、連続して失敗したアカウントを一時的に無効化できます。Ubuntu 22.04やAlmaLinux 9などの最新システムでは、/etc/pam.d/common-auth または system-auth の認証スタックを変更します。
# 5回の試行失敗後、15分間アカウントをロックする
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
account required pam_faillock.so
この例では、unlock_time=900 によって15分間の冷却期間が設定されます。このシンプルな変更だけで、自動化されたブルートフォース攻撃のコスト対効果を大幅に下げることができます。
2. pam_timeによる勤務時間の強制
勤務時間中にのみアクセスを許可すべき機密性の高いワークステーションを管理している場合、pam_time.so が最適なツールです。まず、/etc/pam.d/login にモジュールを追加します。
account required pam_time.so
次に、/etc/security/time.conf で制約を定義します。
login;*;developer;MoTuWeThFr0900-1700
このルールは、「developer」ユーザーのログインを平日の午前9時から午後5時までに制限します。この時間枠外の試行は、アカウント管理グループ(account)によって拒否されます。
安全第一:ロックアウトを回避する
PAMの変更は非常にリスクが高い作業です。もし common-auth を壊してしまうと、sudo が使えなくなり、壊したファイルを修正することさえできなくなるかもしれません。安全を確保するための方法を以下に示します。
アクティブセッション・ルール
PAMファイルを編集している間は、絶対に現在のSSHウィンドウを閉じないでください。保存する前に、別のターミナルを開いて、別のユーザーとしてログインを試みるか、sudo -v を実行してください。もし設定ミスでシステムが壊れていても、元のセッションがroot権限で開いたままなら、すぐにファイルを元に戻せます。私はこのルールを無視したために、リカバリコンソールで何時間も過ごす羽目になったことがあります。同じ間違いをしないでください。
pamtesterによるシミュレーション
ルールが機能するかどうかを推測する必要はありません。pamtester ユーティリティをインストールすれば、ログイン試行を安全にシミュレートできます。例えば:
pamtester sshd web-admin authenticate
このコマンドは、実際にログアウト・ログインを繰り返すことなく、ユーザー「web-admin」がSSH認証スタックを通過できるかどうかをテストします。
ログをリアルタイムで監視する
PAMの失敗は詳細に記録されます。テスト中は別のウィンドウでセキュリティログを tail -f で監視しましょう。Debian/Ubuntuでは /var/log/auth.log を、RHEL系システムでは /var/log/secure を確認します。これらのログは、どのモジュールがアクセスを拒否しているかを正確に示してくれるため、推測に頼る必要がなくなります。
まとめ
PAMは、Linux環境全体のセキュリティを管理するための柔軟で統一された手段を提供します。4つの管理グループをマスターし、コントロールフラグの仕組みを理解することで、MFAや時間ベース of アクセス制限といったエンタープライズグレードのセキュリティを実装できます。緊急用のターミナルを常に開いておくこと、そしてログを頼りにデバッグを行うことを忘れないでください。

