運用・保守 一覧へ戻る トップ運用・保守 / SELinuxの構造
セキュリティ ・ SELinux

SELinuxの構造

OSの最深部・カーネル空間で動作するセキュリティ機構SELinux(Security-Enhanced Linux)の内部構造、動作原理、そしてゼロトラスト多層防御環境における役割を体系的に学習する教材です

全12章 Type Enforcement / AVC / Domain Transition 最終防衛線としての強制アクセス制御

本ページの位置づけ

SELinuxの内部構造(なぜそう動くのか)を解説する教材です。実務での設定・トラブルシューティング手順は「SELinuxの運用管理」をご参照ください。

目次

  1. 第1章:マクロ構造とゼロトラストにおける位置づけ
  2. 第2章:セキュリティコンテキストの徹底解剖
  3. 第3章:ミクロ構造(Type Enforcement)
  4. 第4章:LSMフレームワークとVFS連携
  5. 第5章:Domain Transition(ドメイン遷移)
  6. 第6章:setroubleshootの解析メカニズム
  7. 第7章:実務運用における解決プロセスの優先順位
  8. 第8章:ファイル操作とラベル崩れの挙動原理
  9. 第9章:ファイアウォール連携と多層防御
  10. 第10章:ゼロトラスト全体のデータ処理パイプライン
  11. 第11章:各セキュリティレイヤー比較マトリクス
  12. 第12章:ゼロトラスト原則とSELinuxの機能マッピング

第1章:マクロ構造 ── SELinuxの根本定義とゼロトラストにおける位置づけ

SELinuxは、単に「外部からの不正アクセスを防ぐネットワーク防御壁」ではありません。プロセスがOSに対して発行するすべての「システムコール」を対象に、カーネルレベルで一律にアクセス制御を行うシステムです。

そのため、ネットワーク経由かローカル実行かを問わず、OS上で動作するすべてのプロセスが評価対象となります。ネットワーク上の防衛線を突破した攻撃や、内部ユーザーによる不正操作(特権昇格など)が発生した場合の「最終防衛線」として機能します。

1-1. 防御レイヤーシステム図

システム内の各セキュリティレイヤーと、OS内部(Kernel空間)においてDACおよびSELinux(MAC)が実行される正確な防衛ラインを示した構造図です。

[ インターネット (外部アクセス) ]
       │
       ▼
┌────────────────────┐
│ FortiGate (境界FW)  │ ◀── [第1の壁] L3/L4 ネットワーク境界での遮断
└────────────────────┘
       │ L7トラフィック (Caddyリバースプロキシ宛)
       ▼
┌────────────────────┐
│ Firewalld (ホストFW) │ ◀── [第2の壁] サービスポート(80/443)の管理
│ (バックエンド: nftables) │
└────────────────────┘
       │
       ▼
┌────────────────────┐
│ Caddy / Apache (httpd) │ ◀── [第3の壁] Webサーバープロセス実行
└────────────────────┘
       │
 ───┼─────【 ユーザー空間 (User Space) 】─────────
       │ システムコール要求 (例: open)
 ───┼─────【 カーネル空間 (Kernel Space) 】─────────
       │
       ▼
┌────────────────────┐
│ 標準カーネル (DAC)   │ ◀── [第4の壁] 任意アクセス制御 (Linux標準の所有権・rwx管理)
└────────────────────┘  ※ここでアクセスが拒否された場合、処理は即座に終了する
       │
       ▼ (DAC通過後、LSMフックにより呼び出し)
┌────────────────────┐
│ SELinux (MAC)        │ ◀── [最終防衛線] 強制アクセス制御
│ (カーネル・ポリシーエンジン) │  ※Webサーバープロセスが脆弱性によりUID=0へ
└────────────────────┘  特権昇格したとしても、通常はSELinuxドメイン(httpd_t)は
       │                維持され、ポリシーの制約を受け続ける
       ├─ (許可: Allow) ───▶ [ ターゲットリソース (ファイル / ポート / プロセス) ]
       │
       └─ (拒否: Deny) ────▶ [ 監査ログ (audit.log) ] ──▶ [ setroubleshoot / sealert ]

第2章:セキュリティコンテキスト(Security Context)の徹底解剖

