PAM Pluggable Authentication Modules

PAM (Pluggable Authentication Modules) 包括的ガイド

目次

  1. はじめに
  2. PAM アーキテクチャ
  3. PAM モジュールタイプ
  4. PAM 制御フラグ
  5. /etc/pam.d/ 設定
  6. 主要な PAM モジュール
  7. パスワード複雑性要件
  8. アカウントロックアウトポリシー
  9. PAM による多要素認証
  10. 高度な PAM 設定例
  11. トラブルシューティング
  12. ベストプラクティス
  13. 参考文献

1. はじめに

PAM (Pluggable Authentication Modules) は、Linux/Unix システムにおける認証フレームワークである。アプリケーションと認証メカニズムを分離することにより、認証方法を柔軟に設定・変更できる。PAM を理解することは、Linux システムのセキュリティ管理において極めて重要である。

1.1 PAM の歴史と目的

PAM は1995年に Sun Microsystems によって提案された。その主な目的は以下の通りである。

目的説明
認証の標準化アプリケーションごとに異なる認証コードを排除
モジュール性認証メカニズムを独立したモジュールとして実装
柔軟性システム管理者が認証ポリシーを容易に変更可能
スタック可能複数の認証モジュールを組み合わせ可能

1.2 PAM の全体像

┌─────────────────────────────────────────────────────────┐
│                    アプリケーション                       │
│              (login, sshd, su, sudo, etc.)               │
└─────────────┬───────────────────────────────────────────┘
              │ PAM API
┌─────────────▼───────────────────────────────────────────┐
│                    PAM ライブラリ                         │
│                   (libpam.so)                             │
└─────────────┬───────────────────────────────────────────┘
              │ 設定ファイル参照
┌─────────────▼───────────────────────────────────────────┐
│              /etc/pam.d/ 設定ファイル                     │
│         (サービスごとの設定ファイル)                       │
└─────────────┬───────────────────────────────────────────┘
              │ モジュール呼び出し
┌─────────────▼───────────────────────────────────────────┐
│                   PAM モジュール                          │
│    (/usr/lib/x86_64-linux-gnu/security/ or               │
│     /usr/lib64/security/)                                │
│                                                          │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐   │
│  │pam_unix  │ │pam_ldap  │ │pam_sssd  │ │pam_google│   │
│  │          │ │          │ │          │ │_auth     │   │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘   │
└─────────────────────────────────────────────────────────┘

2. PAM アーキテクチャ

2.1 PAM の構成要素

PAM は以下の4つの主要コンポーネントから構成される。

PAM アーキテクチャ
├── PAM 対応アプリケーション
│   └── PAM API を使用して認証を要求
├── PAM ライブラリ (libpam)
│   └── アプリケーションとモジュール間の仲介
├── PAM 設定ファイル (/etc/pam.d/)
│   └── サービスごとの認証ポリシー定義
└── PAM モジュール (/usr/lib/security/)
    └── 実際の認証・認可処理を実装

2.2 PAM の処理フロー

ユーザー → アプリケーション → libpam → 設定ファイル読み込み
                                           │
                                           ▼
                              ┌─── auth モジュールスタック ───┐
                              │  pam_faillock.so (preauth)     │
                              │  pam_unix.so                   │
                              │  pam_faillock.so (authfail)    │
                              └────────────────────────────────┘
                                           │
                              ┌─── account モジュールスタック ─┐
                              │  pam_unix.so                   │
                              │  pam_access.so                 │
                              │  pam_time.so                   │
                              └────────────────────────────────┘
                                           │
                              ┌─── password モジュールスタック ┐
                              │  pam_pwquality.so              │
                              │  pam_unix.so                   │
                              └────────────────────────────────┘
                                           │
                              ┌─── session モジュールスタック ─┐
                              │  pam_limits.so                 │
                              │  pam_unix.so                   │
                              │  pam_motd.so                   │
                              │  pam_mkhomedir.so              │
                              └────────────────────────────────┘
                                           │
                                           ▼
                                    結果をアプリケーションに返却

2.3 PAM モジュールの配置場所

# モジュールの配置ディレクトリ確認
# RHEL/CentOS (64bit)
ls /usr/lib64/security/
# 出力例:
# pam_access.so    pam_faillock.so  pam_limits.so   pam_pwquality.so  pam_unix.so
# pam_console.so   pam_filter.so    pam_listfile.so pam_rhosts.so     pam_warn.so
# pam_cracklib.so  pam_ftp.so       pam_localuser.so pam_rootok.so    pam_wheel.so
# pam_deny.so      pam_group.so     pam_loginuid.so pam_securetty.so  pam_xauth.so
# pam_echo.so      pam_issue.so     pam_mkhomedir.so pam_selinux.so
# pam_env.so       pam_keyinit.so   pam_motd.so     pam_shells.so
# pam_exec.so      pam_lastlog.so   pam_namespace.so pam_succeed_if.so
# pam_faildelay.so pam_ldap.so      pam_nologin.so  pam_time.so

# Ubuntu/Debian (64bit)
ls /usr/lib/x86_64-linux-gnu/security/

# インストール済みPAMモジュールの確認
dpkg -l | grep libpam  # Debian/Ubuntu
rpm -qa | grep pam      # RHEL/CentOS

3. PAM モジュールタイプ

3.1 4つのモジュールタイプ

