「ログサーバーのディスク、1年もつと思っていたら半年で一杯になりました」
「監査で『ログが改ざんされていないことを示してください』と言われました」
ログの集め方(第2回〜第6回)が分かっても、どこに、どれだけの期間、どう守って置くかを決めないと、容量が足りなくなったり、肝心なときに証拠として使えなかったりします。
第7回では、ログ集約基盤の設計を扱います。構成、冗長、容量、保存期間、改ざん防止、時刻、個人情報まで、設計で決めることを一通り見ていきます。
集約基盤の全体構成
ログ集約基盤は、送信元、中継、保存、分析の4つの層に分けて考えると整理しやすくなります。

| 層 | 役割 | 主な製品・機能 | 設計の注意 |
|---|---|---|---|
| 送信元 | ログを生み、最初に送り出す | rsyslog・journald、Windows(WEF・エージェント)、機器の logging host | 時刻の同期、送れないときのキュー、送信先の冗長 |
| 中継(拠点) | 拠点内の機器をまとめて本社・クラウドへ | rsyslog、Fluent Bit、Vector | 回線断に備えたディスクキュー、TLS、帯域 |
| 中継(DMZ) | DMZ の機器のログを内側へ渡す | rsyslog(受信と転送だけ) | ファイアウォールの許可を「中継1台→ログサーバーの 6514」だけにする |
| 保存 | 原本を決めた期間残す | ログサーバーのファイル、S3 などのオブジェクトストレージ | 圧縮、WORM、世代の管理、ディスク容量の監視 |
| 分析 | 索引を作り、検索・集計・警報 | OpenSearch、Elasticsearch、Loki、Splunk、SIEM | 索引の保持は原本より短くてよい。費用が大きい |
| 基盤の監視 | 基盤そのものが動いているか | rsyslog の impstats、ダッシュボード | ログの途絶を検知する(第8回) |
- 層を分けておくと、原本の保存と検索用の索引を、別の期間・費用で設計でき、分析基盤を入れ替えても原本は残る
- DMZの機器それぞれに内側への通信を許すと、ファイアウォールの穴が機器の数だけ増える。DMZに中継を1台置けば、内側へ開けるのは中継からログサーバーへのTLSの1本で済む
- 小さな環境では1台で兼ねてもかまわないが、役割は分けて考える
冗長とバッファー
ログが欠けるのは、受信側が止まったとき、回線が切れたとき、障害や攻撃でログが急増したときです。対策は「送れない間はためておく」と「受ける側を複数にする」の2つです。

- rsyslogでは、転送のアクションにディスクを使うキュー(第4回)を付けると、送り先が止まっている間はディスクにため、復旧後に順に送る
- キューの大きさは「送り先が何時間止まっても耐えるか」で決め、その時間のログ量が入るよう
queue.maxDiskSpaceを設定する - 中継も2台にして、仮想IPやロードバランサーで束ねる
- UDPは送った側に失敗が分からず、ためられない。欠けては困るログはTCPかTLSで送り、受信の確認まで要るならRELPを使う(第2回)
2台への二重送信とロードバランサー
# 二重送信:アクションごとに別のキュー(片方が止まっても他方へは送り続ける)
action(type="omfwd" target="log1.corp.example.jp" port="6514" protocol="tcp"
StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/name"
queue.type="LinkedList" queue.filename="fwd_log1" queue.maxDiskSpace="2g"
queue.saveOnShutdown="on" action.resumeRetryCount="-1")
action(type="omfwd" target="log2.corp.example.jp" port="6514" protocol="tcp"
StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/name"
queue.type="LinkedList" queue.filename="fwd_log2" queue.maxDiskSpace="2g"
queue.saveOnShutdown="on" action.resumeRetryCount="-1")
# 振り分け(8.2408 以降):target を配列にすると、生きている相手へ順番に送る(TCP のみ)
action(type="omfwd" target=["log1.corp.example.jp", "log2.corp.example.jp"]
port="6514" protocol="tcp" queue.type="LinkedList" queue.filename="fwd_pool")
- 二重送信は、2台が同じログを持つ。1台が壊れても欠けないが、保存と分析の費用は2倍になる
- 振り分けは、1件をどちらか一方へ送る。容量は増えないが、1台が壊れるとその分のログを失うため、保存側で複製する。UDPで配列を書くと、先頭の1台にしか送らない
- ロードバランサーで束ねる場合、TCPは接続単位で振り分けるため偏りやすい(
RebindIntervalで定期的につなぎ直す)。UDPはヘルスチェックをTCPなどで別に行う。送信元IPを書き換える構成では、ログサーバーから送信元がLBに見えるので、送信元IPを保つ方式を選ぶ
容量の見積もり
冒頭の「1年もつはずが半年で一杯」は、見積もりの問題です。