SELinuxがすべてのアクセス制御を判断する際の基準となるのが、ファイル、プロセス、ネットワークポート等に付与されたセキュリティコンテキスト(ラベル)です。

2-1. コンテキストの構成要素

セキュリティコンテキストは、コロン(:)で区切られた4つの要素(MLS無効環境では3つ)で構成されます。

system_u : object_r : httpd_sys_content_t : s0
  │           │              │              │
  │           │              │              └─ MLS/MCSレンジ (情報の機密区分)
  │           │              └─ タイプ(Type) ※プロセスは「ドメイン」と呼ぶ
  │           └─ ロール(Role) ※ファイルは「object_r」固定
  └─ SELinuxユーザー(User) ※Linuxのユーザー(UID)とは独立して管理
要素説明
ユーザー(User)SELinux独自のユーザー定義。OSのユーザーとはマッピングによって紐づけられます(例:system_u(システム用)、unconfined_u(制限なしユーザー))。
ロール(Role)ユーザーが実行できるドメインの範囲を規定(例:system_r(システムサービス用))。ファイルなどの不活性リソースはすべてobject_r(オブジェクト用)に固定されます。
タイプ(Type / Domain)SELinux制御の最重要要素。プロセスに対するラベルは「ドメイン」、ファイルやリソースに対するラベルは「タイプ」と呼ばれます。
レベル(Sensitivity / MLS)マルチレベルセキュリティ(MLS)などで使用される機密レベル(例:s0)。

2-2. 実機でのコンテキスト確認方法

実機(Rocky Linux等)のターミナルでコンテキストを確認する際には、各種コマンドに-Zオプションを付与します。

① プロセスのセキュリティコンテキスト確認

ps -eZ | grep httpd

# 出力例:
system_u:system_r:httpd_t:s0 1234 ? 00:00:00 httpd
# ※Apacheプロセスがhttpd_tドメインで実行されていることがわかります

② ファイルのセキュリティコンテキスト確認

ls -Z /var/www/html/index.html

# 出力例:
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
# ※ファイルがApacheから読み込み可能なhttpd_sys_content_tタイプであることを示します

③ ログイン中のカレントユーザーのコンテキスト確認

id -Z

# 出力例:
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# ※管理者が制限のないunconfined_tドメインでシェルを実行している状態を示します

第3章:ミクロ構造 ── Type Enforcementとポリシーの記述文法

SELinuxポリシーは、どのドメインがどのターゲットタイプに対して、どのような操作を許可されるかを定義したルールの集合体です。

3-1. allowルールの基本構成

ポリシー定義ファイルの基本文法は以下の構造を持ちます。

allow   httpd_t   httpd_sys_content_t : file   { read getattr open };
  │        │              │              │           │
  │        │              │              │           └─ 許可される具体的なアクション
  │        │              │              └─ オブジェクトの分類 (file, dir, socket等)
  │        │              └─ アクセス対象のタイプ (Type)
  │        └─ アクセスを試みるプロセスのドメイン (Domain)
  └─ 許可を宣言するキー

3-2. ポリシーのビルドとカーネルロードの流れ

記述されたテキスト形式のポリシーソース(.te)が、実際にカーネルのポリシーデータベースに読み込まれるまでのパイプラインです。

[ ポリシーソースファイル (.te) ]
      │
      ▼ コンパイル (checkmodule -M -m -o policy.mod policy.te)
[ ポリシーモジュールバイナリ (.mod) ]
      │
      ▼ パッケージ化 (semodule_package -o policy.pp -m policy.mod)
[ ポリシーパッケージ (.pp) ]
      │
      ▼ カーネルへロード (semodule -i policy.pp)
【 カーネルポリシーデータベース (Active Kernel Policy Store) 】

第4章:LSM(Linux Security Module)フレームワークとVFS連携

SELinuxは、カーネルに直接独自のコードを埋め込んでいるわけではありません。Linuxの標準的な仮想ファイルシステムであるVFS(Virtual File System)およびセキュリティフレームワークLSM(Linux Security Module)のフックを経由して呼び出されます。

4-1. VFSを介したシステムコールのインターセプト構造

プロセスがopen()システムコールを実行してから、実際に物理ストレージにアクセスされるまでのカーネル内部フローです。