タイプ目的実行タイミング
authユーザーの本人確認 (認証)ログイン時、su/sudo 実行時
accountアカウントの有効性チェック (認可)認証成功後
passwordパスワードの変更処理passwd コマンド実行時
sessionセッションの設定/解放ログイン/ログアウト時

3.2 auth タイプ

ユーザーの身元を確認する。通常はパスワードの入力を求め、正しいかどうかを検証する。

# auth タイプの例
# /etc/pam.d/login
auth    required      pam_securetty.so        # root のログイン端末を制限
auth    required      pam_nologin.so          # /etc/nologin チェック
auth    required      pam_faillock.so preauth # ロックアウト前チェック
auth    sufficient    pam_unix.so nullok      # UNIX パスワード認証
auth    required      pam_faillock.so authfail # 認証失敗の記録
auth    required      pam_deny.so             # すべて拒否 (フォールバック)

3.3 account タイプ

認証されたユーザーがサービスにアクセスする権限があるかを確認する。

# account タイプの例
account required    pam_unix.so             # アカウントの有効期限チェック
account required    pam_access.so           # /etc/security/access.conf による制御
account required    pam_time.so             # 時間帯によるアクセス制御
account sufficient  pam_localuser.so        # ローカルユーザーのチェック
account required    pam_permit.so           # すべて許可

3.4 password タイプ

パスワードの変更に関する処理を制御する。

# password タイプの例
password requisite  pam_pwquality.so retry=3     # パスワード品質チェック
password sufficient pam_unix.so sha512 shadow \
    use_authtok remember=12                       # UNIX パスワード設定
password required   pam_deny.so                   # その他は拒否

3.5 session タイプ

ログインセッションの開始と終了に関する処理を制御する。

# session タイプの例
session required    pam_limits.so           # リソース制限の適用
session required    pam_unix.so             # セッション管理
session optional    pam_motd.so             # MOTD の表示
session optional    pam_mkhomedir.so        # ホームディレクトリの自動作成
session required    pam_loginuid.so         # 監査用 loginuid の設定
session optional    pam_keyinit.so force revoke  # カーネルキーリング
session optional    pam_env.so              # 環境変数の設定

4. PAM 制御フラグ

4.1 制御フラグ一覧

フラグ成功時失敗時説明
required処理続行処理続行(最終的に失敗)必須。失敗しても後続モジュールを実行
requisite処理続行即座に失敗を返却必須。失敗時は即座にアプリケーションに戻る
sufficient即座に成功を返却無視して処理続行成功時は後続モジュールをスキップ
optional結果を記録結果を記録他に判定がない場合のみ結果が使用される
include--別の設定ファイルを読み込む
substack--include と似るが、スタックのスコープが限定

4.2 制御フラグの動作フロー

required の動作:
  モジュール1 (required) → 成功 → モジュール2 (required) → 失敗 → モジュール3 (required) → 成功
  結果: 失敗 (モジュール2が失敗したため、最終結果は失敗)

requisite の動作:
  モジュール1 (requisite) → 成功 → モジュール2 (requisite) → 失敗 → [即座に失敗を返却]
  結果: 失敗 (モジュール2が失敗した時点で即座に失敗)

sufficient の動作:
  モジュール1 (sufficient) → 成功 → [即座に成功を返却]
  結果: 成功 (前の required が全て成功している場合)

  モジュール1 (sufficient) → 失敗 → モジュール2 (required) → 成功
  結果: 成功 (sufficient の失敗は無視される)

4.3 高度な制御構文

# 角括弧構文 (より細かい制御)
# [value1=action1 value2=action2 ...]

# 利用可能な値:
# success, open_err, symbol_err, service_err, system_err,
# buf_err, perm_denied, auth_err, cred_insufficient,
# authinfo_unavail, user_unknown, maxtries, new_authtok_reqd,
# acct_expired, session_err, cred_unavail, cred_expired,
# cred_err, no_module_data, conv_err, authtok_err,
# authtok_recover_err, authtok_lock_busy, authtok_disable_aging,
# try_again, ignore, abort, authtok_expired, module_unknown,
# bad_item, conv_again, incomplete, default

# 利用可能なアクション:
# ignore, bad, die, ok, done, N (スキップ数), reset

# 実際の例
auth [success=2 default=ignore] pam_unix.so nullok
auth [success=1 default=ignore] pam_ldap.so use_first_pass
auth requisite pam_deny.so
auth required pam_permit.so

# 上記の動作:
# 1. pam_unix.so が成功 → 2つ先 (pam_permit.so) へジャンプ
# 2. pam_unix.so が失敗 → pam_ldap.so を試行
# 3. pam_ldap.so が成功 → 1つ先 (pam_permit.so) へジャンプ
# 4. pam_ldap.so が失敗 → pam_deny.so で拒否

4.4 制御フラグと角括弧構文の対応

required   ≡ [success=ok new_authtok_reqd=ok ignore=ignore default=bad]
requisite  ≡ [success=ok new_authtok_reqd=ok ignore=ignore default=die]
sufficient ≡ [success=done new_authtok_reqd=done default=ignore]
optional   ≡ [success=ok new_authtok_reqd=ok default=ignore]

5. /etc/pam.d/ 設定

5.1 設定ファイル構造