- 1日のログ量は「EPS(1秒あたりのイベント数)× 1件の平均サイズ × 86,400秒」、保存に要る容量は「1日のログ量 × 保存日数 × 圧縮率(圧縮後の大きさの割合)」
- EPSは機器の種類で大きく違い、ファイアウォール、プロキシ、ドメインコントローラーは多く、一般のLinuxサーバーは少なめ。1件の大きさも、syslogの1行は数百バイト程度だが、WindowsのイベントをXMLやJSONにすると1KBを超えることがある
- 代表的な機器で1週間ほど実測するのが確実
- 平均だけで設計してはいけない。障害や攻撃の最中、朝のログオンが集中する時間帯には、平常の数倍から10倍のログが出る。帯域、キュー、取り込み性能はピークで見積もり、検索基盤には索引と複製の分も加える
数値例と実測
| 送信元 | 台数×EPS | 1件の平均 | 1日の量 |
|---|---|---|---|
| Linux サーバー | 200台×2=400 | 300 B | 約10.4 GB |
| Windows サーバー | 100台×3=300 | 1,000 B | 約25.9 GB |
| ドメインコントローラー | 3台×200=600 | 1,000 B | 約51.8 GB |
| ファイアウォール | 2台×300=600 | 400 B | 約20.7 GB |
| ネットワーク機器・ESXi | 60台×1=60 | 300 B | 約1.6 GB |
| 合計 | 1,960 EPS | — | 約110 GB/日 |
# Linux(ログサーバー):送信元ごとに日付で分けて保存している場合の、1日の件数と量
$ cat /var/log/remote/*/2026-09-25.log | wc -l
$ du -ch /var/log/remote/*/2026-09-25.log | tail -1
# Windows(PowerShell):直近1時間のセキュリティログの件数から EPS を求める
PS> $n = (Get-WinEvent -FilterHashtable @{LogName='Security'; StartTime=(Get-Date).AddHours(-1)}).Count
PS> [math]::Round($n / 3600, 1)
PS> Get-WinEvent -ListLog Security | Select-Object LogName, RecordCount, FileSize
数値は説明用の仮定です。1年分の原本は約110 GB × 365日=約40 TBで、テキストのログはgzipで数分の1から10分の1程度になるため、4〜8 TBが目安です。検索基盤に90日置くと約10 TB、複製を1つ持てば約20 TBになります。ピークは平常の10倍(約2万EPS、帯域は平均約10 Mbpsに対し約100 Mbps)を見込みます。
保存期間:法令・基準・社内規程
| 根拠 | 求める内容 | 期間 | 備考 |
|---|---|---|---|
| PCI DSS v4.0.1 要件 10.5.1 | 監査ログの履歴を保存する | 12か月以上。直近3か月はすぐ分析できる状態 | カード会員データを扱うシステム |
| NISC の調査報告書(2011年度) | 政府機関の情報システムのログ | 1年以上 | 政府機関向けの報告書の提言 |
| 刑事訴訟法 197条3項 | 捜査機関が通信履歴を消さないよう求める(保全要請) | 30日以内。延長しても通算60日まで | 求められたら残せる仕組みが要る |
| 個人情報保護法 22条 | 不要になった個人データは遅滞なく消去する(努力義務) | 期間の定めなし | 長く持ちすぎない根拠になる |
| ISO/IEC 27001:2022 附属書A 8.15 | ログを取得・保存・保護・分析する | 組織が決める | ISMS の規程に期間を書く |
| 米国 OMB M-21-31 → M-26-14 | 連邦政府機関のログ | 12か月+コールド18か月(2021年)→2026年5月に撤回し、リスクに応じて決める方式へ | 量より「何に答えるためのログか」 |
| 社内規程の例 | 情報セキュリティ規程、文書管理規程 | 認証・操作のログ1年、通信のログ90日〜1年など | 監査・契約・業界の要件と合わせる |
ログの保存期間を一律に定めた法令は少なく、多くは業界の基準や社内規程で決めます。「長いほど安全」ではありません。費用と個人情報の扱いの両面から、ログの種類ごとに期間を決めて規程に書き、期間を過ぎたら確実に消します。
ホットとコールドの分け方

