SELinuxセキュリティ:Linuxシステムをミリ単位で制御

最終更新: 27月2026
  • SELinuxは、従来のDACパーミッションを超えるタグとポリシーを通じて、Linuxカーネルに強制的なアクセス制御を追加します。
  • セキュリティコンテキスト(ユーザー、ロール、タイプ、レベル)とタイプベースのポリシーにより、プロセス、ファイル、ポートに対する非常にきめ細かなアクセス制御が可能になります。
  • getenforce、chcon、semanage、semodule、booleansなどのツールは、本番環境におけるSELinuxの実践的な管理を容易にします。
  • 適切に設定されていれば、SELinuxは各サービスやアプリケーションが実行できる操作を厳密に制限することで、ゼロデイ攻撃や設定ミスによる被害を軽減します。

LinuxシステムにおけるSELinuxのセキュリティ

SELinuxはカーネルオタク向けの技術のように聞こえるかもしれませんが、実際には今日のLinuxで利用できる最も強力なセキュリティツールの1つです。サーバー、Dockerコンテナのセキュリティ、クラウドインフラストラクチャ、あるいは多少機密性の高いデスクトップコンピュータを管理している場合、SELinuxの仕組みを理解することは、単に「適切に設定されている」システムと、ゼロデイ脆弱性があっても侵害されにくいシステムとの決定的な違いを生み出します。

SELinuxは「複雑」という評判とは裏腹に、非常に論理的なモデルを提供します。各プロセスが実行できる操作と通信可能なオブジェクトを定義し、その定義から逸脱する行為があれば、カーネルが即座にプロセスを停止します。rootユーザーが適切に動作することやデーモンにバグがないことを盲目的に信頼するのではなく、SELinuxは非常に詳細なラベルとポリシーを用いて、スーパーユーザーにも適用される強制的なアクセス制御を強制します。

SELinuxとは何ですか?また、どのような問題を解決するのですか?

SELinux(Security-Enhanced Linux)は、LSM(Linux Security Modules)をベースとしたLinuxカーネルのセキュリティモジュールです。元々はNSAがRed Hatなどのパートナーと協力して開発したもので、カーネルバージョン2.6以降はカーネルの公式な一部となっています。SELinuxは独立したアプリケーションではなく、強制アクセス制御(MAC)システムとロールベースアクセス制御(RBAC)を追加するカーネル拡張機能です。

SELinuxでは、従来のUnixの任意アクセス制御(DAC)(所有者、グループ、その他、rwx権限)とは異なり、アクセス決定はファイル所有者の選択ではなく、セキュリティ管理者が設定したグローバルポリシーに基づいて行われます。DACは依然として存在し、優先されます。DACが拒否した場合、SELinuxは介入しません。しかし、DACが許可した場合でも、SELinuxはポリシーに従って操作をブロックすることができます。

SELinuxアーキテクチャは、セキュリティに関する判断を行うカーネルコードと、許可される操作と許可されない操作を定義するポリシーモジュールという、明確な構成要素の分離を実現しています。この分離により、カーネルを再コンパイルすることなくルールを調整することが可能になり、システムセキュリティに影響を与える可能性のあるコンポーネントの数を削減できます。

SELinuxは、Fedora、Red Hat Enterprise Linux、CentOS、Scientific Linuxなどのディストリビューションでデフォルトで採用されており、Androidなどのシステムにも深く統合されています。Androidでは、システムプロセスやアプリケーションを特定のドメインに限定するためにSELinuxが使用されています。BSDおよびGNU/Linuxの世界では、AppArmor、TOMOYO、TrustedBSD(macOS/FreeBSD上)などの代替手段がありますが、SELinuxはすべてのシステムオブジェクトに対して提供するきめ細かな制御レベルにおいて際立っています。

DACからMACへ:なぜ従来のモデルではもはや不十分なのか

従来のUnixシステムでは、ドメインオブジェクトモデルはDACを使用して管理されます。各ファイルやリソースには所有者と権限があり、そのユーザーとして実行されているプロセスは、それらのリソースに対して何でも実行できます。つまり、デーモンがroot権限で実行されている場合、悪用可能なバグがあれば、rootコンテキストでシステムの半分を制御できてしまう可能性があるということです。

