✦urchin_hat
URCHIN_HAT / TECHNICAL FIELD NOTES

TECH MEMOTECH MEMO

SRE、クラウド、AI、DevOps。
観測したこと、試したこと、考えたことを記録する技術アーカイブ。

ウニの帽子をかぶり、ノートに技術メモを書くキャラクター
OBSERVATION LOG 50 ENTRIES
# FIELD NOTES

TECH MEMO TOPICS

01 / RELIABILITY SRE &
RELIABILITY
02 / PLATFORM CLOUD &
PLATFORM
03 / AUTOMATION AI &
AUTOMATION
『とりあえず無効化』を卒業。Google Cloud(GCE)× AlmaLinuxで学ぶSELinuxの基本 TECH MEMO / FIELD NOTE

『とりあえず無効化』を卒業。Google Cloud(GCE)× AlmaLinuxで学ぶSELinuxの基本

Amazon Linux 2027を機にSELinuxを学び直す

2026年9月、AWSから「Amazon Linux 2027」のパブリックプレビューが発表されました。SELinuxはデフォルトでEnforcingモードになります。発表内容は「Amazon Linux 2027がパブリックプレビューで利用可能に」を参照してください。SELinuxの仕様は「Security updates and features」にまとまっています。執筆時点ではプレビューであり、本番環境での利用は推奨されていません。

Amazon Linux 2023では、SELinuxは警告ログだけを出すPermissiveモードがデフォルトです。ポリシー違反があっても処理は止まらないため、AVCログを見ていなければ問題に気づきません。

Amazon Linux 2027では方針が変わり、SELinuxがデフォルトで「Enforcing(強制)モード」に設定されます。Enforcingモードでは、SELinuxポリシーに反するアクセスが拒否されます。root権限を持つプロセスでも、制限対象のSELinuxドメインで動いていればポリシーの対象です。

「とりあえず無効化」する前に原因を確認する

Linuxサーバーでは、「設定もパーミッションも合っているはずなのに動かない」ことがあります。

ApacheやNginxの設定ファイルに問題がなく、ファイル所有者(chown)や権限(chmod)も正しい。それでもサービスが起動せず、ブラウザから 403 Forbidden や 502 Bad Gateway が返ることがあります。

エラー文で検索すると、技術記事やQ&Aサイトで次のような手順を見かけます。

# SELinuxを一時的にPermissiveモードへ変更
sudo setenforce 0

# 古い記事などで見かける設定例(本記事では実行しません)
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

ここでサービスが動くようになると、原因を直さないまま無効化したくなります。ただし、setenforce 0 は一時的にPermissiveモードへ切り替えるコマンドであり、SELinux自体を無効化するものではありません。RHEL 9系でSELinuxを完全に無効化するには、/etc/selinux/config だけでなくカーネルコマンドラインの変更が必要です。

Amazon Linux 2027へ移行する場合、Permissiveモードではログだけに現れていた拒否が、サービスの起動や処理を止める可能性があります。移行前にAVCログを確認し、必要な設定を洗い出す必要があります。

SELinux(Security-Enhanced Linux)は、プロセスが侵害された場合のアクセス範囲をポリシーで制限する、多層防御の一つです。脆弱性そのものを修正する機能ではありませんが、侵害後の被害を抑える助けになります。理由を確認せず無効化すると、その防御層を一つ失います。

今回確認すること

今回は、標準でSELinuxがEnforcingモードになっている AlmaLinux 9 を使います。検証環境は Google CloudのCompute Engine(GCE) に作りました。VMとディスクはGoogle Cloudの無料枠に収まります。ただし、後述する外部IPv4アドレスは無料枠の対象外です。

TerraformとIAP(Identity-Aware Proxy)を組み合わせて環境を作り、あえて拒否を発生させます。ログから原因を絞り込み、SELinuxを有効にしたまま設定を直す流れを確認します。

SELinuxと従来のアクセス制御の違い

DACではrootの権限が強い

従来のLinux標準のセキュリティは、DAC(Discretionary Access Control / 任意アクセス制御) と呼ばれます。ファイルやディレクトリごとに「所有者(Owner)」「グループ(Group)」「その他(Other)」の読み取り・書き込み・実行権限(rwx)を設定する仕組みです。

DACでは、rootは通常のファイルパーミッションを回避できる強い権限を持ちます。