# /etc/pam.d/ ディレクトリの内容確認
ls -la /etc/pam.d/
# 出力例:
# -rw-r--r-- 1 root root  384 Jan 10 2025 common-account
# -rw-r--r-- 1 root root  581 Jan 10 2025 common-auth
# -rw-r--r-- 1 root root  508 Jan 10 2025 common-password
# -rw-r--r-- 1 root root  622 Jan 10 2025 common-session
# -rw-r--r-- 1 root root  613 Jan 10 2025 common-session-noninteractive
# -rw-r--r-- 1 root root  170 Jan 10 2025 login
# -rw-r--r-- 1 root root   92 Jan 10 2025 other
# -rw-r--r-- 1 root root  143 Jan 10 2025 passwd
# -rw-r--r-- 1 root root  520 Jan 10 2025 sshd
# -rw-r--r-- 1 root root  232 Jan 10 2025 su
# -rw-r--r-- 1 root root  257 Jan 10 2025 sudo

# 設定ファイルのフォーマット:
# type  control  module-path  [module-arguments]

5.2 共通設定ファイル (Ubuntu/Debian)

# /etc/pam.d/common-auth
cat /etc/pam.d/common-auth
# 出力例:
# auth    [success=1 default=ignore]  pam_unix.so nullok
# auth    requisite                   pam_deny.so
# auth    required                    pam_permit.so
# auth    optional                    pam_cap.so

# /etc/pam.d/common-account
cat /etc/pam.d/common-account
# 出力例:
# account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
# account requisite pam_deny.so
# account required  pam_permit.so

# /etc/pam.d/common-password
cat /etc/pam.d/common-password
# 出力例:
# password requisite pam_pwquality.so retry=3
# password [success=1 default=ignore] pam_unix.so obscure use_authtok \
#     try_first_pass sha512 remember=5
# password requisite pam_deny.so
# password required  pam_permit.so

# /etc/pam.d/common-session
cat /etc/pam.d/common-session
# 出力例:
# session [default=1] pam_permit.so
# session requisite   pam_deny.so
# session required    pam_permit.so
# session optional    pam_umask.so
# session required    pam_unix.so
# session optional    pam_systemd.so

5.3 サービス別設定ファイル (RHEL/CentOS)

# /etc/pam.d/system-auth (RHEL/CentOS)
cat /etc/pam.d/system-auth
# auth        required                                     pam_env.so
# auth        required                                     pam_faildelay.so delay=2000000
# auth        required                                     pam_faillock.so preauth silent deny=5 unlock_time=900
# auth        sufficient                                   pam_unix.so nullok
# auth        [default=die]                                pam_faillock.so authfail deny=5 unlock_time=900
# auth        sufficient                                   pam_faillock.so authsucc deny=5 unlock_time=900
# auth        required                                     pam_deny.so
#
# account     required                                     pam_unix.so
# account     sufficient                                   pam_localuser.so
# account     sufficient                                   pam_succeed_if.so uid < 1000 quiet
# account     required                                     pam_permit.so
#
# password    requisite                                    pam_pwquality.so retry=3
# password    sufficient                                   pam_unix.so sha512 shadow nullok use_authtok remember=5
# password    required                                     pam_deny.so
#
# session     optional                                     pam_keyinit.so revoke
# session     required                                     pam_limits.so
# session     [success=1 default=ignore]                   pam_succeed_if.so service in crond quiet use_uid
# session     required                                     pam_unix.so

# /etc/pam.d/sshd
cat /etc/pam.d/sshd
# auth       substack     password-auth
# auth       include      postlogin
# account    required     pam_sepermit.so
# account    required     pam_nologin.so
# account    include      password-auth
# password   include      password-auth
# session    required     pam_selinux.so close
# session    required     pam_loginuid.so
# session    required     pam_selinux.so open env_params
# session    required     pam_namespace.so
# session    optional     pam_keyinit.so force revoke
# session    optional     pam_motd.so
# session    include      password-auth
# session    include      postlogin

6. 主要な PAM モジュール

6.1 pam_unix - 標準 UNIX 認証

# pam_unix は最も基本的な認証モジュール
# /etc/passwd, /etc/shadow を使用

# 主なオプション:
# nullok        - 空パスワードを許可
# shadow        - /etc/shadow を使用
# sha512        - SHA-512 ハッシュ
# remember=N    - N 個のパスワード履歴を保存
# use_authtok   - 前のモジュールが設定したトークンを使用
# try_first_pass - 前のモジュールのパスワードを先に試す

# 設定例
auth      sufficient  pam_unix.so nullok try_first_pass
account   required    pam_unix.so
password  sufficient  pam_unix.so sha512 shadow nullok use_authtok remember=12
session   required    pam_unix.so

6.2 pam_ldap - LDAP 認証

# LDAP サーバーに対して認証を行う

# インストール
apt install libpam-ldap     # Ubuntu/Debian
dnf install nss-pam-ldapd   # RHEL/CentOS

# /etc/pam.d/common-auth (LDAP統合)
auth    [success=2 default=ignore]  pam_unix.so nullok
auth    [success=1 default=ignore]  pam_ldap.so use_first_pass
auth    requisite                   pam_deny.so
auth    required                    pam_permit.so

# /etc/pam.d/common-account (LDAP統合)
account [success=2 new_authtok_reqd=done default=ignore]  pam_unix.so
account [success=1 default=ignore]                         pam_ldap.so
account requisite                                          pam_deny.so
account required                                           pam_permit.so

# LDAP設定 (/etc/ldap.conf or /etc/pam_ldap.conf)
# uri ldap://ldap.example.com
# base dc=example,dc=com
# ldap_version 3
# pam_password md5
# pam_filter objectclass=posixAccount
# pam_login_attribute uid
# pam_member_attribute memberUid