典型的な例としては、データファイルがDBMSを介してのみ操作されるべきデータベースが、実際にはrootユーザーIDを持つプロセスによって読み取りおよび変更可能になっている場合や、過剰な権限で実行されている重要なデーモンなどが挙げられます。プログラミングエラー、バッファオーバーフロー、または不十分な入力検証によって、サービスがシステム全体への侵入経路となってしまう可能性があります。

SELinuxは、DACの上に強制アクセス制御(MAC)レイヤーを追加します。「強制」とは、アクセス制御が管理者によってポリシーを通じて一元的に定義され、ユーザーもプロセスもこれらのルールを独自に緩和できないことを意味します。オペレーティングシステムは、関連するカーネル操作をそれぞれ評価してから許可することで、これらのポリシーを強制します。

カーネルは、LSMフックを使用して、機密性の高いシステムコール(ファイルのオープン、ソケットの作成、ファイルシステムのマウント、IPCによる通信など)ごとにSELinuxに問い合わせます。SELinuxは、各判断ポイントで、ロードされたポリシーと主体および対象のセキュリティコンテキストに基づいて操作を評価します。ポリシーが明示的に許可を与えていない場合、プロセスがroot権限を持っているかどうかに関わらず、操作は拒否されます。

動作モード:強制、許可、無効

SELinuxは、明確に区別された3つの動作状態で動作することができ、本番環境で混乱を避けるためには、これらの状態を理解しておくことが重要です。

  • 施行SELinuxが有効になっており、ポリシーが完全に適用されます。ルールで許可されていないすべての操作はブロックされ、ログに記録されます。
  • パーミッシブSELinuxはアクティブで、ポリシーをロードしてファイルシステムにラベルを付けますが、 ブロックしない 取引が拒否されたかのように記録するだけです。これはデバッグやポリシー調整に最適です。
  • 身体障がい者SELinuxは無効になっています。ポリシーは適用されず、タグ付けも行われません。システムは従来のDACモデルに基づいています。
  暗号化とは何か、どのように機能するのか、そしてなぜ重要なのか

強制モードと許可モードを一時的に素早く切り替えるには、 `setenforce`コマンドを使用します。このコマンドでは、モードを 0 (許可モード) または 1 (強制モード) で指定します。この変更は一時的なものであることに注意してください。再起動後、モードは設定ファイルで定義されたモードに戻ります。

永続的な変更が必要な場合は、ファイルを編集する必要があります。 /etc/selinux/config (または一部のディストリビューションでは /etc/sysconfig/selinux)でディレクティブの値を調整します SELINUX=disabled|permissive|enforcing変更内容は次回の起動時に適用され、多くの場合、ファイルシステムのラベル変更を伴います。

アクティブモードを確認するには、getenforceやsestatusなどのコマンドを使用できます。前者はEnforcing、Permissive、Disabledのいずれかを返しますが、後者はSELinuxの状態、ロードされたポリシー、アクティブなモジュールに関するより詳細な概要を提供します。

セキュリティコンテキストとラベリングシステム

SELinuxの中核を成すのは、セキュリティラベルまたはコンテキストと呼ばれるシステムです。ファイル、プロセス、ネットワークポート、ソケット、デバイスなど、あらゆるオブジェクトには、その使用方法を記述する関連付けられたコンテキストが存在します。このコンテキストは、SELinuxがそのオブジェクトをどのように認識するかを示す複数のフィールドで構成されています。

コンテキストの一般的な形式は、user_u:role_r:type_t:levelですが、ポリシー(特に MLS/MCS を使用する場合)によって若干の違いがあります。各フィールドには、SELinux ユーザー、ロール、タイプ(プロセスを指す場合はドメインとも呼ばれます)、および機密レベルまたはカテゴリという特定の目的があります。

実際には、最も重要な要素はタイプ(3番目のフィールド)です。なぜなら、ポリシー規則の大部分はタイプ間の関係として定式化されるからです。たとえば、httpd_t タイプのプロセスが httpd_sys_content_t というラベルの付いたファイルにアクセスできるようにしたり、特定のドメインが http_port_t というラベルの付いたソケットと通信できるようにしたりします。