[ ユーザー空間 ]  Application (例: Webサーバー)
                     │
                     ▼ システムコール呼び出し: open("/etc/shadow")
───────────┼────────────────────────────────
[ カーネル空間 ]  VFS (Virtual File System)
                     │
                     ├─▶ 1. カーネル標準のDACチェック (所有権・rwxの検証)
                     │     └─ [ 拒否 ] ──▶ 即座にエラー返却 (-EACCES)
                     ▼ [ 許可 ]
              2. LSMフック(例: security_file_open)の呼び出し
                     │
                     ▼ 判定委譲
              ┌─────────────────────────────────┐
              │ SELinux LSMモジュール             │
              │   ├─▶ [ AVC (Access Vector Cache) ] 5つ組検索 │
              │   │     ├─ [ キャッシュあり ] ──▶ 判定結果返却 │
              │   │     └─ [ キャッシュなし ] ──▶ ポリシー検索 │
              │   ▼                              │
              │  判定: httpd_t から shadow_t への open は拒否 │
              └─────────────────────────────────┘
                     │
                     ▼ LSMフック返却値: -EACCES
              VFS処理を中断し、物理ファイルシステムへのアクセスを阻止

4-2. AVC(Access Vector Cache)の詳細キャッシュ構造

SELinuxのポリシーエンジンは、アクセスの判定結果を効率的にキャッシュするため、以下の「5つ組(5-tuple)」をキーとしてAVCに保管します。

# キャッシュエントリの具体例
[ httpd_t , httpd_sys_content_t , file , read ] ⟹ ALLOW
[ httpd_t , shadow_t              , file , read ] ⟹ DENY

構造上のメリット

システムコール要求が発生すると、LSMフック経由でこの5つ組キーが瞬時にAVC内から検索されます。この仕組みにより、システムコールごとに重いポリシー検索を行うことなく、最小限のCPUサイクルでポリシー評価が完了します。

第5章:Domain Transition(ドメイン遷移)の機構

プロセスがプログラムを実行した際、新しい制限(ドメイン)に切り替わる仕組みをDomain Transition(ドメイン遷移)と呼びます。

5-1. fork()およびexecve()によるドメイン遷移の処理フロー

ドメイン遷移は通常の実行中には発生せず、新しくバイナリを呼び出すexecve()システムコールが発行された瞬間にのみ評価されます。

【 親プロセスドメイン 】(例: init_t)
        │
        ▼ fork() システムコール実行
【 子プロセス (親と同一ドメイン) 】(init_t のままコピー)
        │
        ▼ execve("/usr/sbin/httpd") システムコール実行
        ├─ 1. ファイルオブジェクト(httpd_exec_t)の「execute」権限をチェック
        ├─ 2. 新ドメイン(httpd_t)の「entrypoint」権限をチェック
        └─ 3. ポリシー上の「type_transition」ルールの有無を検証
        │
        ▼ 全ての整合性が取れた場合のみ、ドメインが切り替わる
【 遷移後のプロセスドメイン 】(例: httpd_t)

脚注

ドメイン遷移は、ポリシーに定義されたentrypointとtype_transitionによってのみ発生します。

第6章:トラブルシューティング・ツール「setroubleshoot」の解析メカニズム

SELinuxの拒否ログ(/var/log/audit/audit.log)に記録される「AVC拒否」情報から、システム管理者が具体的な解決手順を導き出すまでの連携構造です。

6-1. ログ解析および翻訳の内部フロー

[ カーネル内でアクセス拒否 (AVC Deny) が発生 ]
             │
             ▼
[ /var/log/audit/audit.log に未加工の監査ログが出力 ]
             │
             ▼
【 setroubleshootd (ログ監視デーモン) 】
  ・監査ログをリアルタイムで検知・解析
  ・解決パターンと照合し、ハッシュID(UUID)を生成
             │
             ▼
[ /var/log/messages に簡易的なエラーガイダンスを出力 ]
  (表示例: "SELinux is preventing ... To solve this, run: sealert -l [UUID]")
             │
             ▼
【 管理者が sealert コマンドを実行 】
  sudo sealert -a /var/log/audit/audit.log
  または sealert -l [UUID]
             │
             ▼
