Log Management
Linux ログ管理 包括ガイド
目次
- はじめに
- 従来型 syslog (rsyslog)
- 2.1 rsyslog の基本構造
- 2.2 ファシリティとプライオリティ
- 2.3 rsyslog 設定
- 2.4 リモートログ転送
- systemd-journald
- 3.1 journalctl の基本操作
- 3.2 journald の設定
- 3.3 永続ストレージ
- logrotate
- 集中ログ管理
- ELK Stack 概要
- 6.1 Elasticsearch
- 6.2 Logstash
- 6.3 Kibana
- Fluentd / Fluent Bit
- ログ分析
- ログベースアラート
- 監査ログ (auditd)
- 10.1 auditd の設定
- 10.2 ausearch
- 10.3 aureport
- トラブルシューティング
- ベストプラクティス
- 参考資料
1. はじめに
ログ管理はシステム運用の根幹である。セキュリティインシデントの調査、パフォーマンス問題の分析、コンプライアンス要件への対応など、あらゆる場面でログが重要な役割を果たす。
Linux における主要なログ管理コンポーネントは以下の通りである。
| コンポーネント | 役割 | 主な設定ファイル |
|---|---|---|
| rsyslog | 従来型 syslog デーモン | /etc/rsyslog.conf |
| systemd-journald | systemd のジャーナルシステム | /etc/systemd/journald.conf |
| logrotate | ログローテーション | /etc/logrotate.conf |
| auditd | カーネル監査システム | /etc/audit/auditd.conf |
主要なログファイルの場所
| ファイル | 内容 |
|---|---|
/var/log/messages | システム全般(RHEL系) |
/var/log/syslog | システム全般(Debian系) |
/var/log/auth.log | 認証ログ(Debian系) |
/var/log/secure | 認証ログ(RHEL系) |
/var/log/kern.log | カーネルログ |
/var/log/boot.log | ブートログ |
/var/log/cron | cron ログ |
/var/log/maillog | メールログ |
/var/log/audit/audit.log | 監査ログ |
/var/log/httpd/ | Apache ログ |
/var/log/nginx/ | Nginx ログ |
/run/log/journal/ | journald 揮発性ログ |
/var/log/journal/ | journald 永続ログ |
2. 従来型 syslog (rsyslog)
2.1 rsyslog の基本構造
rsyslog は syslog プロトコル (RFC 5424) を実装した高性能ログデーモンである。
# rsyslog の状態確認
$ systemctl status rsyslog
● rsyslog.service - System Logging Service
Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled)
Active: active (running) since Mon 2026-03-01 10:00:00 JST; 40 days ago
Docs: man:rsyslogd(8)
Main PID: 1234 (rsyslogd)
Tasks: 3 (limit: 23456)
Memory: 4.5M
CGroup: /system.slice/rsyslog.service
└─1234 /usr/sbin/rsyslogd -n
# バージョン確認
$ rsyslogd -v
rsyslogd 8.2102.0-15.el9 (aka 2021.02) compiled with:
PLATFORM: x86_64-redhat-linux-gnu
FEATURE_REGEXP: Yes
GSSAPI Kerberos 5: Yes
FEATURE_DEBUG: Yes
feature 64bit integers: Yes
feature TLS (GnuTLS): Yes
feature RELP: Yes
2.2 ファシリティとプライオリティ
ファシリティ(ログの発生源)
| ファシリティ | コード | 説明 |
|---|---|---|
kern | 0 | カーネルメッセージ |
user | 1 | ユーザレベルメッセージ |
mail | 2 | メールシステム |
daemon | 3 | デーモンプロセス |
auth | 4 | 認証・セキュリティ |
syslog | 5 | syslog 自体のメッセージ |
lpr | 6 | プリンタ |
news | 7 | ニュースシステム |
uucp | 8 | UUCP |
cron | 9 | cron デーモン |
authpriv | 10 | プライベート認証メッセージ |
ftp | 11 | FTP デーモン |
local0-local7 | 16-23 | ローカル使用(カスタム用途) |
プライオリティ(重要度)
| プライオリティ | コード | 説明 | 用途例 |
|---|---|---|---|
emerg | 0 | システム使用不能 | カーネルパニック |
alert | 1 | 即座の対応が必要 | DB破損 |
crit | 2 | クリティカル | ハードウェア障害 |
err | 3 | エラー | アプリケーションエラー |
warning | 4 | 警告 | ディスク容量不足 |
notice | 5 | 注意(正常だが重要) | 設定変更通知 |
info | 6 | 情報 | サービス起動完了 |
debug | 7 | デバッグ | 詳細なデバッグ情報 |
2.3 rsyslog 設定
メイン設定ファイル
# /etc/rsyslog.conf
#################
#### MODULES ####
#################
# imuxsock: ローカル syslog ソケット
module(load="imuxsock")
# imklog: カーネルログ
module(load="imklog")
# imjournal: systemd ジャーナルからの入力
module(load="imjournal"
StateFile="imjournal.state"
ratelimit.interval="600"
ratelimit.burst="20000")
# imtcp: TCP 経由でのリモートログ受信
# module(load="imtcp")
# input(type="imtcp" port="514")
# imudp: UDP 経由でのリモートログ受信
# module(load="imudp")
# input(type="imudp" port="514")
###########################
#### GLOBAL DIRECTIVES ####
###########################
# タイムスタンプフォーマット
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
# ファイルの所有者・パーミッション
$FileOwner syslog
$FileGroup adm
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
# ワークディレクトリ
$WorkDirectory /var/lib/rsyslog
###############
#### RULES ####
###############
# カーネルメッセージ
kern.* /var/log/kern.log
# 認証関連
auth,authpriv.* /var/log/auth.log
# メール関連
mail.* -/var/log/mail.log
# (-) はバッファリングを有効にする(パフォーマンス向上)
# cron 関連
cron.* /var/log/cron.log
# 緊急メッセージは全ユーザに送信
*.emerg :omusrmsg:*
# 全般(認証とメール以外)
*.*;auth,authpriv.none;mail.none;cron.none /var/log/messages
# 追加の設定ファイル読み込み
$IncludeConfig /etc/rsyslog.d/*.conf
カスタムフィルタリングルール
# /etc/rsyslog.d/50-custom.conf
# プロパティベースフィルタ: 特定プログラムのログを分離
:programname, isequal, "sshd" /var/log/sshd.log
& stop # このメッセージはここで処理を停止
# プロパティベースフィルタ: 特定メッセージパターンをフィルタ
:msg, contains, "failed password" /var/log/failed_auth.log
# RainerScript (高度なフィルタリング)
if $programname == 'nginx' and $syslogseverity <= 4 then {
action(type="omfile" file="/var/log/nginx/error.log")
stop
}
# テンプレート定義(カスタムログフォーマット)
template(name="CustomFormat" type="string"
string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n")
# テンプレートを使用したルール
local0.* action(type="omfile" file="/var/log/myapp.log" template="CustomFormat")
# JSON形式のテンプレート
template(name="JsonFormat" type="list") {
constant(value="{")
constant(value="\"timestamp\":\"") property(name="timereported" dateFormat="rfc3339")
constant(value="\",\"host\":\"") property(name="hostname")
constant(value="\",\"severity\":\"") property(name="syslogseverity-text")
constant(value="\",\"facility\":\"") property(name="syslogfacility-text")
constant(value="\",\"program\":\"") property(name="programname")
constant(value="\",\"message\":\"") property(name="msg" format="jsonf")
constant(value="\"}\n")
}
local1.* action(type="omfile" file="/var/log/myapp-json.log" template="JsonFormat")
2.4 リモートログ転送
ログ送信側の設定
# /etc/rsyslog.d/60-remote.conf
# UDP 経由でリモートサーバに転送
*.* @logserver.example.com:514
# TCP 経由でリモートサーバに転送(信頼性が高い)
*.* @@logserver.example.com:514
# 特定のファシリティ/プライオリティのみ転送
auth,authpriv.* @@logserver.example.com:514
*.err @@logserver.example.com:514
# TLS 暗号化転送
$DefaultNetstreamDriverCAFile /etc/pki/tls/certs/ca-bundle.crt
$DefaultNetstreamDriverCertFile /etc/pki/tls/certs/rsyslog-client.crt
$DefaultNetstreamDriverKeyFile /etc/pki/tls/private/rsyslog-client.key
$ActionSendStreamDriver gtls
$ActionSendStreamDriverMode 1
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer logserver.example.com
*.* @@logserver.example.com:6514
# キューイング(ネットワーク障害時のバッファリング)
$ActionQueueType LinkedList
$ActionQueueFileName remote_fwd
$ActionResumeRetryCount -1
$ActionQueueSaveOnShutdown on
$ActionQueueMaxDiskSpace 1g
ログ受信側の設定
# /etc/rsyslog.d/10-remote-receive.conf
# TCP で受信
module(load="imtcp")
input(type="imtcp" port="514")
# UDP で受信
module(load="imudp")
input(type="imudp" port="514")
# ホスト名別にログファイルを分離
template(name="RemoteHostLog" type="string"
string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")
# リモートホストからのログを分離保存
if $fromhost-ip != '127.0.0.1' then {
action(type="omfile" dynaFile="RemoteHostLog")
stop
}
# TLS 受信
module(load="imtcp"
StreamDriver.Name="gtls"
StreamDriver.Mode="1"
StreamDriver.AuthMode="x509/fingerprint")
input(type="imtcp" port="6514")
3. systemd-journald
3.1 journalctl の基本操作
journald は systemd に統合されたログシステムで、構造化されたバイナリ形式でログを保存する。
# 全ログ表示(最新から)
$ journalctl
# 最新のログからリバース表示
$ journalctl -r
# 末尾のログをリアルタイム表示(tail -f 相当)
$ journalctl -f
# 直近のN行を表示
$ journalctl -n 50
# 今回のブート以降のログ
$ journalctl -b
# 前回のブートのログ
$ journalctl -b -1
# ブートID一覧
$ journalctl --list-boots
-2 abc12345 Mon 2026-04-01 10:00:00 JST — Mon 2026-04-05 08:30:00 JST
-1 def67890 Mon 2026-04-05 08:35:00 JST — Thu 2026-04-08 15:00:00 JST
0 ghi13579 Thu 2026-04-08 15:05:00 JST — Fri 2026-04-10 14:00:00 JST
# 特定ユニット(サービス)のログ
$ journalctl -u sshd.service
$ journalctl -u nginx.service --since "1 hour ago"
# 特定プライオリティ以上
$ journalctl -p err # err, crit, alert, emerg
$ journalctl -p warning # warning 以上
# 時間範囲指定
$ journalctl --since "2026-04-10 09:00:00" --until "2026-04-10 17:00:00"
$ journalctl --since "2 hours ago"
$ journalctl --since today
$ journalctl --since yesterday --until today
# カーネルメッセージ(dmesg 相当)
$ journalctl -k
$ journalctl -k -b -1 # 前回ブートのカーネルメッセージ
# 特定PIDのログ
$ journalctl _PID=3421
# 特定UID(ユーザ)のログ
$ journalctl _UID=1000
# 特定実行ファイルのログ
$ journalctl /usr/sbin/sshd
# 出力フォーマット指定
$ journalctl -o json-pretty # 構造化JSON
$ journalctl -o short-iso # ISO8601 タイムスタンプ
$ journalctl -o verbose # 全フィールド表示
$ journalctl -o cat # メッセージのみ(メタデータなし)
# ディスク使用量確認
$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.
# ログの手動クリーンアップ
$ sudo journalctl --vacuum-size=500M # 500MB以下に削減
$ sudo journalctl --vacuum-time=30d # 30日より古いログを削除
$ sudo journalctl --vacuum-files=5 # ファイル数を5以下に削減
journalctl 出力フォーマット比較:
| フォーマット | 説明 | 用途 |
|---|---|---|
short | デフォルト(syslog風) | 日常的な確認 |
short-iso | ISO 8601 タイムスタンプ | 正確な時刻確認 |
json | JSON (1行) | スクリプト処理 |
json-pretty | JSON (整形) | デバッグ |
verbose | 全メタデータ | 詳細調査 |
cat | メッセージのみ | シンプルな確認 |
export | バイナリシリアライズ | ログ転送 |
3.2 journald の設定
# /etc/systemd/journald.conf
[Journal]
# ログの保存先
# volatile = /run/log/journal/ (揮発性、再起動で消失)
# persistent = /var/log/journal/ (永続)
# auto = /var/log/journal/ があれば永続、なければ揮発性
Storage=persistent
# 圧縮を有効にする
Compress=yes
# 永続ストレージの最大サイズ(ファイルシステムの10%がデフォルト)
SystemMaxUse=2G
# 個別ジャーナルファイルの最大サイズ
SystemMaxFileSize=128M
# 空き容量の最低保証
SystemKeepFree=4G
# 揮発性ストレージの最大サイズ
RuntimeMaxUse=500M
# ログのレート制限
RateLimitIntervalSec=30s
RateLimitBurst=10000
# 転送先設定
# yes = rsyslog にも転送する(デフォルト)
ForwardToSyslog=yes
ForwardToKMsg=no
ForwardToConsole=no
ForwardToWall=yes
# 最大保存期間
MaxRetentionSec=1month
# ログレベルのフィルタ(保存する最大レベル)
MaxLevelStore=debug
MaxLevelSyslog=debug
MaxLevelKMsg=notice
MaxLevelConsole=info
MaxLevelWall=emerg
# 設定変更後の反映
$ sudo systemctl restart systemd-journald
3.3 永続ストレージ
# 永続ストレージ用ディレクトリを作成
$ sudo mkdir -p /var/log/journal
$ sudo systemd-tmpfiles --create --prefix /var/log/journal
# パーミッション確認
$ ls -la /var/log/journal/
drwxr-sr-x+ 3 root systemd-journal 4096 Apr 1 10:00 .
drwxr-xr-x 20 root root 4096 Apr 1 10:00 ..
drwxr-sr-x+ 2 root systemd-journal 4096 Apr 10 14:00 abc123def456
# journald を再起動して永続化を有効にする
$ sudo systemctl restart systemd-journald
# 状態確認
$ journalctl --header | head -20
4. logrotate
logrotate はログファイルのローテーション(アーカイブ・圧縮・削除)を自動化するツール。
メイン設定
# /etc/logrotate.conf
# ローテーション頻度(デフォルト)
weekly
# 保持する世代数
rotate 4
# ローテーション後に空ファイルを作成
create
# 圧縮を有効にする
compress
# 1世代前は圧縮しない(直前のログをすぐ参照できるように)
delaycompress
# 日付をファイル名に付加
dateext
dateformat -%Y%m%d
# サブ設定ファイルの読み込み
include /etc/logrotate.d
アプリケーション別の設定例
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
# /etc/logrotate.d/syslog
/var/log/messages
/var/log/secure
/var/log/maillog
/var/log/cron {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
/usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
}
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 90
compress
delaycompress
missingok
notifempty
create 0644 myapp myapp
# サイズベースのローテーション
size 100M
# ローテーション前の処理
prerotate
echo "Log rotation starting at $(date)" >> /var/log/myapp/rotation.log
endscript
# ローテーション後の処理
postrotate
systemctl reload myapp.service >/dev/null 2>&1 || true
endscript
# 最後に1回だけ実行(sharedscriptsと組み合わせ)
lastaction
/usr/local/bin/notify-rotation.sh myapp
endscript
}
logrotate の主要ディレクティブ:
| ディレクティブ | 説明 |
|---|---|
daily / weekly / monthly | ローテーション頻度 |
rotate N | 保持する世代数 |
compress | gzip で圧縮 |
delaycompress | 1世代前は圧縮しない |
missingok | ログファイルがなくてもエラーにしない |
notifempty | 空ファイルはローテーションしない |
create MODE OWNER GROUP | 新しい空ファイルを作成 |
copytruncate | コピーして元ファイルを切り詰め(シグナル不要) |
sharedscripts | スクリプトを全ファイルで1回だけ実行 |
size SIZE | サイズ超過時にローテーション |
maxage N | N日より古いファイルを削除 |
dateext | 日付をファイル名に付加 |
# logrotate のテスト実行(ドライラン)
$ sudo logrotate -d /etc/logrotate.d/nginx
reading config file /etc/logrotate.d/nginx
Handling 1 logs
rotating pattern: /var/log/nginx/*.log after 1 days (30 rotations)
# 手動でローテーション実行
$ sudo logrotate -f /etc/logrotate.d/nginx
# logrotate の状態確認
$ cat /var/lib/logrotate/status
logrotate state -- version 2
"/var/log/nginx/access.log" 2026-4-10-3:0:0
"/var/log/nginx/error.log" 2026-4-10-3:0:0
"/var/log/messages" 2026-4-7-3:0:0
5. 集中ログ管理
アーキテクチャパターン
パターン1: rsyslog 直接転送
┌─────────┐ rsyslog TCP/TLS ┌──────────────┐
│ Server A │ ──────────────────────→ │ Central Log │
│ Server B │ ──────────────────────→ │ Server │
│ Server C │ ──────────────────────→ │ (rsyslog) │
└─────────┘ └──────────────┘
パターン2: ELK Stack
┌─────────┐ Filebeat ┌──────────┐ ┌───────────────┐ ┌────────┐
│ Server A │ ──────────────→ │ Logstash │ ──→ │ Elasticsearch │ ←── │ Kibana │
│ Server B │ ──────────────→ │ │ │ │ │ │
│ Server C │ ──────────────→ │ │ │ │ │ │
└─────────┘ └──────────┘ └───────────────┘ └────────┘
パターン3: Fluentd/Fluent Bit
┌─────────┐ Fluent Bit ┌──────────┐ ┌───────────────┐
│ Server A │ ──────────────→ │ Fluentd │ ──→ │ Elasticsearch │
│ Server B │ ──────────────→ │(集約) │ ──→ │ S3 / GCS │
│ Server C │ ──────────────→ │ │ ──→ │ Kafka │
└─────────┘ └──────────┘ └───────────────┘
集中ログ管理ソリューション比較
| 項目 | rsyslog集中収集 | ELK Stack | Fluentd + ES | Loki + Grafana |
|---|---|---|---|---|
| 難易度 | 低 | 高 | 中 | 中 |
| リソース消費 | 低 | 高 | 中 | 低 |
| 検索性能 | 低(grep) | 高 | 高 | 中 |
| スケーラビリティ | 中 | 高 | 高 | 高 |
| 可視化 | なし | Kibana | Kibana/Grafana | Grafana |
| コスト | 無料 | 無料/有料 | 無料/有料 | 無料/有料 |
6. ELK Stack 概要
6.1 Elasticsearch
# Elasticsearch インストール(RPM)
$ sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
$ cat > /etc/yum.repos.d/elasticsearch.repo << 'EOF'
[elasticsearch]
name=Elasticsearch repository
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md
EOF
$ sudo dnf install elasticsearch
# /etc/elasticsearch/elasticsearch.yml
cluster.name: logging-cluster
node.name: es-node-01
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts:
- "es-node-01"
- "es-node-02"
- "es-node-03"
cluster.initial_master_nodes:
- "es-node-01"
# JVMヒープサイズ(物理メモリの50%以下、32GB以下を推奨)
# /etc/elasticsearch/jvm.options.d/heap.options
# -Xms8g
# -Xmx8g
# インデックスライフサイクル管理 (ILM)
# 30日後にウォームフェーズ、90日後に削除
# 起動
$ sudo systemctl enable --now elasticsearch
# クラスタ状態確認
$ curl -s http://localhost:9200/_cluster/health?pretty
{
"cluster_name" : "logging-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 45,
"active_shards" : 90,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0
}
# インデックス一覧
$ curl -s http://localhost:9200/_cat/indices?v
health status index uuid pri rep docs.count store.size
green open logs-2026.04.10 abc123 1 1 1234567 2.3gb
green open logs-2026.04.09 def456 1 1 2345678 3.1gb
6.2 Logstash
# Logstash インストール
$ sudo dnf install logstash
# /etc/logstash/conf.d/syslog.conf
input {
beats {
port => 5044
ssl => false
}
# syslog 直接受信
syslog {
port => 5514
type => "syslog"
}
}
filter {
# syslog メッセージのパース
if [type] == "syslog" {
grok {
match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" }
}
date {
match => [ "syslog_timestamp", "MMM d HH:mm:ss", "MMM dd HH:mm:ss" ]
}
}
# Nginx アクセスログのパース
if [fields][log_type] == "nginx_access" {
grok {
match => { "message" => "%{IPORHOST:clientip} - %{USER:ident} \[%{HTTPDATE:timestamp}\] \"%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response} %{NUMBER:bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
}
geoip {
source => "clientip"
target => "geoip"
}
useragent {
source => "agent"
target => "user_agent"
}
}
# SSH 認証失敗ログのパース
if [program] == "sshd" {
grok {
match => { "message" => "Failed %{WORD:auth_method} for %{USER:username} from %{IP:src_ip} port %{INT:src_port}" }
tag_on_failure => ["_sshd_grok_failure"]
}
}
# 不要フィールドの削除
mutate {
remove_field => [ "beat", "input_type", "offset", "tags" ]
}
}
output {
elasticsearch {
hosts => ["http://localhost:9200"]
index => "logs-%{+YYYY.MM.dd}"
# インデックスライフサイクル管理
ilm_enabled => true
ilm_rollover_alias => "logs"
ilm_pattern => "{now/d}-000001"
ilm_policy => "logs_policy"
}
# デバッグ用(標準出力に表示)
# stdout { codec => rubydebug }
}
Filebeat (ログ収集エージェント)
# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/messages
- /var/log/secure
fields:
log_type: syslog
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
fields:
log_type: nginx_access
- type: log
enabled: true
paths:
- /var/log/nginx/error.log
fields:
log_type: nginx_error
output.logstash:
hosts: ["logstash-server:5044"]
# ロードバランシング
loadbalance: true
# TLS設定
# ssl.certificate_authorities: ["/etc/pki/tls/certs/ca-bundle.crt"]
# ssl.certificate: "/etc/pki/tls/certs/filebeat.crt"
# ssl.key: "/etc/pki/tls/private/filebeat.key"
# プロセッサ(軽量な前処理)
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
- drop_fields:
fields: ["agent.ephemeral_id", "agent.id", "agent.name", "ecs.version"]
6.3 Kibana
# /etc/kibana/kibana.yml
server.port: 5601
server.host: "0.0.0.0"
server.name: "kibana-server"
elasticsearch.hosts: ["http://localhost:9200"]
# セキュリティ設定
# elasticsearch.username: "kibana_system"
# elasticsearch.password: "changeme"
# ログ設定
logging.root.level: info
logging.appenders.file.type: file
logging.appenders.file.fileName: /var/log/kibana/kibana.log
logging.appenders.file.layout.type: json
# 起動
$ sudo systemctl enable --now kibana
# Kibana ダッシュボードへのアクセス: http://kibana-server:5601
7. Fluentd / Fluent Bit
Fluentd
# インストール (td-agent)
$ curl -fsSL https://toolbelt.treasuredata.com/sh/install-redhat-fluent-package5-lts.sh | sh
# または gem でインストール
$ sudo gem install fluentd
<!-- /etc/fluent/fluentd.conf -->
<!-- syslog 入力 -->
<source>
@type syslog
port 5140
tag system
<parse>
message_format auto
</parse>
</source>
<!-- ファイル入力 -->
<source>
@type tail
path /var/log/nginx/access.log
pos_file /var/log/fluentd/nginx-access.pos
tag nginx.access
<parse>
@type nginx
</parse>
</source>
<!-- ファイル入力(JSON形式のアプリログ) -->
<source>
@type tail
path /var/log/myapp/*.log
pos_file /var/log/fluentd/myapp.pos
tag myapp
<parse>
@type json
time_key timestamp
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<!-- フィルタ: フィールド追加 -->
<filter **>
@type record_transformer
<record>
hostname "#{Socket.gethostname}"
environment production
</record>
</filter>
<!-- フィルタ: 不要ログの除外 -->
<filter nginx.access>
@type grep
<exclude>
key path
pattern /\/(health|ready)/
</exclude>
</filter>
<!-- Elasticsearch への出力 -->
<match **>
@type elasticsearch
host elasticsearch-server
port 9200
logstash_format true
logstash_prefix logs
<buffer>
@type file
path /var/log/fluentd/buffer/elasticsearch
flush_interval 10s
chunk_limit_size 8MB
queue_limit_length 256
retry_max_interval 30
retry_forever true
</buffer>
</match>
<!-- S3 への出力(アーカイブ用) -->
<match archive.**>
@type s3
s3_bucket my-log-archive
s3_region ap-northeast-1
path logs/%Y/%m/%d/
<buffer time>
@type file
path /var/log/fluentd/buffer/s3
timekey 3600
timekey_wait 10m
</buffer>
<format>
@type json
</format>
</match>
Fluent Bit (軽量版)
# /etc/fluent-bit/fluent-bit.conf
[SERVICE]
Flush 5
Daemon Off
Log_Level info
Parsers_File parsers.conf
HTTP_Server On
HTTP_Listen 0.0.0.0
HTTP_Port 2020
[INPUT]
Name tail
Path /var/log/messages
Tag syslog
Parser syslog-rfc3164
Refresh_Interval 10
Mem_Buf_Limit 5MB
[INPUT]
Name systemd
Tag journal.*
Systemd_Filter _SYSTEMD_UNIT=sshd.service
Systemd_Filter _SYSTEMD_UNIT=nginx.service
Read_From_Tail On
[INPUT]
Name tail
Path /var/log/nginx/access.log
Tag nginx.access
Parser nginx
Refresh_Interval 5
[FILTER]
Name modify
Match *
Add hostname ${HOSTNAME}
[FILTER]
Name grep
Match nginx.access
Exclude path /health
[OUTPUT]
Name forward
Match *
Host fluentd-aggregator
Port 24224
[OUTPUT]
Name es
Match *
Host elasticsearch-server
Port 9200
Index logs
Type _doc
Logstash_Format On
Logstash_Prefix logs
Retry_Limit 5
Fluentd vs Fluent Bit 比較:
| 特徴 | Fluentd | Fluent Bit |
|---|---|---|
| 言語 | Ruby + C | C |
| メモリ使用量 | ~40MB | ~450KB |
| プラグイン数 | 700+ | 100+ |
| 用途 | 集約・ルーティング | エッジ・軽量収集 |
| パフォーマンス | 高 | 非常に高 |
| 設定の柔軟性 | 非常に高 | 高 |
| Kubernetes | 対応 | 推奨(DaemonSet) |
8. ログ分析
コマンドラインでのログ分析
# アクセスログの基本分析
# IPアドレス別アクセス数(上位10件)
$ awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
4567 192.168.1.100
3456 10.0.0.50
2345 172.16.0.25
1234 192.168.1.200
# HTTPステータスコード別集計
$ awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
45678 200
5678 301
3456 404
567 500
234 403
# 時間帯別アクセス数
$ awk -F'[' '{print $2}' /var/log/nginx/access.log | awk -F: '{print $2}' | sort | uniq -c
1234 00
1100 01
890 02
...
5678 10
6789 11
...
# エラーログの分析
$ grep "error" /var/log/nginx/error.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head -10
# SSH認証失敗の分析
$ grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -rn | head -10
456 192.168.1.50
234 10.0.0.100
123 172.16.0.99
# 特定期間のログ抽出(journalctl)
$ journalctl -u sshd --since "2026-04-10 00:00" --until "2026-04-10 23:59" | grep "Failed" | wc -l
45
# ログのリアルタイム監視(複数ファイル)
$ tail -f /var/log/messages /var/log/secure /var/log/nginx/error.log
# awk を使った高度な分析
$ awk '/Failed password/{
match($0, /from ([0-9.]+)/, arr);
ips[arr[1]]++
}
END {
for (ip in ips) printf "%6d %s\n", ips[ip], ip
}' /var/log/secure | sort -rn | head -10
ログ分析ツール
# GoAccess(リアルタイムWebログ分析)
$ sudo dnf install goaccess
# ターミナルで表示
$ goaccess /var/log/nginx/access.log --log-format=COMBINED
# HTML レポート生成
$ goaccess /var/log/nginx/access.log --log-format=COMBINED -o /var/www/html/report.html
# lnav(高機能ログビューア)
$ sudo dnf install lnav
$ lnav /var/log/messages /var/log/secure
9. ログベースアラート
rsyslog でのアラート
# /etc/rsyslog.d/70-alerts.conf
# OOM Killer 検知時にメール送信
if $msg contains "Out of memory" then {
action(type="ommail"
server="smtp.example.com"
port="25"
mailfrom="alert@example.com"
mailto="ops@example.com"
subject.template="OOM_Alert"
body.enable="on")
}
# SSH ブルートフォース検知
template(name="SSHAlert" type="string"
string="SSH brute force detected: %msg%\nHost: %HOSTNAME%\nTime: %timereported%\n")
if $programname == 'sshd' and $msg contains 'Failed password' then {
action(type="omfile" file="/var/log/ssh-alerts.log")
# 外部スクリプト呼び出し
action(type="omprog" binary="/usr/local/bin/ssh-alert.sh")
}
Prometheus + Alertmanager でのログアラート
# Prometheus アラートルール(mtail等と組み合わせ)
groups:
- name: log_alerts
rules:
- alert: HighErrorRate
expr: rate(log_errors_total[5m]) > 10
for: 2m
labels:
severity: warning
annotations:
summary: "High error rate in logs"
description: "Error rate is {{ $value }}/s on {{ $labels.instance }}"
- alert: SSHBruteForce
expr: rate(ssh_failed_logins_total[5m]) > 5
for: 1m
labels:
severity: critical
annotations:
summary: "SSH brute force detected on {{ $labels.instance }}"
fail2ban(ログベースの自動防御)
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
backend = systemd
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 3
bantime = 86400
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
# fail2ban の状態確認
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 3
| |- Total failed: 45
| `- File list: /var/log/secure
`- Actions
|- Currently banned: 2
|- Total banned: 12
`- Banned IP list: 192.168.1.50 10.0.0.100
10. 監査ログ (auditd)
10.1 auditd の設定
auditd はカーネルの監査サブシステムであり、セキュリティ関連のイベントを詳細に記録する。
# インストール確認
$ rpm -qa | grep audit
audit-3.0.7-1.el9.x86_64
audit-libs-3.0.7-1.el9.x86_64
# サービス状態確認
$ sudo systemctl status auditd
$ sudo auditctl -s
enabled 1
failure 1
pid 1234
rate_limit 0
backlog_limit 8192
lost 0
backlog 0
メイン設定
# /etc/audit/auditd.conf
log_file = /var/log/audit/audit.log
log_group = root
log_format = ENRICHED
flush = INCREMENTAL_ASYNC
freq = 50
max_log_file = 50
num_logs = 10
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
# ネットワーク経由のログ転送
# tcp_listen_port = 60
# tcp_listen_queue = 5
# tcp_max_per_addr = 1
監査ルール
# /etc/audit/rules.d/audit.rules
# 既存ルールの削除
-D
# バッファサイズ
-b 8192
# 失敗時の動作(0=何もしない、1=printk、2=panic)
-f 1
# ============================================
# ファイルアクセス監視
# ============================================
# passwd, shadow, group ファイルの変更監視
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity
# sudoers の変更監視
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
# SSH設定の変更監視
-w /etc/ssh/sshd_config -p wa -k sshd_config
# cron設定の変更監視
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
-w /var/spool/cron/ -p wa -k cron
# ============================================
# システムコール監視
# ============================================
# ファイル削除の監視(uid >= 1000 の一般ユーザ)
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k file_deletion
# 権限昇格の監視
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k privilege_escalation
# ネットワーク設定変更の監視
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k network_changes
# 時刻変更の監視
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time_change
-w /etc/localtime -p wa -k time_change
# ログイン・ログアウトの監視
-w /var/log/lastlog -p wa -k logins
-w /var/run/faillock/ -p wa -k logins
-w /var/log/tallylog -p wa -k logins
# カーネルモジュールの操作監視
-a always,exit -F arch=b64 -S init_module -S delete_module -S finit_module -k kernel_modules
-w /sbin/insmod -p x -k kernel_modules
-w /sbin/rmmod -p x -k kernel_modules
-w /sbin/modprobe -p x -k kernel_modules
# ============================================
# 設定を不変にする(最後に記述)
# ============================================
-e 2
# ルールの適用
$ sudo augenrules --load
$ sudo auditctl -l # 現在のルール一覧表示
# ルールの一時追加
$ sudo auditctl -w /tmp/testfile -p rwxa -k test_watch
$ sudo auditctl -a always,exit -F arch=b64 -S open -F dir=/etc -F success=0 -k etc_access_fail
監査ルールのフラグ:
| フラグ | 説明 |
|---|---|
-w | ファイル/ディレクトリの監視 |
-p | パーミッション: r(read), w(write), x(execute), a(attribute) |
-k | キー(検索用タグ) |
-a | システムコールルールの追加 |
-F | フィルタ条件 |
-S | 監視するシステムコール |
10.2 ausearch
# キーで検索
$ sudo ausearch -k identity
----
time->Fri Apr 10 10:30:15 2026
type=CONFIG_CHANGE msg=audit(1712717415.123:456): auid=1000 ses=2 subj=unconfined op=updated_rules path="/etc/passwd" key="identity" list=4 res=1
# 時間範囲で検索
$ sudo ausearch --start 04/10/2026 09:00:00 --end 04/10/2026 17:00:00
# ユーザIDで検索
$ sudo ausearch -ua 1000
# システムコールで検索
$ sudo ausearch -sc execve
# 結果をインタプリット(人間が読みやすい形式)
$ sudo ausearch -k identity -i
----
type=CONFIG_CHANGE msg=audit(2026/04/10 10:30:15.123:456): auid=sysadmin ses=2 subj=unconfined op=updated_rules path="/etc/passwd" key="identity" list=exit res=yes
# 失敗したアクセスのみ
$ sudo ausearch --success no
# 特定のコマンド実行を検索
$ sudo ausearch -c sudo
# 特定ファイルへのアクセスを検索
$ sudo ausearch -f /etc/shadow
# CSV形式で出力
$ sudo ausearch -k identity --format csv
10.3 aureport
# サマリレポート
$ sudo aureport --summary
Summary Report
======================
Range of time in logs: 04/01/2026 00:00:00.000 - 04/10/2026 14:00:00.000
Selected time for report: 04/01/2026 00:00:00.000 - 04/10/2026 14:00:00.000
Number of changes in configuration: 45
Number of changes to accounts, groups, or roles: 12
Number of logins: 234
Number of failed logins: 56
Number of authentications: 345
Number of failed authentications: 78
Number of users: 15
Number of terminals: 8
Number of host names: 5
Number of executables: 45
Number of commands: 123
Number of files: 234
Number of AVC's: 0
Number of MAC events: 12
Number of failed syscalls: 890
Number of anomaly events: 3
Number of responses to anomaly events: 0
Number of crypto events: 567
Number of integrity events: 0
Number of virt events: 0
Number of keys: 8
Number of process IDs: 1234
Number of events: 12345
# 認証レポート
$ sudo aureport -au
Authentication Report
============================================
# date time acct host term exe success event
============================================
1. 04/10/2026 09:15:01 admin 192.168.1.100 ssh /usr/sbin/sshd yes 1234
2. 04/10/2026 09:20:15 root 192.168.1.50 ssh /usr/sbin/sshd no 1235
3. 04/10/2026 10:30:00 admin ? /dev/pts/0 /usr/bin/sudo yes 1236
# 失敗した認証のみ
$ sudo aureport -au --failed
# ログインレポート
$ sudo aureport -l
# ファイルアクセスレポート
$ sudo aureport -f
# 実行可能ファイルレポート
$ sudo aureport -x
# 異常イベントレポート
$ sudo aureport --anomaly
# キー別レポート
$ sudo aureport -k
Key Report
===============================================
# date time key success exe auid event
===============================================
1. 04/10/2026 10:30:15 identity yes /usr/sbin/useradd 1000 456
2. 04/10/2026 11:00:00 sudoers yes /usr/bin/vi 1000 789
3. 04/10/2026 12:15:30 sshd_config yes /usr/bin/vi 1000 1012
# 時間範囲指定
$ sudo aureport -au --start 04/10/2026 09:00:00 --end 04/10/2026 17:00:00
11. トラブルシューティング
rsyslog のトラブルシューティング
# rsyslog の構文チェック
$ rsyslogd -N 1
rsyslogd: version 8.2102.0, config validation run...
rsyslogd: End of config validation run. Bye.
# デバッグモードで起動
$ sudo rsyslogd -dn
# rsyslog の内部統計
$ sudo rsyslogd -N 1 -o fullmain
# ログが書き込まれない場合
# 1. パーミッション確認
$ ls -la /var/log/messages
-rw------- 1 root root 1234567 Apr 10 14:00 /var/log/messages
# 2. SELinux コンテキスト確認
$ ls -Z /var/log/messages
system_u:object_r:var_log_t:s0 /var/log/messages
# 3. ディスク容量確認
$ df -h /var/log
# 4. rsyslog のエラーログ確認
$ journalctl -u rsyslog --since "1 hour ago"
journald のトラブルシューティング
# ジャーナルの整合性チェック
$ journalctl --verify
PASS: /var/log/journal/abc123/system.journal
PASS: /var/log/journal/abc123/user-1000.journal
# ジャーナルのディスク使用量
$ journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.
# ジャーナルファイルの直接確認
$ ls -la /var/log/journal/*/
# ログが永続化されない場合
# 1. ディレクトリの存在確認
$ ls -la /var/log/journal/
# 2. 設定確認
$ grep Storage /etc/systemd/journald.conf
# 3. パーミッション確認
$ stat /var/log/journal/
auditd のトラブルシューティング
# 監査ログのバックログ確認
$ sudo auditctl -s
enabled 1
failure 1
pid 1234
rate_limit 0
backlog_limit 8192
lost 0 # ここが > 0 ならログロスト
backlog 45
# バックログが溢れる場合
$ sudo auditctl -b 16384 # バッファサイズを増加
# ルールが多すぎてパフォーマンスに影響する場合
$ sudo auditctl -l | wc -l # ルール数確認
# 特定ルールの除外(高頻度すぎるルール)
$ sudo auditctl -a never,exit -F dir=/tmp/high_io_dir
12. ベストプラクティス
ログ管理全般
- ログの集中管理を実装する -- 各サーバのログを1箇所に集約し、検索・分析を容易にする
- ログのローテーションを確実に設定する -- ディスク枯渇を防止
- タイムスタンプを統一する -- NTP でシステム時刻を同期し、全サーバで UTC または同一タイムゾーンを使用
- 構造化ログを採用する -- JSON 形式など、パーサブルなフォーマットを使用
- ログレベルを適切に設定する -- 本番環境では info 以上、デバッグが必要な場合のみ debug
セキュリティ
- 監査ログは分離して保存する -- 攻撃者による改竄を困難にする
- ログの転送は暗号化する -- TLS を使用
- ログの改竄検知を実装する -- ハッシュベースの整合性チェック
- アクセス権限を最小化する -- ログファイルの読み取り権限を制限
- コンプライアンス要件に従った保存期間を設定する -- PCI DSS は最低1年
パフォーマンス
- 非同期書き込みを使用する -- rsyslog の
-プレフィックスやバッファリング - レート制限を設定する -- ログストームによるシステム障害を防止
- 不要なログを早期にフィルタリングする -- 転送前に不要ログを除外
- ディスクI/O への影響を監視する -- 特に高トラフィック環境
保存と管理
# ログ保存期間の推奨値
# セキュリティログ: 最低1年(コンプライアンスに応じて)
# アプリケーションログ: 3-6ヶ月
# デバッグログ: 1-4週間
# アクセスログ: 3-12ヶ月
# ストレージ見積もりの例
# 1サーバあたり 1GB/日 のログ
# 10サーバ x 1GB/日 x 90日 = 900GB
# 圧縮率 ~10:1 = ~90GB の実ストレージ
ログ管理チェックリスト
| 項目 | 確認事項 |
|---|---|
| 収集 | 全サーバでログ収集エージェントが稼働しているか |
| 転送 | ログが集中サーバに到達しているか |
| 保存 | ローテーションが正しく動作しているか |
| 検索 | 必要なログを迅速に検索できるか |
| アラート | 重要イベントのアラートが設定されているか |
| 監査 | コンプライアンス要件を満たしているか |
| バックアップ | ログのバックアップが取られているか |
| アクセス制御 | ログへのアクセス権限が適切か |
13. 参考資料
- 公式ドキュメント:
- RFC:
- RFC 5424 -- The Syslog Protocol
- RFC 5425 -- Transport Layer Security (TLS) Transport Mapping for Syslog
- man ページ:
man rsyslog.conf,man journalctl,man logrotate,man auditd,man auditctl,man ausearch,man aureport
最終更新: 2026-04-10
対象OS: RHEL 8/9, Ubuntu 22.04/24.04, 及び systemd ベースの主要Linuxディストリビューション