これらのコンテキストは次のように保存されます 拡張ファイルシステム属性したがって、ext4、XFSなどの拡張属性をサポートするファイルシステムを使用することが不可欠です。プロセスの場合、現在のコンテキストおよびその他の関連コンテキストは、擬似ファイルシステムを介して公開されます。 /proc/<pid>/attr/ current、exec、fscreate、prev、sockcreate、keycreateなどのファイル内。

ターゲットポリシーを持つシステムにおけるコンテキストの典型的な例は次のとおりです。

  • system_u:object_r:httpd_sys_content_t:s0 ApacheまたはNginxによって配信されるWebコンテンツの場合。
  • system_u:object_r:home_user_t:s0 ユーザーのホームディレクトリ用。
  • system_u:system_r:httpd_t:s0 ウェブサーバー自体の実行ドメイン向け。

SELinuxコンテキストの構成要素を分解する

unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023のようなコンテキストに遭遇すると、象形文字のように見えるかもしれませんが、それぞれの要素は SELinux とその参照ポリシー内の特定の概念に対応しています。

El SELinuxユーザー (慣例により接尾辞が付く) _uこれは、/etc/passwd に記述されている Unix ユーザーとは異なります。SELinux は独自のユーザーデータベースを保持し、それらを Linux ユーザーにマッピングします。MAC レイヤーを DAC から独立させるという考え方に基づき、SELinux ユーザーは複数の Unix ユーザーをグループ化できます。