【 ターミナル上に人間が判読可能な解決策とコマンドを出力 】

第7章:実務運用における解決プロセスの優先順位

実務においてアクセス拒否が発生した場合、安易にポリシー生成ツールであるaudit2allowを使用してアクセス制限を緩和することは推奨されません。管理者は、以下の「トラブルシューティングの優先順位」に沿って、最も安全な解決策を選択します。

7-1. トラブルシューティング優先順位

STEP 1:ラベルの修復(restorecon)

💡 原因:ファイル操作などで一時的にファイルラベルが狂っただけではないか?
🔧 対処:標準データベースに登録された適切なラベルに修復する。(解決しない場合は次のステップへ)

STEP 2:Boolean(機能スイッチ)の調整(setsebool)

💡 原因:OSがあらかじめ用意している「許可スイッチ」がオフなだけではないか?
🔧 対処:Booleanの設定を変更して機能を開放する。(解決しない場合は次のステップへ)

STEP 3:標準ラベル定義の修正(semanage fcontext)

💡 原因:標準と異なる独自のディレクトリ構成でファイルを運用していないか?
🔧 対処:OSのデータベースに自環境用のラベルルールを永続登録する。(解決しない場合は次のステップへ)

STEP 4:カスタムポリシーの生成(audit2allow)※最終手段

💡 原因:独自開発のプログラムなど、OSの標準データベースにないアクセス挙動が必要か?
🔧 対処:必要最小限のアクセス許可ルールをプロファイル化して適用する。

7-2. 実例:Postfixのルートディレクトリ書き込み拒否

実務における設計判断

誤った解決策(ステップ4の安易な適用)

audit2allowを用いて、Postfixに対して/rootへの書き込み許可(ポリシー緩和)を与える。
結果:メールサービスが侵害された際、特権領域が直接攻撃対象となるためセキュリティ境界が崩壊します。

正しい解決策(アプリケーションの再設計)

/etc/aliasesを設定し、root宛てのメールを一般ユーザーの領域(/home/admin/...)へ転送する。
結果:SELinuxのセキュリティ境界を強固に保ったまま、通常のポリシー範囲内でメールを配送可能にします。

⚠️ audit2allow利用時の重要な警告

audit2allowは「監査ログから拒否された動作を抽出し、それをそのまま許可するルールに変換するだけの機械的な補助ツール」に過ぎません。生成されたルールがシステム全体の最小権限の原則(Least Privilege)を脅かさないか、あるいはより上位の解決策(ディレクトリ配置の変更やエイリアスの設定など)で代替できないかは、必ずシステム管理者自身が論理的に判断する必要があります。

第8章:実務におけるファイル操作とラベル崩れの挙動原理(restorecon)

OS上でファイルを移動(mv)またはコピー(cp)した際、SELinuxのコンテキストがどのように扱われ、どのように「ラベル崩れ」が発生するかを解説します。

8-1. ファイル操作コマンドごとのコンテキスト挙動と注意点

操作コマンド挙動の特徴セキュリティコンテキスト(ラベル)の挙動
mv(同一ファイルシステム内)メタデータ(inode)の書き換えのみ。ソース(移動元)のラベルをそのまま保持する。※移動先のディレクトリポリシーとの不一致が発生しやすい(要restorecon)。
mv(異なるファイルシステム間)実データのコピーと元の削除(cp + rm)が発生。宛先(移動先)ディレクトリの標準コンテキストを自動的に継承。
cp宛先にファイルを新しく作成し、データを書き込む。宛先(移動先)ディレクトリの標準コンテキストを自動的に継承。
tar複数のファイルをアーカイブにまとめる。通常利用では保存されない。※アーカイブ時に--selinuxオプションを付与することで、展開先へのラベル復元が可能。
rsyncディレクトリ間、またはサーバー間でファイルを同期する。通常利用では保存されない。※バックアップ時などラベルを維持する場合は、実務的に-aX(または-aHAX)オプションを使用する。

8-2. ラベル修復(restorecon)の仕組み

mvなどによってディレクトリの規定ルールと異なるラベルが付着してしまった場合に、OSがどのように整合性を修復するかのプロセスです。

【 不適切なラベルが維持されたファイル 】(例: 同一ファイルシステム内のmvで持ってきたためラベル不一致)
             │
             ▼