Webサーバー(NginxやApache)やコンテナが侵害され、攻撃者がroot権限まで取得すると、DACだけでは影響範囲が広がります。Linux capabilities、コンテナ分離、読み取り専用ファイルシステムなど、ほかの制約が働く場合は別です。

SELinuxが提供する強制アクセス制御(MAC)

これに対してSELinuxは、MAC(Mandatory Access Control / 強制アクセス制御) を実装するLinuxカーネルのセキュリティモジュールです。

MACでは、DACの判定に加えて、LinuxカーネルがSELinuxポリシーを適用します。RHEL系で標準の targeted ポリシーは、すべてのプロセスを同じ強さで制限するわけではありません。Nginxのような対象サービスは専用ドメインへ閉じ込める一方、通常のログインユーザーは既定で unconfined_t として動きます。

  • 最小特権をポリシーで補う: プロセスがアクセスできるポートやファイルを、DACとは別のルールで絞れます。
  • root権限だけでは回避できない: 制限対象のドメインで動くプロセスは、Linux上の実行ユーザーがrootでもSELinuxポリシーに従います。

SELinuxの基本概念とアクセス制御の仕組み

SELinuxのメリット・デメリット

SELinuxは侵害時の影響を抑える助けになる一方、ログの読み方やラベル管理を覚える必要があります。

観点従来のLinuxアクセス制御(DAC)SELinuxによる強制アクセス制御(MAC)
制御の単位ユーザー / グループごとの権限(rwx)プロセスとリソースの「ラベル(型)」によるポリシー制御
root権限の扱い通常のファイルパーミッションを広く回避できる制限対象のドメインでは、root権限だけでポリシーを回避できない
侵害時の影響root権限まで奪われると影響範囲が広がりやすいポリシーが許可していない操作を拒否し、影響範囲を狭められる可能性がある
運用の容易さ直感的で学習コストが低いラベルやブール値の理解が必要で導入障壁が高い
トラブル時の挙動通常のPermission denied(原因特定が容易)AVC拒否ログ(監査ログを読まないと原因が分かりにくい)

たとえば、Webサーバーのプロセスが httpd_t などの制限対象ドメインで動いていれば、ポリシーで許可されていないファイルの読み取りや通信を拒否できます。ただし、ポリシーで許可済みの操作やSELinux自体の脆弱性まで防げるわけではありません。

運用では、「型(Type)」「ドメイン」「AVCログ」「SELinuxブール値」などの概念を理解し、ポリシー変更を環境間で管理する必要があります。それでも、原因を確認せず無効化するより、拒否された操作を特定して必要な許可だけを追加する方が、意図した防御を保てます。

検証環境の設計:GCE × AlmaLinux 9 × Terraform

検証目的とはいえ、パブリックIPのSSHポート(22番)をそのままインターネットに公開するのは避けます。今回は、SSHの接続元をIAPに限定する環境をTerraformで構築します。

すでにAlmaLinux 9の検証環境がある場合は、「Nginxのポート変更による拒否の再現」まで読み飛ばせます。

VMとブートディスクは、Google Cloudの無料枠の条件を満たす構成にします。無料枠の対象や上限は変更される可能性があるため、作成前に公式の「無料のクラウド機能とトライアル特典」を確認してください。

無料枠(Always Free)の主な条件

  • マシンタイプ: 非プリエンプティブルの e2-micro(ゲストOSからは2 vCPU、共有CPUは合計25%相当、1 GBメモリ)
  • ブートディスク: 標準永続ディスク(pd-standard)を月30 GBまで
  • リージョン: us-central1、us-west1、us-east1 のいずれか

これは1請求先アカウントあたりの月間無料使用量です。複数の対象リージョンやVMで使った時間は合算されます。また、外部IPv4アドレスや無料枠を超えたデータ転送は別料金です。

IAP接続とアウトバウンド通信の注意点

IAPトンネリングを利用すると、外部からのインバウンドSSH通信をGoogleの管理IP帯(35.235.240.0/20)経由に限定できます(参考:IAPを使用したTCP転送)。ただし、IAP用の許可ルールを追加しただけでは、default-allow-ssh など既存の許可ルールは無効になりません。後述のTerraformでは、対象VMへの22番ポートをIAP以外から拒否するルールも追加します。

VMに外部IPを付与しない完全プライベート構成では、そのままでは VMから外部インターネットへのアウトバウンド通信ができません。そのため、パッケージ管理ツール(dnf)でリポジトリからメタデータを取得できず、タイムアウトエラーが発生します。