- ログの検索は直近の数日から数週間に集中し、古いログを開くのは監査や事故の調査のときくらい。そこで、すぐ検索できる高価な場所(ホット)と、安いが取り出しに時間のかかる場所(コールド)に分ける
- 例えば直近90日は検索基盤に索引付きで置き、古いものは圧縮した原本をオブジェクトストレージに移し、1年を過ぎたら消す。PCI DSSの「直近3か月はすぐ分析でき、12か月保存」は、この分け方そのもの
- 移動と削除は手作業にせず、ElasticsearchのILM、OpenSearchのISM、S3のライフサイクルで自動化する
- 取り出しの時間と費用に注意。S3 Glacier Deep Archiveは、標準の取り出しに12時間以内かかる。「監査で求められたら何日以内に出すか」から逆算して置き場所を選ぶ
改ざん防止の考え方
冒頭の「改ざんされていないことを示して」への答えです。管理者の権限を奪った攻撃者は、足跡を消すために、まずログを消します。

手元のログは書き換えられる前提で、次の4つを組み合わせて守ります。
- 作られたらすぐ外へ送る:集約先に届いていれば、あとで手元を消されても残る
- WORM(Write Once Read Many):保存先を追記だけにし、決めた期間は削除も上書きもできないようにする
- ハッシュや署名:書き換えや途中の削除に気づけるようにする
- 権限の分離:ログの保存先は、別の管理者・別の認証・クラウドなら別のアカウント(第9回)で管理する
ログを消す・止める操作そのもの(Windowsの1102、CloudTrailのStopLogging)も監視します(第8回)。
改ざん防止の手段
| 手段 | 仕組み | 例 | 注意 |
|---|---|---|---|
| WORM | 決めた期間、削除・上書きできない | S3 Object Lock(コンプライアンスモード)、ストレージ製品の WORM 機能 | コンプライアンスモードは root でも期間中は消せない。期間の誤設定に注意 |
| ハッシュ | ファイルのハッシュを別の場所に記録し、後で照合する | Linux は sha256sum、Windows は Get-FileHash -Algorithm SHA256、CloudTrail のダイジェスト(第9回) | ハッシュを同じ場所に置くと一緒に書き換えられる |
| ハッシュチェーン | 前のハッシュを次に含め、途中の削除・挿入を検知する | journald の Forward Secure Sealing(journalctl –setup-keys、–verify) | 検証用の鍵はサーバーの外に保管する |
| 署名 | 送信元が署名し、受け手が検証する | RFC 5848(署名付き syslog)、rsyslog の omfile の署名(KSI) | RFC 5848 の実装はごく少ない |
| 権限の分離 | 保存先の削除権限を別の管理者・別のアカウントに置く | ログアーカイブ用アカウント、SCP による禁止 | 日常の管理者に削除権限を渡さない |