【 restorecon -v /var/www/html/index.html を実行 】
             │
             ▼
【 libselinuxを介してfile_contextsデータベースを横断検索 】
  ※file_contexts, file_contexts.local, semanage追加分などを統合的に検索
             │
             ▼
【 ファイルのコンテキストを正しいラベルへ上書き修復 (httpd_sys_content_t) 】

第9章:ファイアウォール連携と多層防御における協調

Fail2banがパケットを遮断する際のコマンド制御の流れ、およびSELinuxとの多層防御における役割の違いを解説します。

9-1. Fail2banのコマンド処理シーケンス

Fail2banは単独でパケットを破棄するのではなく、OS標準のユーティリティを介してカーネルのパケットフィルタを制御します。

【 Fail2ban (ログ検知) 】
        │
        ▼ (連携命令)
【 firewall-cmd 】 (管理コマンドの呼び出し)
        │
        ▼ (ポリシー反映)
【 Firewalld 】 (ファイアウォールサービス)
        │
        ▼ (ルール転送)
【 nftables 】 (カーネル制御バックエンド)
        │
        ▼ (パケット破棄)
【 Kernel packet filter (カーネル空間) 】

SELinuxとの役割の違い

Fail2ban・Firewalld・nftablesが守るのは「ネットワークに到達するパケット」です。一方SELinuxが守るのは「そのパケットが正規のアプリケーションに届いた後の、OS内部でのシステムコール」であり、防御対象のレイヤーが根本的に異なります。詳細は第11章:各セキュリティレイヤー比較マトリクスを参照してください。

第10章:ゼロトラスト全体のデータ処理パイプライン

外部から要求されたアクセスパケットが各防衛ラインを通過し、OS内のストレージ(ファイルシステム)へ書き込まれるか遮断されるか、その全プロセスを示した統合パイプライン図です。SELinuxは、VFS層でのDAC判定を通過した後にLSMフックにより評価を行います。

[ インターネット (外部アクセス要求) ]
       │
       ▼ (1. 境界ネットワーク防御)
┌──────────────────────────────────────┐
│ FortiGate (境界ファイアウォール)         │ ◀── L3/L4レベルのパケットフィルタリング
└──────────────────────────────────────┘
       │
       ▼ (2. ホストネットワーク防御)
┌──────────────────────────────────────┐
│ Firewalld / nftables (Fail2ban連携)   │ ◀── 攻撃検知時のIPアドレス高速遮断
└──────────────────────────────────────┘
       │
       ▼ (3. アプリケーションゲートウェイ)
┌──────────────────────────────────────┐
│ Caddy / Apache (httpd)                │ ◀── Web通信(HTTPS)の終端および、
└──────────────────────────────────────┘     Authentikによる多要素認証の検証
       │
       ▼ [ 認証成功 / 通常アクセス ]
┌──────────────────────────────────────┐
│ Application (プロセス実行)             │ ◀── ユーザー空間でのアプリ動作
└──────────────────────────────────────┘
       │
       ▼ (4. OS内部での命令発行)
┌──────────────────────────────────────┐
│ System Call (システムコール要求)        │ ◀── open()やwrite()などの命令発行
└──────────────────────────────────────┘
       │
       ▼ (5. 仮想ファイルシステムによる抽象化)
┌──────────────────────────────────────┐
│ VFS (Virtual File System)             │ ◀── カーネル共通のファイル処理層
└──────────────────────────────────────┘
       │
       ├─▶ 5-1. [ DACチェック ] (ファイルの所有者・権限管理 rwx の検証)
       │         └─ 拒否時はここで処理中断
       ▼ [ DAC通過 ] (6. 強制アクセス制御の介入)
┌──────────────────────────────────────┐
│ LSM (Linux Security Module - SELinux) │ ◀── システムコールに対する最終許可・拒否判定。
└──────────────────────────────────────┘     UID=0であってもポリシー外の行動を拒否
       │
       ▼ [ SELinux許可 ] (7. 物理ドライバへの橋渡し)
┌──────────────────────────────────────┐
│ Filesystem Driver (ext4, xfs等)       │ ◀── 個々のファイルシステムによるブロック割り当て
└──────────────────────────────────────┘
       │
       ▼ (8. ハードウェア)