El SELinux ロール (接尾辞付き _rこれは、ユーザーまたはドメインがどのような役割を担うことができるかを定義します。厳密に適用する場合、完全なRBACと呼ばれます。ほとんどのファイルオブジェクトはobject_rロールを使用しますが、system_r、user_r、staff_r、sysadm_rなどのロールは、プロセスが担うべきセキュリティコンテキストに応じて適用されます。

El SELinux のタイプまたはドメイン (スフィジョ _t実際には、型が重要な要素となります。型は、オブジェクトのクラス、またはプロセスの実行ドメインを記述します。ポリシーは、型間でどのような相互作用が許可されるかを指定します。つまり、どのドメインが他のどの型のオブジェクトに対して読み取り、書き込み、実行、または通信を行うことができるかを指定します。

レベルとカテゴリは、マルチレベルセキュリティ(MLS)またはマルチカテゴリセキュリティ(MCS)ポリシーが有効になっている場合に使用されます。機密性は階層構造(例:s0、s1など)ですが、カテゴリは階層構造ではありません(c0、c1、c2など)。特に重要な環境(例えば、特定の政府機関)では、データの読み取りは下位レベルまで、書き込みは同じレベルまたは上位レベルまでのみ可能であり、データを非常に具体的な区分ごとに分離するために、レベルとカテゴリが使用されます。

SELinuxポリシー:ターゲット型、厳格型、MLS/MCS、モジュール性

SELinux によって適用されるセキュリティは、ロードされたポリシーによって決定されます。ポリシーとは、どのドメインがどのタイプに対してどのような操作を実行できるか、またその他の要素(遷移、タグ付けルールなど)を記述する一連のルールです。通常、ディストリビューションには標準ポリシーが同梱されているため、すべてをゼロから記述する必要はありません。

最も一般的なポリシーは「ターゲット型」と呼ばれます。このモードでは、特定のプロセス(主にネットワークサービスや、Apache、Nginx、DNS、プロキシ、SNMP、syslogなどの高リスクデーモン)のみが限定されたドメイン内で実行されます。その他のユーザープロセスはすべて「非限定型」ドメインで実行され、そこでは基本的に標準的なLinuxセキュリティが適用され、特定のアクションがログに記録されます。

また、ほぼすべてのプロセスが特定のポリシーの下に置かれる厳格なポリシーもあります。これははるかに安全ですが、モデルが十分に理解されていない場合は、ラベル付けやルールの不一致が標準的なワークフローを混乱させる可能性があるため、維持管理がかなり困難になる場合があります。

高度なセキュリティ環境においては、機密性やカテゴリを活用してさらにきめ細かな制御を行うMLS/MCS(マルチレベル/マルチカテゴリセキュリティ)ポリシーが用いられます。これらは、非常に厳格な軍事環境や行政環境で典型的に見られるものであり、運用上の複雑さが極めて高いため、特定の状況以外ではほとんど使用されません。

最新のポリシーはモジュール式で配布されます。単一の巨大なポリシーファイルではなく、特定のサービスごとに個別のモジュールを使用することで、管理と更新が大幅に簡素化されます。これらのモジュールは、semoduleやsemanage moduleといったツールで管理され、ポリシー全体を再コンパイルすることなく、ポリシーの一部をインストール、削除、有効化、無効化することができます。

  ローカルセキュリティカメラ用のFrigateのインストールと設定方法

SELinux がどのように決定するか: 主体、オブジェクト、クラス、およびパーミッション

プロセス(主体)がリソース(オブジェクト)にアクセスしようとすると、SELinuxは概念的に「タイプXのドメインは、クラスCに属するタイプZのオブジェクトに対して操作Yを実行できるか?」という問いを立てます。そして、定義されたルールを通してポリシー内でその答えを探します。

ほとんどのディストリビューションや Android で使用されているタイプ強制 (TE) ポリシーでは、各オブジェクトはクラス(ファイル、ディレクトリ、fifo_file、tcp_socket、プロセスなど) に属し、ポリシーは各クラスに対してどのような権限が可能かを定義します。読み取り、書き込み、実行、バインド、接続、getattr、オープンなど、さまざまな権限があります。

TEルールは非常に直接的に表現されます。基本的な例を挙げると次のようになります。

httpd_t http_port_t:tcp_socket name_bind を許可する。

このルールにより、ポリシーは、httpd_t ドメイン内のプロセスが、http_port_t というラベルの付いた TCP ソケットに対して name_bind 操作を実行できることを示します。このアプローチは、特定のパスではなくオブジェクトのタイプとクラスに焦点を当てているため、ファイルの移動やディレクトリ構造の変更時に予期せぬ問題が発生するのを防ぎます。

例えばAndroidでは、SELinux属性を使用して`appdomain`のようなより一般的なラベルの下にタイプをグループ化することで、定義を繰り返すことなく単一のルールを複数のドメイン(`untrusted_app`、`isolated_app`など)に適用できます。また、`rw_file_perms`のようなマクロを使用して、いくつかの一般的なファイル権限をグループ化し、見落としによるエラーを減らすこともできます。

内部ステータス、AVC、および拒否登録簿

アクセス要求が発生すると、SELinuxはまずアクセスベクトルキャッシュ(AVC)を参照します。AVCは、処理を高速化するために最近のアクセス決定を保存するキャッシュです。決定が既にキャッシュに存在する場合は、それが直接使用されます。そうでない場合は、ファイアウォール(カーネル内のSELinuxの内部部分)に問い合わせが行われ、ファイアウォールはポリシーと主体および対象のコンテキストに基づいて操作を評価します。

要求されたアクションを明示的に許可するルールが存在しない場合、デフォルトの決定は拒否となります。この「デフォルトで拒否」という理念は、SELinuxの柱の一つであり、許可的な設定ミスに対する堅牢性を支えるものです。

強制モードで拒否が発生すると、カーネルは次のようなメッセージをログに記録します。 avc: 拒否 システムログに表示されます。ディストリビューションによっては、 /var/log/audit/audit.logに /var/log/messages または、auditdデーモンによってキャプチャされます。これらのメッセージには、プロセスコンテキスト(scontext)、オブジェクトコンテキスト(tcontext)、クラス、要求された操作、およびデバッグに非常に役立つその他のデータが含まれます。

パーミッシブモードでは、操作は許可されますが、イベント「avc: denied」が生成され、permissive=1 のマークが付けられます。これは、ポリシーの構築と調整において非常に役立ちます。なぜなら、通常の動作を妨げることなく、強制適用を実装した場合にシステムがどのような問題に直面するかを確認できるからです。

SELinuxをディストリビューションとAndroidに統合する

Linuxサーバーおよびデスクトップのエコシステムでは、SELinuxはデフォルトで有効になっています。 Fedora、RHEL、CentOSおよび派生OSDebianとUbuntuはカーネルとパッケージで完全なサポートを提供していますが、アクティベーションは通常オプションであり、selinux-basics、selinux-policy-default、auditdなどのパッケージをインストールし、その後グローバルに再タグ付けする必要があります。 fixfiles relabel.

Androidは当初、バージョン4.3でSELinuxをパーミッシブモードで組み込み、4.4では部分的な使用(installd、netd、vold、zygoteなどの重要なドメインのみ)に移行し、Android 5.0以降は完全に統合されています。Androidのポリシーは、タイプと属性を使用してアプリ、システムサービス、機密性の高いプロセスを分離することに重点を置いており、これらのコンポーネントのいずれかが侵害された場合の影響を最小限に抑えることを目的としています。

Androidは、一般的なアプリケーションプロセスにはuntrusted_appタイプ、アプリドメインをグループ化するにはappdomain属性、アプリ間および物理ユーザー間でデータを分離するにはMLS/MCSカテゴリといった概念を使用しています。これらすべてが連携して機能することで、たとえ侵害されたアプリケーションが非常に広範なユーザー権限を取得していたとしても、サンドボックスから脱出することを防ぎます。

重要:Android では、ユーザー、ロール、高度な感度を無視することで SELinux モデルが簡素化されています。SELinux ユーザーは 1 人 (u)、基本的なロールは 2 つ (主体を表す r とオブジェクトを表す object_r) のみで、感度は常に s0 です。データ分離において違いを生むのはカテゴリです。

AppArmorおよび他のLSMとの比較

多くの議論において、 SELinuxとAppArmorの比較は必然的に持ち上がります。どちらもLinuxのセキュリティモジュールであり、MAC(アクセス制御)を提供しているからです。しかし、両者のアプローチは大きく異なるため、どちらかを自分の環境に合わせて選択する前に、この点を理解しておくことが重要です。

SELinuxは、オブジェクトとそのタイプを中心としたポリシーを定義します。システム内のすべてのオブジェクト(ファイル、プロセス、ソケット、ポート、デバイス、IPCなど)にはラベルが割り当てられます。アクセス権限の決定は、正確なファイルパスに依存することなく、主体とオブジェクトのコンテキストに基づいて行われます。これにより、ディレクトリ構造の変更や代替ファイルシステムビュー(chroot、コンテナ、バインドマウントなど)に対して、システムの安定性が向上します。

一方、AppArmorはタスク中心のパスベースのポリシーを適用します。各プログラムのプロファイルを定義し、どのファイルパス、ポートなどにアクセスできるか、またどのような権限でアクセスできるかを指定します。設定はより直感的で、SELinuxのエキスパートになりたくない管理者にとっては一般的に使いやすいですが、制御の粒度はやや低く、ファイルシステムの構造に依存する度合いが高くなります。

  Linux およびその他の重要なファイルシステム上の NTFS PLUS

どちらもデフォルトで拒否するという原則を共有していますが、その適用方法は異なります。AppArmorはデフォルトでプロファイルでカバーされているタスクのみを拒否しますが、SELinuxは厳格モードの場合、システム全体とタグ付けされたすべてのオブジェクトにまで拒否範囲を拡大します。結果として、SELinuxは通常、より広範囲で複雑なポリシーを必要とするものの、より高度なレベルの制限を提供します。

SELinuxを管理するための実用的なツール

SELinux の操作には、モード、タグ付け、ブール値、ポリシー モジュールの管理を簡素化する一連のコマンドライン ツールが不可欠です。最初はツールが多すぎて圧倒されるかもしれませんが、いくつかのユーティリティで日常的なタスクのほとんどをカバーできます。

ファイルとプロセスのセキュリティコンテキストを表示するには、次のオプションを使用できます。 -Z ls、ps、idなどの一般的なコマンドで。たとえば、 ls -Z DACのパーミッションに加えて、各ファイルのSELinuxコンテキストも表示されるため、タグ付けが想定どおりかどうかをすばやく確認できます。

`chcon`(「コンテキストの変更」)コマンドを使用すると、`-r`、`-to`、`-l`などのオプションを使用して、ファイルのコンテキスト全体または特定の部分(役割、タイプ、範囲)のみを手動で変更できます。これは一時的な修正に便利ですが、`restorecon`や`fixfiles`などのツールを使用してポリシーに従ってラベル付けが再適用されると、変更が失われる可能性があることを覚えておくことが重要です。

semanageツールは、ランタイムポリシー管理における万能ツールです。様々なサブコマンドを使用することで、永続ファイルコンテキスト(fcontext)、LinuxユーザーとSELinuxユーザー間のログインマッピング(login)、SELinuxユーザーとその役割(user)、タグ付きポート(port)、ブール値、さらにはポリシーモジュールまで管理できます。しかも、ポリシー全体をソースから再コンパイルする必要はありません。

ポリシー内のルールのブロックを有効または無効にする小さなスイッチであるブール値の状態を確認および変更するには、setsebool ブール値自体に加えて、getseboolとsetseboolが使用されます。典型的なブール値は httpd_enable_homedirs で、これが有効になると、Web サーバーがユーザーのホーム ディレクトリにアクセスできるようになります (~user/public_html/ に便利です)。

最後に、 fixfilesのようなコマンドを使用すると、定義されたルールに従ってファイルシステムの完全なラベル付けを強制的に実行できます。また、semoduleは、参照ポリシーまたは管理者によってパッケージ化および配布されたポリシーモジュール(.pp)のインストール、一覧表示、有効化、無効化を処理します。

カスタマイズされたポリシーの作成と調整

アプリケーションに独自の SELinux モジュールがない場合や、より詳細な制限が必要な場合は、カスタム ポリシーを作成する必要があります。複雑に聞こえるかもしれませんが、手順を注意深く実行すれば、ワークフローは非常に明確に定義されています。

最初のステップは、関連するオブジェクト(実行ファイル、データディレクトリ、ソケットなど)に適切なタイプがラベル付けされていることを確認することです。これは、` semanage fcontext`コマンドでファイルコンテキストルールを定義し、`restorecon` コマンドで正規表現を使用してディレクトリツリー全体に適用することで実現できます。

その後、システムは通常、そのマシン(または場合によっては特定のドメイン)に対してパーミッシブモードに設定され、アプリケーションは通常どおり実行できます。SELinuxは、発生するはずだったすべての` avc: denied`ステートメントをログに記録します。これらのログは、通常audit2allowなどのツールで分析され、候補となるルールを抽出するために使用されます。

参照ポリシーは通常、アプリケーションごとに3つのファイルで構成されます。.teファイルにはTEルール(allow、type、domain_typeなど)が、.fcファイルにはファイルコンテキストルールが、.ifファイルには他のモジュールが再利用できるパブリックインターフェースが記述されています。これらはすべてmakeを使用して.ppモジュールにコンパイルされ、semoduleでロードされます。

audit2allowが提案する内容を鵜呑みにしないことが重要です。本来であれば、必要以上に寛容な設定になっていることが多いからです。理想的には、提案されたルールを手動で確認し、必要に応じて新しいタイプを作成して機密データと無関係なデータを分離し、拒否された操作が重要でない場合は、dontauditルールを使用して、権限を付与せずにノイズの記録を停止することを検討すべきです。

SUSE Linux MicroやAndroidなどの環境では、追加のツール(例えば、JSON記述からコンテナポリシーを生成するUdicaなど)が提供されており、ポリシー言語全体を一から学習することなく、特定のコンテナにポリシーを迅速に適合させることで、プロセスの一部を自動化します。

コンテキスト、モジュール式ポリシー、ブール値、管理ツールといった要素からなるこのエコシステム全体によって、SELinuxは非常に堅牢で柔軟なセキュリティプラットフォームとなっています。初期学習に多少の投資をすれば、各サービスやアプリケーションの動作を非常に正確に制限することが可能になり、エクスプロイト、マルウェア、人為的ミスに対するシステムの攻撃対象領域を大幅に強化できます。

Linux SELinuxの強化
関連記事:
SELinux による Linux の強化: 完全かつ実践的なガイド