RFC 5848は、主要なsyslog製品では標準の機能として広まっていません。実務では、TLSでの転送(第5回)と、保存先のWORM・ハッシュ・権限の分離を組み合わせるのが現実的です。
時刻とタイムゾーン
Sep 26 10:23:45 web01 sshd[1234]: Failed password ... # RFC 3164:年・TZ なし
2026-09-26T10:23:45.678+09:00 web01 sshd[1234]: Failed password ... # オフセット付き
2026-09-26T01:23:45.678Z web01 sshd[1234]: Failed password ... # UTC
# rsyslog:送信元が書いた時刻と、受信した時刻を両方残す
template(name="RemoteBoth" type="string"
string="%timereported:::date-rfc3339% %timegenerated:::date-rfc3339% %HOSTNAME% %syslogtag%%msg%\n")
# Windows:イベントは UTC で記録され、表示のときに現地時刻になる
PS> (Get-WinEvent -LogName System -MaxEvents 1).TimeCreated.ToUniversalTime().ToString('o')
2026-09-26T01:23:45.6780000Z
- RFC 3164の形式には、年もタイムゾーンもない。受信側が年を補うため、年末年始や遅れて届いたログで年を誤ることがあり、UTCかJSTかも分からない(第2回)
- 記録はUTC、またはオフセット付き(RFC 3339)にそろえ、ミリ秒まで残す。すべての機器の時刻をNTPで合わせる(連載「NTP入門」第7回・第11回)
- 受信時刻(timegenerated)も残すと、送信元の時計のずれや、キューにたまって遅れて届いたことに気づける(機器側の設定は第6回)
個人情報・パスワードとマスキング
| ログに出てしまうもの | 例 | 対策 |
|---|---|---|
| パスワードの誤入力 | ユーザー名の欄にパスワードを打ち、ログオン失敗(4625、sshd の Invalid user)に残る | 集約先の閲覧権限を絞る。検索画面で既定で伏せる |
| URL のトークン・セッション ID | アクセスログの ?token=… | Web サーバーのログ書式で除く、送る前に置換する |
| 個人情報 | メールアドレス、氏名、IP アドレスとユーザー ID の組 | 必要な項目だけ残す。ハッシュ化・仮名化する |
| 秘密情報 | API キー、接続文字列(デバッグログ) | アプリで出さない。出たら鍵を失効させる |
# rsyslog:IPv4 アドレスの下位8ビットを0にする(192.0.2.10 → 192.0.2.0)
module(load="mmanon")
action(type="mmanon" ipv4.bits="8" ipv6.enable="off")
# Vector(VRL):メールアドレスの形をした文字列を伏せる
.message = redact(.message, filters: [r'[\w.+-]+@[\w-]+(\.[\w-]+)+'])
IPアドレスやユーザーIDも、ほかの情報と照合して個人を識別できるなら、個人情報として扱います(第1回)。マスキングは中継で行うのが基本ですが、調査に必要な情報まで消さないよう、原本は権限を絞って保存し、分析基盤では伏せる、という分け方もあります。CloudWatch Logsのデータ保護ポリシー(第9回)のように、取り込み時に伏せる機能もあります。
構造化ログ(JSON)と新しい収集ツール
# アプリが1行1件の JSON で出す例
{"ts":"2026-09-26T01:23:45.678Z","level":"warn","app":"order","trace_id":"4bf92f35","order_id":"A1234","msg":"payment retry","retry":2}
# rsyslog:メッセージ中の JSON を取り出す(find-json は 8.2510 以降。旧版は @cee: で始まる行だけの cookie モード)
module(load="mmjsonparse")
action(type="mmjsonparse" mode="find-json")
# JSON で書き出すテンプレート(取り出した項目は $!名前 で参照)
template(name="JsonOut" type="list" option.jsonf="on") {
property(outname="@timestamp" name="timereported" dateFormat="rfc3339" format="jsonf")
property(outname="host" name="hostname" format="jsonf")
property(outname="app" name="$!app" format="jsonf")
property(outname="message" name="msg" format="jsonf")
}
取り出した項目は、テンプレートの中で$!名前で参照します(上の例の$!app)。find-jsonは8.2510以降の機能で、旧版は@cee:で始まる行だけを解析するcookieモードです。
- 利点:項目名が付いているので、正規表現で切り出さずに検索・集計できる。項目を増やしても解析の設定が壊れにくく、改行を含む内容も1件に収まる
- 時刻(UTC)、レベル、アプリ名、要求ID・トレースIDを必ず入れ、項目名を組織で統一する(ECSやOpenTelemetryのセマンティック規約が参考になる)
- 欠点:1件が大きくなり、人が目で読みにくい。syslogで運ぶなら、メッセージ長の上限(第2回)に注意
- OS標準のrsyslogの版は古い場合がある(第4回)。
find-jsonを使うなら版を確かめる
| 項目 | Fluent Bit | Vector | OpenTelemetry Collector |
|---|---|---|---|
| 開発・ライセンス | Fluent プロジェクト(CNCF の Graduated、Fluentd と同じ組織)、Apache 2.0 | Datadog が保守、MPL 2.0、CNCF 外 | CNCF(2026年5月に Graduated)、Apache 2.0 |
| 現行版(2026年9月) | v5.1(C 言語、軽量) | v0.58(Rust、1.0 未満) | v0.161(安定部分は v1.67、Go) |
| 得意なこと | 軽さ。Kubernetes・ECS の収集役の定番(AWS の FireLens) | VRL による変換・マスキング、処理性能 | ログ・メトリクス・トレースを1つの形式(OTLP)で扱う |
| syslog の受信 | syslog 入力(RFC 3164・5424、UDP・TCP) | syslog ソース(UDP・TCP、TLS) | syslog レシーバー(beta、RFC 3164・5424、TCP は TLS 可) |
| 主な送り先 | OpenSearch、Loki、S3、CloudWatch Logs、Kafka、OTLP | 左に加え Splunk HEC、Datadog など | OTLP に対応した基盤、各社のエクスポーター |
OpenTelemetryのログのデータモデル(Stable)は、発生時刻(Timestamp)と収集時刻(ObservedTimestamp)、SeverityNumber、Body、Attributesなどを定めます。rsyslogにもOTLPで送るomotelがあり、syslogはrsyslogのまま、アプリやコンテナは新しいツールで併用するのが現実的です。
考えてみよう
- 自分の職場のログの流れを、送信元・中継・保存・分析の4層に当てはめて描いてください。1台止まるとログが欠ける所はどこですか。
- この記事の式で、自分の環境の1日のログ量と1年分の容量を見積もってください。いちばん量の多い送信元はどれですか。
- 管理者のアカウントを乗っ取られたとき、攻撃者に消されないログはどれですか。消されたことに誰が気づけますか。
ヒント:この記事の冗長とバッファーの図、容量の見積もりの式と数値例、改ざん防止の4つの考え方が手がかりです。
まとめ
- 基盤は送信元 → 中継 → 保存 → 分析の4層。原本と索引は別の期間・費用で設計する
- 送れない間はディスクキューにため、受け手は2台で束ねる。UDPはためられない
- 容量はEPS×1件×86,400×日数×圧縮率。平均ではなくピークと、索引・複製の分も
- 保存期間はログの種類ごとに規程で決め、過ぎたら消す。「長いほど安全」ではない
- 直近はホット、古いものはコールドへ。移動と削除は自動化し、取り出しの時間も確かめる
- 改ざん防止はすぐ送る・WORM・ハッシュ・権限の分離。消す操作も監視する
- 時刻はUTCかオフセット付き、受信時刻も残す。個人情報は原本は絞り、分析では伏せる
次回は、集めたログを検索・監視して異常に気づく仕組み(検索基盤とSIEM)を扱います。
連載「syslog入門」全11回
全回の目次と、読む順番・目的別の読み方は、syslog入門の入口のページにまとめています。
- ログとは・なぜ集めるか
- syslogの基本
- Linuxのログの仕組み
- rsyslog 前編
- rsyslog 後編
- Windows・ネットワーク機器のログ
- ログ集約基盤の設計(この記事)
- 分析と監視・SIEM
- クラウドのログ
- syslogのトラブルシュート
- ログ管理の設計演習


コメント