┌──────────────────────────────────────┐
│ 物理ディスク (Disk / SSD)              │ ◀── 最終的なデータの永続化
└──────────────────────────────────────┘

第11章:多層防御における各セキュリティレイヤー比較マトリクス

システム内に配置された各防衛機構が、それぞれ「どのレイヤー」を「どのような基準」で防衛しているかの全体対応表です。

防御レイヤー防御対象判定タイミング判定の具体例ゼロトラスト環境における役割
FortiGateパケット境界ネットワーク到着時送信元IP、不要ポート、DDoSなどのパケット遮断外部公開ネットワークセグメントの物理的境界防衛
Firewalld (nftables)ポート / プロトコルホストネットワークインターフェース到着時80/443番など、明示的に許可した通信ポートのみホスト内へ通過させるホストOS自体のネットワーク露出面の最小化
Fail2banログ / 認証履歴アプリケーションログの追記・更新時短時間の連続ログイン失敗(ブルートフォース等)を検知しIPを動的遮断外部露出したログインポートに対する侵入試行の排除
SELinuxシステムコールアプリケーションからカーネルへの命令実行時httpd_tドメインによる/etc/shadowの読込を拒否(MAC)内部への侵入やプロセスの改ざんを前提とした、特権昇格後の被害拡散(横移動)防止
DAC (標準アクセス制御)ディレクトリ / ファイルファイルオブジェクトへのアクセス時所有者、所属グループ、パーミッション(rwx)による制御一般ユーザー間、一般的なサービス間におけるファイル共有境界の維持
AppArmor(参考)パス指定プロセスプロセスの起動およびアクセス時プログラムの「実行ファイルの絶対パス」に基づき起動やアクセスを制限(Ubuntu等で標準)パスベースによる定義の平易性を重視したホスト保護(SELinuxより設定が直感的)

第12章:ゼロトラストセキュリティ原則とSELinuxの機能マッピング

本ガイドの設計思想の核となる「ゼロトラストセキュリティ原則」が、SELinuxの各機能によってどのようにホストOS上で具体化されているかを示します。

ゼロトラストコア原則SELinuxでの具体的なアプローチOS内におけるセキュリティ上の効果
最小権限の原則
(Least Privilege)
各プロセス(例:httpd_t)に対し、業務上必要最小限のタイプ(例:httpd_sys_content_t)へのアクセス許可のみをallowルールで定義。アプリケーションに不要な特権(例:他のサービス領域の読み書き)を一切排除する。
侵害前提の設計
(Assume Breach)
プロセスの特権昇格(UID=0化)が発生した場合でも、正規のexecve()およびドメイン遷移規則(type_transition)を経由しない限りセキュリティコンテキストは維持される。Webサーバー等が外部から乗っ取られてroot権限が奪取された場合でも、OS内部への壊滅的な被害を防ぐ。
継続的な検証
(Continuous Verification)
ユーザー空間のプロセスによるファイル等の要求に対し、システムコール・VFS/LSM層において、AVCおよびポリシーによりすべてのアクセスを毎回評価。一度確立したセッションや、起動中のプロセスであっても、「暗黙の信頼」をせず常にシステムコール単位でアクセスを検証し続ける。
被害の局所化
(Blast Radius Containment)
サービスごとに隔離されたドメイン(httpd_t やpostfix_t など)間の干渉を拒否。万が一、一つのプロセスが侵害された場合でも、そのプロセスのドメインに限定して被害を封じ込め、システム全体の乗っ取り(横展開)を防止。

おわりに

SELinuxは、「ネットワーク到達後・アプリケーション実行後」という、他の防御機構では手の届かない最深部(システムコールレベル)を守る最終防衛線です。この内部構造の知識を基礎として、「SELinuxの運用管理」で実務用のトラブルシューティング・コマンドリファレンスを確認してください。

SELinuxの内部構造、これで整理完了 🎉

セキュリティコンテキスト・Type Enforcement・LSM/VFS連携・Domain Transition・多層防御マトリクスまで一通り確認しました。実務設定は「SELinuxの運用管理」もあわせてご参照ください。

運用・保守 一覧へ戻る