6.3 pam_sssd - SSSD 認証

# SSSD (System Security Services Daemon) による統合認証
# LDAP, Active Directory, FreeIPA に対応

# インストール
apt install sssd sssd-ldap     # Ubuntu/Debian
dnf install sssd sssd-ldap     # RHEL/CentOS

# /etc/sssd/sssd.conf
cat > /etc/sssd/sssd.conf << 'EOF'
[sssd]
config_file_version = 2
services = nss, pam
domains = example.com

[domain/example.com]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldaps://ldap.example.com
ldap_search_base = dc=example,dc=com
ldap_id_use_start_tls = True
ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt
cache_credentials = True
offline_credentials_expiration = 7

[nss]
filter_groups = root
filter_users = root

[pam]
offline_credentials_expiration = 7
offline_failed_login_attempts = 3
offline_failed_login_delay = 5
EOF

chmod 600 /etc/sssd/sssd.conf

# PAM 設定
# /etc/pam.d/common-auth (SSSD統合)
auth    [success=2 default=ignore]  pam_unix.so nullok
auth    [success=1 default=ignore]  pam_sss.so use_first_pass
auth    requisite                   pam_deny.so
auth    required                    pam_permit.so

# SSSD の起動
systemctl enable --now sssd

6.4 pam_faillock - アカウントロックアウト

# pam_faillock はログイン失敗のカウントとロックアウトを管理
# (pam_tally2 の後継)

# /etc/security/faillock.conf
cat > /etc/security/faillock.conf << 'EOF'
deny = 5
unlock_time = 900
fail_interval = 900
even_deny_root
root_unlock_time = 60
dir = /var/run/faillock
audit
EOF

# PAM 設定
auth    required    pam_faillock.so preauth
auth    [success=1 default=ignore] pam_unix.so nullok
auth    [default=die] pam_faillock.so authfail
auth    sufficient  pam_faillock.so authsucc
auth    requisite   pam_deny.so
auth    required    pam_permit.so

account required    pam_faillock.so

# ロックアウト管理コマンド
faillock --user username          # 状態確認
faillock --user username --reset  # リセット
faillock                          # 全ユーザー表示

6.5 pam_pwquality - パスワード品質

# パスワードの複雑性を強制する

# /etc/security/pwquality.conf
minlen = 14
minclass = 3
ucredit = -1
lcredit = -1
dcredit = -1
ocredit = -1
difok = 8
maxrepeat = 3
maxclassrepeat = 4
usercheck = 1
dictcheck = 1
enforcecheck = 1
retry = 3
enforce_for_root

# PAM 設定
password requisite pam_pwquality.so retry=3
password sufficient pam_unix.so sha512 shadow use_authtok remember=12

6.6 pam_limits - リソース制限

# ユーザーやグループに対するリソース制限を設定

# /etc/security/limits.conf
# <domain>  <type>  <item>  <value>
#
# domain: ユーザー名, @グループ名, * (全員)
# type: soft (変更可能な制限), hard (上限)
# item: core, data, fsize, memlock, nofile, nproc, stack, cpu, etc.

cat > /etc/security/limits.d/99-hardening.conf << 'EOF'
# コアダンプの無効化
*               hard    core            0

# ファイルディスクリプタ制限
*               soft    nofile          4096
*               hard    nofile          65536

# プロセス数制限
*               soft    nproc           4096
*               hard    nproc           16384

# メモリロック制限
*               soft    memlock         65536
*               hard    memlock         65536

# 特定グループの制限
@developers     soft    nofile          8192
@developers     hard    nofile          131072

# 特定ユーザーの制限
admin           soft    nproc           unlimited
admin           hard    nproc           unlimited
EOF

# 現在の制限確認
ulimit -a
# 出力例:
# core file size          (blocks, -c) 0
# data seg size           (kbytes, -d) unlimited
# file size               (blocks, -f) unlimited
# max locked memory       (kbytes, -l) 65536
# max memory size         (kbytes, -m) unlimited
# open files                      (-n) 4096
# pipe size            (512 bytes, -p) 8
# stack size              (kbytes, -s) 8192
# cpu time               (seconds, -t) unlimited
# max user processes              (-u) 4096
# virtual memory          (kbytes, -v) unlimited

# PAM 設定
session required pam_limits.so

6.7 pam_access - アクセス制御

# ユーザー/グループに対してログイン元に基づくアクセス制御

# /etc/security/access.conf
# フォーマット: permission : users/groups : origins
# permission: + (許可) or - (拒否)
# origins: ホスト名, IPアドレス, ネットワーク, tty, ALL, LOCAL

cat > /etc/security/access.conf << 'EOF'
# root はコンソールからのみログイン可能
+ : root : LOCAL

# 管理者グループは管理ネットワークからのみ
+ : @admins : 10.0.0.0/24
+ : @admins : LOCAL

# 開発者グループは社内ネットワークから
+ : @developers : 192.168.0.0/16
+ : @developers : LOCAL

# その他のユーザーは全て拒否
- : ALL : ALL
EOF

# PAM 設定
account required pam_access.so

6.8 pam_time - 時間帯制御

# 時間帯に基づくアクセス制御

# /etc/security/time.conf
# フォーマット: services;ttys;users;times
# services: サービス名 (login, sshd, etc.)
# ttys: 端末名 (* = all)
# users: ユーザー名/グループ名 (!で否定)
# times: 日時指定