Errors during downloading metadata for repository 'appstream':
  - Curl error (28): Timeout was reached for https://mirrors.almalinux.org/...

IAPは「外から中へのSSH接続」を中継する仕組みであり、「中から外への通信」を代理するNATではありません。外部IPを持たないVMからインターネットへ出るには、Cloud NATやプロキシなどが別途必要です。

今回は、パッケージ導入とブラウザからの動作確認を簡単にするため、エフェメラル外部IPv4アドレスを1つ付与します。エフェメラルIPv4アドレスもVMの起動中は課金対象です。料金は「Virtual Private Cloud の料金」で確認できます。無料枠だけで完結する構成ではない点に注意してください。

Terraformコード

以下の3ファイルを用意してデプロイします。

main.tf

terraform {
  required_version = ">= 1.0.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
  zone    = var.zone
}

# 1. Google IAP経由のSSH接続(TCP:22)を許可
resource "google_compute_firewall" "allow_iap_ssh" {
  name        = "allow-iap-ssh"
  network     = "default"
  description = "Allow SSH from Google IAP"

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_ranges = ["35.235.240.0/20"]
  target_tags   = ["iap-ssh"]
  priority      = 1000
}

# IAP以外から対象VMのTCP:22へ接続できないようにする
# allow_iap_sshの方が優先度が高いため、IAPのIP帯だけは許可される
resource "google_compute_firewall" "deny_direct_ssh" {
  name        = "deny-direct-ssh"
  network     = "default"
  description = "Deny direct SSH except traffic allowed by a higher-priority rule"
  direction   = "INGRESS"
  priority    = 1100

  deny {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["iap-ssh"]
}

# 2. Web確認用ポート(80, 8080, 8888)のアクセスを許可
resource "google_compute_firewall" "allow_web" {
  name        = "allow-web-traffic"
  network     = "default"
  description = "Allow Web traffic from anywhere"

  allow {
    protocol = "tcp"
    ports    = ["80", "8080", "8888"]
  }

  source_ranges = ["0.0.0.0/0"]
  target_tags   = ["http-server"]
}

# 3. GCEインスタンス(AlmaLinux 9 / 無料枠スペック)
resource "google_compute_instance" "selinux_lab" {
  name         = "selinux-lab-instance"
  machine_type = "e2-micro"
  zone         = var.zone

  boot_disk {
    initialize_params {
      image = "almalinux-cloud/almalinux-9"
      size  = 30
      type  = "pd-standard"
    }
  }

  network_interface {
    network = "default"
    # パッケージ導入やブラウザ確認のためエフェメラル外部IPを付与
    access_config {
    }
  }

  tags = ["http-server", "iap-ssh"]

  allow_stopping_for_update = true
}

output "instance_external_ip" {
  description = "VMの外部IPアドレス"
  value       = google_compute_instance.selinux_lab.network_interface[0].access_config[0].nat_ip
}

output "ssh_iap_command" {
  description = "IAP経由の接続コマンド"
  value       = "gcloud compute ssh ${google_compute_instance.selinux_lab.name} --zone=${var.zone} --tunnel-through-iap --project=${var.project_id}"
}

variables.tf

variable "project_id" {
  description = "Google Cloud Project ID"
  type        = string
}

variable "region" {
  description = "Region for Free Tier"
  type        = string
  default     = "us-central1"
}

variable "zone" {
  description = "Zone for Free Tier"
  type        = string
  default     = "us-central1-a"
}

terraform.tfvars

project_id = "your-gcp-project-id"
region     = "us-central1"
zone       = "us-central1-a"

環境を作成したら、出力されたコマンドを使ってIAP経由でVMへログインします。

このコードは、default VPCが存在し、対象プロジェクトでCompute Engine APIとIAP APIが有効になっていることを前提にしています。実行ユーザーには、IAPトンネルとVMログインに必要なIAM権限も必要です。80・8080・8888番は検証のためインターネット全体へ公開するので、検証後は terraform destroy で削除します。

terraform init
terraform apply

# IAPトンネル経由でSSH接続
gcloud compute ssh selinux-lab-instance --zone=us-central1-a --tunnel-through-iap --project=your-gcp-project-id

実践:Nginxのポート変更による拒否の再現

ログインしたら、Nginxの待ち受けポートを標準の80番から変更し、SELinuxによる拒否を再現します。

1. Nginxの導入と8080番ポートの挙動

まずはNginxをインストールして起動します。

sudo dnf install -y nginx policycoreutils-python-utils
sudo systemctl enable --now nginx

OS側で firewalld が有効な場合は、Google Cloudのファイアウォールとは別に検証用ポートを許可します。

sudo firewall-cmd --permanent \
  --add-port=80/tcp \
  --add-port=8080/tcp \
  --add-port=8888/tcp
sudo firewall-cmd --reload

ブラウザで http://<外部IP>/ にアクセスすると、Nginxのデフォルトページ(Web Server Test Page)が表示されます。

AlmaLinux上のWebサーバー初期テストページ画面

ここで、ポートを8080番に変更してみます。設定ファイルを書き換えてサービスを再起動すると、問題なく起動し、ブラウザからもアクセスできてしまいます。

なぜ8080番は動くのでしょうか。SELinuxのポート型を確認すると理由が分かります。

sudo semanage port -l | grep 8080
# 出力例:
# http_cache_port_t              tcp      8080, 8118, 8123, 10001-10010

SELinuxの標準ポリシーでは、httpd_t ドメインに http_port_t(80、443など)だけでなく、http_cache_port_t(8080など)へのバインドも許可されています。Red Hatの「非標準構成のアプリケーションおよびサービス用にSELinuxを設定する」にも、ポート型の一覧を確認し、非標準ポートへ http_port_t を追加する手順があります。

2. 未許可ポート(8888)への変更

次に、今回のAlmaLinux 9環境ではWebサーバー用の型が付いていなかった 8888番ポートへ変更します。ポート型はポリシーのバージョンやローカル変更で異なる可能性があるため、先に確認します。

sudo semanage port -l | grep -w 8888

何も表示されないことを確認してから進めます。8888番が表示された場合は、割り当て済みの型と用途を先に確認します。別の型が割り当てられているポートには、後述の semanage port -a をそのまま実行できません。

/etc/nginx/nginx.conf の設定を変更します。

    server {
        listen       8888;
        listen       [::]:8888;
        server_name  _;
        root         /usr/share/nginx/html;
        ...

設定ファイルの文法チェックを実行します。

sudo nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

文法チェックは正常に通ります。nginx -t は設定ファイルの構文や参照先を確認しますが、設定した待ち受けポートでサービスを起動する処理ではないため、この時点では name_bind の拒否は発生しません。

一方、systemd経由でNginxを再起動すると起動に失敗します。

sudo systemctl restart nginx
# Job for nginx.service failed because the control process exited with error code.
# See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.

設定に誤りはありませんが、プロセスが起動できません。SELinuxによる拒否が疑われるため、AVCログを確認します。

原因の特定:AVC監査ログを読み解く

「動かないからとりあえずPermissiveにする」と判断する前に、まずは監査ログを確認します。

SELinuxのアクセス拒否ログ(AVC: Access Vector Cache)は /var/log/audit/audit.log に記録されます。監査ログ検索ツール ausearch を使うと、目的の拒否ログをすばやく抽出できます。

sudo ausearch -m avc -c nginx --interpret
# または直近の拒否ログを確認
sudo ausearch -m avc -ts recent

出力されるログから、該当箇所を確認します。次は読み方を示すために項目を抜き出した例であり、時刻、PID、監査イベント番号は環境ごとに変わります。

type=AVC msg=audit(1727600000.123:456): avc:  denied  { name_bind } for  pid=31523 comm="nginx" src=8888 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0

この1行から、今回の拒否に関係する主体、対象、操作を読み取れます。

項目ログの値内容・意味
comm"nginx"アクションを実行しようとしたコマンド名
denied { ... }{ name_bind }ソケットへのポート割り当て(bind)が拒否された
src8888対象となったポート番号
scontext...:httpd_t:...プロセス側の型(ドメイン)。Webサーバー用の httpd_t
tcontext...:unreserved_port_t:...リソース側の型(タイプ)。未予約ポートの unreserved_port_t
tclasstcp_socket対象となったリソースのクラス(TCPソケット)

このログから、「Webサーバーのプロセス(httpd_t)が、Web用として許可されていないポート(unreserved_port_t: 8888)にバインドしようとしたため、SELinuxが遮断した」という事実が読み取れます。

SELinuxを有効にしたまま解決する

原因が「8888番ポートにWebサーバー用の型が付いていないこと」だと分かれば、8888番へ http_port_t を割り当てます。

管理ツールの導入

ポートやファイルコンテキストを管理する semanage コマンドは、先ほどインストールした policycoreutils-python-utils パッケージに含まれます。未導入の場合は、次のコマンドで追加します。

sudo dnf install -y policycoreutils-python-utils

一時的な切り分けの作法(Permissiveモード)

SELinuxが原因かを切り分けるときは、設定ファイルを disabled に書き換えず、一時的に Permissiveモード(拒否は行わずログだけを出す状態) を使います。

# Permissiveモードに変更(再起動不要で即時反映)
sudo setenforce 0

# サービスが起動することを確認
sudo systemctl restart nginx

# 確認が済んだら即座に Enforcing に戻す
sudo setenforce 1

# Enforcingで同じ拒否が再現することを確認
sudo systemctl restart nginx

Permissiveモードで起動できたら、AVCログを確認してEnforcingへ戻します。その後、Nginxを再起動して同じ拒否が再現すれば、SELinuxポリシーが起動失敗に関係していると判断できます。Permissiveモードで起動したプロセスは、setenforce 1 を実行しただけでは再起動されません。

恒久対応:ポート型(http_port_t)の追加

semanage port コマンドで、8888番ポートを http_port_t に追加します。

sudo semanage port -a -t http_port_t -p tcp 8888

-a は未登録のポートを追加する指定です。8888番に別の型がすでに割り当てられている場合はエラーになるため、既存用途との競合を確認し、別のポートを選ぶか、意図を確認した上で -m による変更を検討します。

登録内容を確認します。

sudo semanage port -l | grep http_port_t
http_port_t                    tcp      8888, 80, 81, 443, 488, 8008, 8009, 8443, 9000

http_port_t の許可リストに 8888 が追加されたことを確認できます。

Nginxの再起動と確認

再度Nginxを再起動します。

sudo systemctl restart nginx
sudo systemctl status nginx

エラーなく Active: active (running) となり、ブラウザから http://<外部IP>:8888/ へアクセスしてWebページが表示されることを確認できます。

SELinuxを無効化せず、必要なポートだけをWebサーバー用として登録できました。

SELinuxは型とポリシーでアクセスを判断する

1. プロセスとリソースを型で識別する

SELinuxでは、プロセス(主体)と、ファイルやポート、ディレクトリなどのリソース(客体)にセキュリティコンテキストと呼ばれる「ラベル」が付きます。

  • プロセスの型(ドメイン): プロセスに付与されるラベル(例: httpd_t)
  • リソースの型(タイプ): ファイルやポートに付与されるラベル(例: http_port_t、httpd_sys_content_t)

カーネル内のSELinuxは、「プロセス側のドメイン」が「対象リソースのタイプ」に対して指定の操作を実行してよいかを、ロードされたポリシーと照合して判定します。

SELinuxにおける主体・ポリシー判定・客体のアクセスフロー

2. /etc/selinux/config は起動時のモードを指定する

/etc/selinux/config では、OS起動時のモードや利用するポリシーを指定します。enforcing はポリシーを強制し、permissive は拒否せずにAVCログを記録します。

RHEL 9系では、SELINUX=disabled だけでSELinuxを完全に無効化する方式は廃止されました。完全に無効化する場合は、カーネルコマンドラインへ selinux=0 を追加します。Red Hatは、トラブルシューティングにはPermissiveモードを使うよう案内しています(参考:SELinuxの状態およびモードの変更)。

個別の設定変更には、semanage や setsebool などの専用コマンドを使います。semanage で追加したローカル変更は永続化され、起動時にロードされるポリシーへ反映されます。

3. targeted ポリシーという前提

AlmaLinux 9では、ディストリビューションが提供する targeted ポリシーを利用します。制限対象のドメインでは、ポリシーで許可されていない操作を拒否するのが基本です。一方、すべてのユーザープロセスやサービスが制限対象になるわけではありません。

Nginx、Apache、MySQL、SSHなどの主要サービスにはあらかじめ型とルールが定義されています。管理者は、カスタムポートや非標準ディレクトリなど、標準構成との差分を確認して設定します。

ポート以外で起きるSELinuxのトラブル

ポート変更以外でも、ファイルの型やブール値が原因でサービスが動かないことがあります。

1. ドキュメントルートの変更(403 Forbidden)

Webサイトの公開ディレクトリを標準の /var/www/html から /data/my-site などに変更すると、パーミッションが正しくても403エラーが発生することがあります。

  • 原因: 新しい配置先が var_t や default_t など、Webコンテンツ用ではない型になっていると、httpd_t からの読み取りが拒否されるため。実際の型は ls -Zd /data/my-site で確認します。

  • 対処手順:

    # ディレクトリ配下の正規ルールとして httpd_sys_content_t を登録
    sudo semanage fcontext -a -t httpd_sys_content_t "/data/my-site(/.*)?"
    
    # 登録したコンテキストを既存ファイル群へ再帰的に適用
    sudo restorecon -Rv /data/my-site
    

2. リバースプロキシや外部APIへの接続(502 Bad Gateway)

NginxからバックエンドのAPサーバー(Node.jsやPHP-FPM)や外部APIへ接続する構成では、SELinuxに通信を拒否されると502エラーやタイムアウトが発生します。

  • 原因: Webサーバープロセスからバックエンドや外部APIへの接続に必要なSELinuxブール値が、既定で off になっているため。すべての502エラーやタイムアウトがSELinuxに起因するわけではないので、AVCログも合わせて確認します。

  • 対処手順:

    # 現在のブール値を確認
    getsebool httpd_can_network_connect
    
    # 恒久的に許可(-P オプションを付与)
    sudo setsebool -P httpd_can_network_connect 1
    

3. SSHポートの変更によるサーバー締め出し

SSHポートを標準の22番から2222番などに変更し、sshd の再起動後に新しい接続ができなくなるケースです。

  • 原因: 2222番ポートが ssh_port_t に登録されていないため、sshdプロセスのバインドが拒否されてサービスが停止する。

  • 対処手順:

    # 必ずポートを変更・sshd再起動する「前」に実行
    sudo semanage port -a -t ssh_port_t -p tcp 2222
    

SELinuxだけでなく、OSのファイアウォールやクラウド側のファイアウォールでも新しいポートを許可する必要があります。既存セッションを残したまま別ターミナルから新しいポートへ接続できることを確認し、問題があれば元へ戻せる経路も用意します。

運用視点:手動操作による環境ドリフトを防ぐ

サーバー上で semanage や setsebool を手作業で実行すると、「検証環境では動いたが本番環境では動かない」といった環境ドリフト(設定差異)が起きやすくなります。

複数台へ同じ設定を配る場合は、SELinuxのカスタム設定もコードとして管理すると差分を追いやすくなります。

AnsibleでSELinuxの設定を管理する

Ansibleでは、community.general.seport、community.general.sefcontext、ansible.posix.seboolean の各モジュールを使い、必要なSELinux設定をPlaybookへ記述できます。sefcontext は既存ファイルへラベルを適用しないため、必要に応じて restorecon も実行します(参考:seport、sefcontext、seboolean)。

ゴールデンイメージを使う環境では、Packerなどのビルド工程でSELinux設定を適用する方法もあります。稼働中のサーバーを手作業で変更せず、同じイメージからVMやコンテナを作り直す運用にすると、設定差異を抑えられます。

AVCログを起点に必要な設定だけ直す

今回の検証では、Nginxの設定構文に問題がなくても、SELinuxのポート型が合わなければ起動に失敗することを確認しました。拒否が起きたときの流れは次のとおりです。

  • 拒否されたら: ausearch -m avc -ts recent で「誰が、何に対して、どんな操作を拒否されたか」を確認する。
  • 切り分けたいときは: disabled にするのではなく、setenforce 0(Permissive)で挙動を確かめ、原因を確認したら setenforce 1(Enforcing)に戻す。
  • 恒久的に直すなら: semanage port や restorecon、setsebool を使って適切な型やブール値を登録する。

AVCログで httpd_t、unreserved_port_t、name_bind を確認できれば、SELinux全体を緩めずに対象ポートだけを修正できます。

運用で闇雲に無効化するのではなく、拒否の理由や設定方法を理解して向き合えば、SELinuxとも良い付き合いができると思います。

@urchin_hat
WRITTEN BY@urchin_hat

とある領域のSaaSサービスのSREとして、プロダクトの信頼性と事業成長を支えています。

← BACK TO MEMO