cat > /etc/security/time.conf << 'EOF'
# 月曜〜金曜の9:00〜18:00のみSSHログインを許可
sshd;*;@developers;Wk0900-1800

# root は常に許可
sshd;*;root;Al0000-2400

# 週末はメンテナンスグループのみ
sshd;*;@maintenance;Wd0000-2400

# すべてのサービスについて、一般ユーザーは営業時間のみ
*;*;!root;Wk0800-2000
EOF

# 時間指定の形式:
# Mo Tu We Th Fr Sa Su - 個別の曜日
# Wk - 平日 (月〜金)
# Wd - 週末 (土日)
# Al - すべて
# HHMM-HHMM - 時間範囲

# PAM 設定
account required pam_time.so

6.9 pam_motd - ログインメッセージ

# ログイン時にメッセージを表示

# 静的 MOTD
cat > /etc/motd << 'EOF'
Authorized access only.
All activity is monitored and logged.
EOF

# 動的 MOTD スクリプト
# /etc/update-motd.d/ ディレクトリ内のスクリプトが順番に実行される
cat > /etc/update-motd.d/10-system-info << 'SCRIPT'
#!/bin/bash
echo "========================================"
echo "  Hostname: $(hostname)"
echo "  Date:     $(date)"
echo "  Uptime:   $(uptime -p)"
echo "  Load:     $(cat /proc/loadavg | awk '{print $1, $2, $3}')"
echo "  Memory:   $(free -h | grep Mem | awk '{print $3"/"$2}')"
echo "  Disk:     $(df -h / | tail -1 | awk '{print $3"/"$2" ("$5")"}')"
echo "========================================"
SCRIPT
chmod +x /etc/update-motd.d/10-system-info

# PAM 設定
session optional pam_motd.so motd=/run/motd.dynamic
session optional pam_motd.so noupdate

6.10 pam_env - 環境変数設定

# ログイン時に環境変数を設定

# /etc/security/pam_env.conf
# フォーマット: VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]]

cat > /etc/security/pam_env.conf << 'EOF'
# 基本環境変数
EDITOR    DEFAULT=vim
VISUAL    DEFAULT=vim
PAGER     DEFAULT=less

# ロケール設定
LANG      DEFAULT=en_US.UTF-8
LC_ALL    DEFAULT=en_US.UTF-8

# PATH の追加
PATH      DEFAULT=${PATH}:/usr/local/bin

# カスタム環境変数
COMPANY_ENV DEFAULT=production
EOF

# /etc/environment (システム全体の環境変数)
cat > /etc/environment << 'EOF'
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
LANG="en_US.UTF-8"
EOF

# PAM 設定
session required pam_env.so readenv=1
session required pam_env.so readenv=1 envfile=/etc/default/locale

6.11 pam_mkhomedir - ホームディレクトリ自動作成

# LDAP/SSSD ユーザーのホームディレクトリを自動作成

# PAM 設定
session required pam_mkhomedir.so skel=/etc/skel umask=0027

# オプション:
# skel=DIR    - スケルトンディレクトリ (テンプレート)
# umask=MASK  - 作成時の umask

# スケルトンディレクトリの内容確認
ls -la /etc/skel/
# 出力例:
# -rw-r--r-- 1 root root  220 Jan  6  2022 .bash_logout
# -rw-r--r-- 1 root root 3771 Jan  6  2022 .bashrc
# -rw-r--r-- 1 root root  807 Jan  6  2022 .profile

# カスタムスケルトンの作成
mkdir -p /etc/skel/.ssh
chmod 700 /etc/skel/.ssh
cat > /etc/skel/.bashrc << 'EOF'
# Custom bashrc for new users
export EDITOR=vim
alias ll='ls -la'
EOF

6.12 pam_tally2 - ログイン試行カウント (レガシー)

# 注意: pam_tally2 は非推奨。pam_faillock を使用すること。
# RHEL 8+ / Ubuntu 22.04+ では pam_faillock が推奨

# レガシー設定 (参考)
auth     required  pam_tally2.so deny=5 onerr=fail unlock_time=900 \
    even_deny_root root_unlock_time=60
account  required  pam_tally2.so

# カウンターの確認
pam_tally2 --user=username
# 出力例:
# Login    Failures Latest failure     From
# username     3    01/15/25 14:30:22  192.168.1.100

# カウンターのリセット
pam_tally2 --user=username --reset

7. パスワード複雑性要件

7.1 pam_pwquality の詳細設定

# /etc/security/pwquality.conf の全パラメータ

cat > /etc/security/pwquality.conf << 'EOF'
# === 文字要件 ===

# 最小パスワード長
minlen = 14

# 最小文字クラス数 (大文字、小文字、数字、記号)
minclass = 3

# 各文字クラスの最小数 (負の値 = 必須数)
ucredit = -1    # 大文字: 最低1文字
lcredit = -1    # 小文字: 最低1文字
dcredit = -1    # 数字: 最低1文字
ocredit = -1    # 記号: 最低1文字

# === 品質チェック ===

# 旧パスワードとの差分文字数
difok = 8

# ユーザー名チェック (パスワードにユーザー名を含まないか)
usercheck = 1

# GECOS フィールドチェック (ユーザーのフルネーム等)
gecoscheck = 1

# 辞書チェック (cracklib辞書)
dictcheck = 1

# === 繰り返し制限 ===

# 連続する同一文字の最大数
maxrepeat = 3

# 連続する同一クラスの最大数
maxclassrepeat = 4

# 回文チェック
palindrome = 1

# === その他 ===

# 不正パスワード入力の再試行回数
retry = 3

# root にもポリシーを強制
enforce_for_root

# 拒否されたパスワードについてのメッセージ
badwords = password company admin root

# ローカルユーザーの辞書ファイル
# dictpath = /usr/share/dict/words
EOF

7.2 パスワード複雑性テスト

# pwscore コマンドでパスワード強度をテスト
echo "MyP@ssw0rd123!" | pwscore
# 出力: 82

echo "password" | pwscore
# 出力: (エラーメッセージ)
# Password quality check failed:
#  The password fails the dictionary check - it is based on a dictionary word

# cracklib-check でのテスト
echo "testpassword" | cracklib-check
# 出力: testpassword: it is based on a dictionary word

echo "X9#kL2mN@pQ4" | cracklib-check
# 出力: X9#kL2mN@pQ4: OK

8. アカウントロックアウトポリシー

8.1 包括的なロックアウト設定

# === /etc/security/faillock.conf ===
cat > /etc/security/faillock.conf << 'EOF'
# 5回の失敗でロックアウト
deny = 5

# 15分後に自動アンロック (0=手動のみ)
unlock_time = 900

# 15分以内の失敗をカウント
fail_interval = 900

# root もロックアウト対象
even_deny_root

# root のアンロック時間 (短めに設定)
root_unlock_time = 60

# 監査ログの記録
audit

# サイレントモード (セキュリティ上推奨)
silent

# ロックアウトデータの保存先
dir = /var/run/faillock
EOF

# === PAM 設定 (auth スタック) ===
# /etc/pam.d/system-auth or /etc/pam.d/common-auth

# preauth: 認証前にロックアウト状態をチェック
auth    required                        pam_faillock.so preauth

# 通常の認証
auth    [success=1 default=ignore]      pam_unix.so nullok

# authfail: 認証失敗時にカウント
auth    [default=die]                   pam_faillock.so authfail

# authsucc: 認証成功時にカウンターリセット
auth    sufficient                      pam_faillock.so authsucc

auth    requisite                       pam_deny.so
auth    required                        pam_permit.so

# === PAM 設定 (account スタック) ===
account required                        pam_faillock.so
account required                        pam_unix.so

8.2 ロックアウト管理

# ユーザーのロックアウト情報を表示
faillock --user john
# 出力例:
# john:
# When                Type  Source                           Valid
# 2025-01-15 10:00:01 RHOST 192.168.1.100                   V
# 2025-01-15 10:00:05 RHOST 192.168.1.100                   V
# 2025-01-15 10:00:09 RHOST 192.168.1.100                   V
# 2025-01-15 10:00:13 RHOST 192.168.1.100                   V
# 2025-01-15 10:00:17 RHOST 192.168.1.100                   V

# ロックアウトの解除
faillock --user john --reset

# 全ユーザーのロックアウト状態を確認
faillock

# ロックアウト監視スクリプト
cat > /usr/local/bin/check-lockouts.sh << 'SCRIPT'
#!/bin/bash
LOCKED_USERS=$(faillock 2>/dev/null | grep -B1 "V$" | grep ":" | cut -d: -f1 | sort -u)

if [ -n "$LOCKED_USERS" ]; then
    echo "=== Locked Out Users ==="
    for user in $LOCKED_USERS; do
        COUNT=$(faillock --user "$user" 2>/dev/null | grep "V$" | wc -l)
        echo "  $user: $COUNT failed attempts"
    done
fi
SCRIPT
chmod +x /usr/local/bin/check-lockouts.sh

9. PAM による多要素認証

9.1 Google Authenticator (TOTP)

# Google Authenticator PAM モジュールのインストール
apt install libpam-google-authenticator  # Ubuntu/Debian
dnf install google-authenticator         # RHEL/CentOS (EPEL必要)

# ユーザーごとの初期設定
google-authenticator
# 対話形式で以下を設定:
# - 時間ベース (TOTP) トークンを使用するか? → y
# - QRコードが表示される (Google Authenticator アプリでスキャン)
# - 緊急バックアップコードが生成される
# - .google_authenticator ファイルの更新を許可? → y
# - 同一トークンの複数使用を禁止? → y
# - 時間ずれの許容? → y (1分程度)
# - レート制限を有効化? → y

# PAM 設定 (/etc/pam.d/sshd)
# SSH鍵認証 + TOTP の二要素認証
auth    required    pam_google_authenticator.so nullok

# SSH 設定 (/etc/ssh/sshd_config)
# ChallengeResponseAuthentication yes
# AuthenticationMethods publickey,keyboard-interactive
# KbdInteractiveAuthentication yes

# sshd の再起動
systemctl restart sshd

# テスト接続
ssh -o PubkeyAuthentication=yes user@server
# パスワード入力後にワンタイムパスワードが求められる

9.2 YubiKey による認証

# YubiKey PAM モジュールのインストール
apt install libpam-yubico  # Ubuntu/Debian
dnf install pam_yubico     # RHEL/CentOS

# PAM 設定
auth required pam_yubico.so id=<API_CLIENT_ID> key=<API_SECRET_KEY> \
    authfile=/etc/yubikey_mappings

# ユーザーとYubiKeyのマッピング
cat > /etc/yubikey_mappings << 'EOF'
admin:ccccccxxxxx1
john:ccccccxxxxx2:ccccccxxxxx3
EOF

9.3 FIDO2/U2F による認証

# pam-u2f のインストール
apt install libpam-u2f  # Ubuntu/Debian

# U2F キーの登録
mkdir -p ~/.config/Yubico
pamu2fcfg > ~/.config/Yubico/u2f_keys

# 追加のキー登録
pamu2fcfg -n >> ~/.config/Yubico/u2f_keys

# PAM 設定
auth required pam_u2f.so authfile=/etc/u2f_mappings cue nouserok

# システム全体のマッピングファイル
# /etc/u2f_mappings
# username:key_handle,public_key,...

10. 高度な PAM 設定例

10.1 LDAP + TOTP の多要素認証

# /etc/pam.d/sshd (LDAP + Google Authenticator)
auth    required                        pam_env.so
auth    required                        pam_faillock.so preauth silent
auth    [success=2 default=ignore]      pam_unix.so nullok
auth    [success=1 default=ignore]      pam_sss.so use_first_pass
auth    requisite                       pam_deny.so
auth    [default=die]                   pam_faillock.so authfail
auth    sufficient                      pam_faillock.so authsucc
auth    required                        pam_google_authenticator.so

account required    pam_faillock.so
account required    pam_unix.so
account sufficient  pam_sss.so
account required    pam_permit.so

password requisite  pam_pwquality.so retry=3
password sufficient pam_unix.so sha512 shadow use_authtok remember=12
password sufficient pam_sss.so use_authtok
password required   pam_deny.so

session required    pam_limits.so
session required    pam_unix.so
session optional    pam_sss.so
session optional    pam_mkhomedir.so skel=/etc/skel umask=0077
session optional    pam_motd.so

10.2 時間帯とネットワークに基づくアクセス制御

# /etc/pam.d/sshd (時間帯 + ネットワーク制限)
auth    required    pam_env.so
auth    required    pam_faillock.so preauth
auth    sufficient  pam_unix.so nullok
auth    [default=die] pam_faillock.so authfail
auth    sufficient  pam_faillock.so authsucc
auth    required    pam_deny.so

account required    pam_faillock.so
account required    pam_unix.so
account required    pam_access.so     # ネットワーク制限
account required    pam_time.so       # 時間帯制限

# /etc/security/access.conf
+ : @admins : ALL
+ : @developers : 10.0.0.0/8
+ : @operators : 10.0.0.0/8 172.16.0.0/12
- : ALL : ALL

# /etc/security/time.conf
sshd;*;@developers;Wk0800-2000
sshd;*;@admins;Al0000-2400

10.3 グループベースの sudo 設定

# /etc/pam.d/sudo
auth    required    pam_env.so
auth    required    pam_faillock.so preauth
auth    sufficient  pam_unix.so
auth    [default=die] pam_faillock.so authfail
auth    sufficient  pam_faillock.so authsucc
auth    required    pam_deny.so

# wheel グループのみ sudo を許可
auth    required    pam_wheel.so use_uid

account required    pam_unix.so
account required    pam_faillock.so

session required    pam_limits.so
session required    pam_unix.so
session required    pam_env.so

11. トラブルシューティング

11.1 PAM デバッグの有効化

# モジュールレベルのデバッグ
# 各モジュールに debug オプションを追加
auth required pam_unix.so debug
auth required pam_faillock.so preauth debug

# syslog でデバッグメッセージを確認
tail -f /var/log/auth.log    # Ubuntu/Debian
tail -f /var/log/secure      # RHEL/CentOS

# journalctl での確認
journalctl -f -u sshd
journalctl -f _COMM=sshd

11.2 一般的な問題と解決策

問題原因解決策
ログインできないPAM 設定エラーシングルユーザーモードで /etc/pam.d/ を確認
パスワード変更できないpwquality 要件未満pwscore でテスト、要件を確認
LDAP ユーザーがログインできないSSSD/LDAP 接続エラーsystemctl status sssd、ログを確認
ロックアウトが解除されないfaillock 設定faillock --user USER --reset
ホームディレクトリが作成されないpam_mkhomedir 未設定session に pam_mkhomedir.so を追加
MFA が動作しないSSH 設定の不整合AuthenticationMethods を確認
権限エラーSELinuxaudit2allow で原因を調査

11.3 PAM 設定のテスト方法

# pamtester を使用したテスト
apt install pamtester  # Ubuntu/Debian

# 認証テスト
pamtester login username authenticate
# パスワード入力を求められる

# アカウントチェック
pamtester login username acct_mgmt

# セッションテスト
pamtester login username open_session
pamtester login username close_session

# 常にバックアップを保持する
cp -a /etc/pam.d /etc/pam.d.backup

# 緊急時の復旧
# 1. シングルユーザーモードで起動
# 2. /etc/pam.d/ をバックアップから復元
# 3. または /etc/pam.d/other を最小設定にする

cat > /etc/pam.d/other << 'EOF'
auth     required  pam_unix.so
account  required  pam_unix.so
password required  pam_unix.so
session  required  pam_unix.so
EOF

11.4 PAM 設定の検証スクリプト

#!/bin/bash
# pam-check.sh - PAM設定の健全性チェック

echo "=== PAM Configuration Health Check ==="

# 1. 設定ファイルの構文チェック
echo ""
echo "--- Syntax Check ---"
for f in /etc/pam.d/*; do
    while IFS= read -r line; do
        # コメントと空行をスキップ
        [[ "$line" =~ ^[[:space:]]*# ]] && continue
        [[ -z "$line" ]] && continue

        # 基本的な構文チェック
        if ! echo "$line" | grep -qP '^(auth|account|password|session)\s+(required|requisite|sufficient|optional|include|substack|\[)'; then
            echo "  WARNING: $f: Invalid line: $line"
        fi
    done < "$f"
done
echo "  Syntax check complete."

# 2. モジュールの存在確認
echo ""
echo "--- Module Existence Check ---"
for f in /etc/pam.d/*; do
    grep -oP '/\S+\.so' "$f" 2>/dev/null | while read -r mod; do
        if [ ! -f "$mod" ]; then
            echo "  MISSING: $f references $mod (not found)"
        fi
    done
done

# 3. セキュリティ設定の確認
echo ""
echo "--- Security Settings Check ---"

# faillock の確認
if grep -rq "pam_faillock" /etc/pam.d/; then
    echo "  [OK] pam_faillock is configured"
else
    echo "  [WARN] pam_faillock is NOT configured"
fi

# pwquality の確認
if grep -rq "pam_pwquality" /etc/pam.d/; then
    echo "  [OK] pam_pwquality is configured"
else
    echo "  [WARN] pam_pwquality is NOT configured"
fi

# pam_wheel の確認 (sudo)
if grep -q "pam_wheel" /etc/pam.d/su 2>/dev/null; then
    echo "  [OK] pam_wheel is configured for su"
else
    echo "  [WARN] pam_wheel is NOT configured for su"
fi

echo ""
echo "=== Check Complete ==="

12. ベストプラクティス

12.1 PAM 設定のベストプラクティス

項目推奨事項優先度
バックアップ変更前に必ず /etc/pam.d/ のバックアップを取得最高
テスト設定変更は別セッションを維持したまま実施最高
ロックアウトpam_faillock で5回以内のロックアウトを設定
パスワード品質pam_pwquality で14文字以上・3クラス以上を要求
パスワード履歴remember=12 で過去12個のパスワード再利用を防止
アクセス制御pam_access でネットワークベースの制限を実装
リソース制限pam_limits で適切なリソース制限を設定
MFAGoogle Authenticator 等で多要素認証を実装
ログデバッグログを必要時に有効化できるよう準備
監査PAM 設定の定期的な監査を実施

12.2 セキュリティチェックリスト

# PAM セキュリティ監査チェックリスト

# 1. パスワードポリシーの確認
grep -r "pam_pwquality" /etc/pam.d/
cat /etc/security/pwquality.conf

# 2. ロックアウトポリシーの確認
grep -r "pam_faillock" /etc/pam.d/
cat /etc/security/faillock.conf

# 3. パスワード履歴の確認
grep "remember=" /etc/pam.d/* 2>/dev/null

# 4. root ログイン制限の確認
grep "pam_securetty" /etc/pam.d/login 2>/dev/null
grep "pam_wheel" /etc/pam.d/su 2>/dev/null

# 5. アクセス制御の確認
grep "pam_access" /etc/pam.d/* 2>/dev/null
cat /etc/security/access.conf

# 6. null パスワードの確認
grep "nullok" /etc/pam.d/* 2>/dev/null

# 7. パーミッションの確認
ls -la /etc/pam.d/
# すべて root:root 所有、644 であること

12.3 緊急時の復旧手順

# PAM 設定の破損によりログイン不能になった場合

# 方法1: シングルユーザーモード
# GRUB メニューで 'e' を押してカーネルパラメータに 'single' を追加
# バックアップから復元:
cp -a /etc/pam.d.backup/* /etc/pam.d/

# 方法2: Live CD/USB からの復旧
mount /dev/sda1 /mnt
cp -a /mnt/etc/pam.d.backup/* /mnt/etc/pam.d/
umount /mnt

# 方法3: 最小限の PAM 設定に戻す
for service in login sshd su sudo; do
    cat > /etc/pam.d/$service << 'EOF'
auth     required  pam_unix.so
account  required  pam_unix.so
password required  pam_unix.so
session  required  pam_unix.so
EOF
done

13. 参考文献

  1. The Linux-PAM System Administrators' Guide - http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_SAG.html
  2. The Linux-PAM Module Writers' Guide - http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_MWG.html
  3. The Linux-PAM Application Developers' Guide - http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_ADG.html
  4. Red Hat - Configuring PAM - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/configuring_authentication_and_authorization_in_rhel/configuring-pam
  5. Ubuntu PAM Configuration - https://ubuntu.com/server/docs/security-pam
  6. pam_faillock(8) man page - https://man7.org/linux/man-pages/man8/pam_faillock.8.html
  7. pam_pwquality(8) man page - https://man7.org/linux/man-pages/man8/pam_pwquality.8.html
  8. pam_unix(8) man page - https://man7.org/linux/man-pages/man8/pam_unix.8.html
  9. SSSD Documentation - https://sssd.io/docs/introduction.html
  10. Google Authenticator PAM - https://github.com/google/google-authenticator-libpam
  11. CIS Benchmarks - PAM Section - https://www.cisecurity.org/cis-benchmarks

本ドキュメントは PAM (Pluggable Authentication Modules) について包括的にまとめたものである。PAM 設定の変更は慎重に行い、必ずバックアップを取得してからテストすること。設定ミスはシステムへのログインを不可能にする可能性がある。