# GuardDuty の誤検知とノイズを抑える運用：Suppression Rule・信頼 IP リスト・脅威リストの正しい使い分け

> Amazon GuardDuty のノイズ・誤検知を本番品質で抑えるチューニング実装ガイド。Suppression Rule（既知ノイズの自動アーカイブ）・信頼 IP/エンティティリスト（既知の正規ソースから finding を出さない）・脅威リスト（既知の悪性ソースから finding を出す）の3つの道具を、症状→正しい道具のマッピングで使い分けます。抑制された finding は Security Hub/S3/Detective/EventBridge に届かず、Extended Threat Detection の相関材料にもならない——広すぎる抑制が Critical な攻撃シーケンスを丸ごと不可視化する罠と、reactive・スコープ最小・IaC 中心の運用ルールを、Terraform/CLI の実コードで解説します。

- 公開日: 2026-06-27
- 著者: 友田 陽大
- タグ: セキュリティ, AWS, GuardDuty, 運用設計, Terraform
- URL: https://tomodahinata.com/blog/aws-guardduty-suppression-rules-trusted-ip-threat-lists-tuning-guide
- カテゴリ: Amazon GuardDuty 本番運用
- 総合ガイド: https://tomodahinata.com/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide

## 要点

- ノイズは対応の敵だが、間違ったチューニングは『攻撃も一緒に隠す』。道具は3つ・役割も3つ——Suppression Rule（既知ノイズの finding パターンを自動アーカイブ）・信頼 IP/エンティティリスト（既知の正規ソースから finding を出さない）・脅威リスト（既知の悪性ソースから finding を出す）
- 抑制された finding は Security Hub CSPM・S3・Detective・EventBridge に送られず、Malware Protection for EC2 のスキャンも起動しない。ただし finding 自体は生成され、archived として90日間保存される（service.archived = true で参照可）
- 最大の罠：Extended Threat Detection はアーカイブ済み（抑制で自動アーカイブされたものを含む）finding を攻撃シーケンスの相関材料にしない。型を丸ごと消す広い抑制は Critical な多段攻撃を不可視化する。抑制は reactive に・特定の挙動へ絞る
- リストの制限：信頼エンティティ1＋信頼 IP リスト1、脅威リスト最大6（アカウント×リージョンあたり）。IPv4 のみ・公開アドレス/ドメインのみ・信頼が脅威に優先。S3 ファイル編集後は再アクティベート必須（約15分、最大40分）。Runtime Monitoring 以外の全プランに適用
- コストの誤解：Suppression Rule は GuardDuty コストを下げない（課金は finding 数ではなく解析量）。信頼リストは finding を減らすが、データは依然として解析される。チューニングはコスト最適化の道具ではない

---

「GuardDuty を入れたらアラートが鳴りやまない。で、全部ミュートしました」——AWS のセキュリティ運用を相談される場で、わりと聞く台詞です。

そして、これはたいてい**危険な一手**です。脆弱性スキャナの定期 portscan、bastion への SSH ブルートフォース、オンプレ GW 経由の通信——確かに正規の運用が finding を量産し、ダッシュボードは赤く埋まります。けれど「うるさいから型ごと消す」をやると、**その finding が本来束ねるはずだった Critical な攻撃シーケンスまで、一緒に消えています**。ノイズは対応の敵ですが、**間違ったチューニングは攻撃そのものを隠す**——これがこの記事の通底するテーマです。

この記事は、[GuardDuty 本番設計のピラー記事](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)の7章「誤検知とノイズを抑える」を、単独で一本書けるだけの深さに掘り下げる**スポーク**です。GuardDuty のチューニングには道具が3つあり、それぞれ**役割がまったく違います**。この使い分けを間違えると、ノイズも減らず・コストも減らず・むしろ検知能力だけが削れる、という最悪が起きます。逆に正しく使い分ければ、**「対応すべき finding だけが残り、攻撃の文脈は失われない」**運用になります。題材として、私がマルチアカウント AWS 上の[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で IAM・可観測性・DR を横断実装した経験——**実際の金銭・カーボンクレジット・地域通貨を扱うため、「ノイズに埋もれて本物の侵害を見逃す」ことが許されなかった**——という視点も交えます。

> **この記事のルール**：Suppression Rule・信頼リスト・脅威リストの仕様・制限・挙動は **AWS 公式ドキュメント（2026年6月時点）** に基づきます。リストの上限・対応形式・適用範囲は改定されるため、本番投入前に必ず公式の最新情報を確認してください。そしてもう一つの鉄則——**チューニングは絶対に「本物の攻撃を見えなくする」方向に倒してはいけません**。抑制は reactive に（繰り返し誤検知だと確認できたものだけ）・スコープを最小に・コンソールのクリックではなく IaC で（レビュー可能・再現可能に）行います。

---

## 0. メンタルモデル：3つの道具・3つの仕事

設計を始める前に、3つの道具が**それぞれ別の問題を解いている**ことを一行で固定します。混同が、ほぼすべての事故の原因です。

> **GuardDuty のチューニング道具は3つ。「既知の無害な finding パターン」を消すのが Suppression Rule、「既知の正規ソース」から finding を出さないのが信頼リスト、「既知の悪性ソース」から finding を出すのが脅威リスト。」**

| 道具 | 解く問題 | 何に効くか | 公式の挙動 |
| --- | --- | --- | --- |
| **Suppression Rule（抑制ルール）** | 正規運用が生む**既知の finding パターン**がうるさい | finding **型 ＋ 絞り込み属性**にマッチする新規 finding を**自動アーカイブ** | フィルタ条件にマッチした新規 finding を archive。Security Hub/S3/Detective/EventBridge に送らない |
| **信頼 IP / エンティティリスト（Trusted list）** | **既知の正規ソース**（自社固定 IP・監視 SaaS）からの通信で finding が出る | 載せた IP/ドメインからの活動について **finding を生成しない** | trusted に載った entry については finding を生成しない |
| **脅威リスト（Threat list）** | **自前で「悪性」と判断したソース**を検知したい | 載せた IP/ドメイン/ハッシュへの活動で **finding を生成する** | threat に載った entry に関わる活動で finding を生成する |

3つの違いを、もう一段はっきりさせます。

1. **Suppression Rule は「finding の側」を見る。** 「この**型の finding が、この条件で出たら**、それは無害だからアーカイブ」という後段のフィルタです。たとえば「`Recon:EC2/Portscan` が、自社脆弱性スキャナの AMI から出たら無害」。GuardDuty は finding を**いったん生成してから**アーカイブします（だから後述のとおり、解析コストは変わりません）。
2. **信頼リストは「ソースの側」を見る。** 「この IP/ドメインは信頼できるから、そもそも finding を**生成しない**」という前段のフィルタです。たとえば「自社の固定 egress IP からの通信は finding にしない」。
3. **脅威リストは信頼リストの裏返し。** 「この IP/ドメイン/ハッシュは悪性だから、関わったら finding を**生成する**」。自前の脅威インテリジェンスを GuardDuty の検知に持ち込む道具です。

この3点を押さえると、チューニングは **「①ノイズの正体は『finding パターン』か『ソース』か → ②パターンなら抑制・ソースなら信頼リスト → ③自前で検知を足したいなら脅威リスト」** という分岐に整理できます。そして全体を貫く制約が——**どれを使っても、本物の攻撃（特に Extended Threat Detection が束ねる多段攻撃）を見えなくしてはいけない**こと。順に深掘りします。

---

## 1. Suppression Rule（抑制ルール）の深掘り：何が起き、何が起きないか

最も誤解の多い道具がこれです。「抑制＝finding を消す」と思っていると、**消えていないものまで消えたつもりになる**——そこが事故の入口です。

### 1.1 抑制ルールの正体は「action = ARCHIVE のフィルタ」

公式の定義はシンプルです。Suppression Rule とは、**フィルタ属性と値の組み合わせ（criteria）で、マッチした新規 finding を自動的にアーカイブするルール**です。GuardDuty のフィルタ機能そのものを、`action` を `ARCHIVE` にして使うと抑制ルールになります（Terraform の `aws_guardduty_filter` でいう `action = "ARCHIVE"`）。

公式が明示する「2条件パターン」が、設計の基本形です。**第1条件に finding 型、第2条件にスコープを絞る属性**（AMI・タグ・IP など）を置きます。これは偶然ではなく、公式の推奨例がすべてこの形です。

```bash
# 抑制ルールは「action=ARCHIVE のフィルタ」。CLI/API では create-filter で作る。
# 公式の2条件パターン: ①finding 型 + ②スコープを絞る属性。
# 例: 自社の脆弱性スキャナ（特定 AMI）が出す Recon:EC2/Portscan だけを抑制する。
aws guardduty create-filter \
  --detector-id "$DETECTOR_ID" \
  --name "suppress-portscan-from-vuln-scanner" \
  --action ARCHIVE \
  --rank 1 \
  --finding-criteria '{
    "Criterion": {
      "type": { "Equals": ["Recon:EC2/Portscan"] },
      "resource.instanceDetails.imageId": { "Equals": ["ami-0a7a207083example"] }
    }
  }'
```

> **フィルタの仕様（公式・要点）**：1つのフィルタには**最低1・最大50の属性**を指定でき、`Equals`/`NotEquals` は1属性あたり**最大50値**。**異なる属性どうしは AND**、同一属性の複数値は AND/OR で評価されます。つまり上の例は「型が Portscan **かつ** AMI が一致」の AND——だから**スコープが狭く絞られる**。これが「型だけ」の危険な抑制との決定的な差です。

### 1.2 「抑制された finding」に何が起き、何が起きないか（最重要の事実）

ここが本章の核心です。公式の挙動を正確に押さえないと、運用を誤ります。

| 抑制された finding に**起きないこと**（送られない／起動しない） | 抑制された finding に**起きること**（残る） |
| --- | --- |
| AWS Security Hub CSPM に**送られない** | finding 自体は**生成される**（解析は止まらない） |
| Amazon S3 に**エクスポートされない** | **archived（アーカイブ済み）**として保存される |
| Amazon Detective に**送られない** | GuardDuty 内に**90日間**保存され、その間いつでも閲覧可能 |
| Amazon EventBridge に**送られない**（＝自動対応も発火しない） | コンソールの **Archived** か、API `ListFindings` の `service.archived = true` で参照可能 |
| Malware Protection for EC2 の**マルウェアスキャンを起動しない** | （= ETD の相関材料にはならない。3章で詳述） |

公式の表現をそのまま借りれば——**「抑制された finding は AWS Security Hub CSPM・Amazon S3・Amazon Detective・Amazon EventBridge に送られない。Malware Protection for EC2 を有効化していても、抑制された finding はマルウェアスキャンを起動しない」**。一方で**「GuardDuty は抑制ルールにマッチしても finding を生成し続け、ただし自動的に archived としてマークする。archived な finding は90日間 GuardDuty に保存され、その期間いつでも閲覧できる」**。

この非対称が、抑制の本質です。**「通知・連携の経路からは外れるが、データとしては消えていない」**。だから——

```bash
# 抑制で消したつもりの finding を、archived として掘り起こして監査する。
# service.archived = true が「抑制された（またはユーザーがアーカイブした）finding」の母集合。
aws guardduty list-findings \
  --detector-id "$DETECTOR_ID" \
  --finding-criteria '{ "Criterion": { "service.archived": { "Equals": ["true"] } } }'
```

> **設計への含意**：抑制は「ダッシュボードと通知を静かにする」道具であって、「**検知を止める**」道具ではありません。finding は90日残るので、**「実は抑制で消していた中に本物が紛れていなかったか」を後から監査できます**。ただし——次章で見るとおり、**Extended Threat Detection はこのアーカイブ済みを相関材料にしない**ため、「残っているから安全」とは言い切れません。

### 1.3 マルチアカウントでは「管理者だけ」が抑制を作れる

公式の Note は明確です——**マルチアカウント環境では、GuardDuty 管理者（委任管理者）だけが抑制ルールを作成できます**。メンバーアカウントの担当者が勝手にノイズを消すことはできません。これは統制上むしろ望ましい挙動です：**「誰がどの検知を消したか」が委任管理者アカウントに一元化**され、レビューと監査の対象を1か所に絞れます。組織での委任管理者の立て方は[マルチアカウント統制のスポーク記事](/blog/aws-guardduty-multi-account-organizations-delegated-administrator-terraform-guide)で扱います。

### 1.4 公式の代表的な抑制ユースケース（すべて「型＋絞り込み」の2条件）

公式が**「reactive に・繰り返し誤検知だと確認できた finding にのみ作れ」**と明記したうえで挙げる、代表ユースケースです。共通点は**例外なく「型＋スコープ属性」の2条件**であること——型だけで消す例は1つもありません。

| ユースケース | 第1条件（型） | 第2条件（絞り込み） | なぜ無害か |
| --- | --- | --- | --- |
| オンプレ GW 経由の egress | `UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS` | **API caller IPv4 address**（オンプレ GW の IP/CIDR） | Outposts や VPC VPN で内向きに抜ける正規構成。複数 IP は条件を追加 |
| 脆弱性スキャナの portscan | `Recon:EC2/Portscan` | **Instance image ID**（スキャナの AMI）または **Tag** | 自社の脆弱性評価ツールが意図的に portscan している |
| bastion への SSH ブルートフォース | `UnauthorizedAccess:EC2/SSHBruteForce` | **Instance tag value**（bastion を識別するタグ） | bastion は外から叩かれるのが想定挙動 |
| 意図的に公開した web サーバ | `Recon:EC2/PortProbeUnprotectedPort` | **Instance tag key**（公開サーバを識別するタグ） | web サーバは公開ポートを持つのが正常 |
| coredns の DNS 重複（Runtime） | `Trojan:Runtime/*!DNS` 等の DNS 系 Runtime finding | **Executable path** または **Executable SHA-256**（DNS サーバ pod のプロセス） | K8s は coredns 等が pod として DNS を引くため、pod 側とサーバ pod 側で**2重に DNS イベント**が出る |

最後の coredns のケースだけ補足します。公式によれば、Kubernetes クラスタは `coredns` のような DNS サーバを pod として動かすため、**各 DNS ルックアップにつき2つの DNS イベント**（pod 由来とサーバ pod 由来）が記録され、`Backdoor:Runtime/C&CActivity.B!DNS` などの**重複 finding**を生みます。これを `executablePath` か `executableSha256`（任意で第3条件に `Kubernetes container image`）で絞って抑制する——これも「型だけ」ではなく**プロセス単位まで絞り込む**好例です。

```bash
# coredns 由来の DNS finding 重複を、DNS サーバ pod のプロセスに絞って抑制。
# 型だけで消すと本物の C&C 通信まで消える。executableSha256 で「自分の coredns」に限定する。
aws guardduty create-filter \
  --detector-id "$DETECTOR_ID" \
  --name "suppress-coredns-dns-duplicates" \
  --action ARCHIVE \
  --rank 2 \
  --finding-criteria '{
    "Criterion": {
      "type": { "Equals": ["Backdoor:Runtime/C&CActivity.B!DNS"] },
      "service.runtimeDetails.process.executableSha256": { "Equals": ["<your-coredns-sha256>"] }
    }
  }'
```

---

## 2. Suppression Rule を IaC で管理する（Terraform）

コンソールのクリックで抑制ルールを作るのは**アンチパターン**です。「誰が・いつ・なぜ・どの条件で検知を消したか」がレビューできず、再現もできません。抑制は**検知能力を削る変更**なので、最もレビューが必要なはずの操作です。だから IaC で。

```hcl
# 抑制ルール = action = "ARCHIVE" の aws_guardduty_filter。
# action の許容値は "ARCHIVE"（抑制）か "NOOP"（通常フィルタ）。
# 公式の2条件パターンを criterion 2つで表現する。
resource "aws_guardduty_filter" "suppress_scanner_portscan" {
  name        = "suppress-portscan-from-vuln-scanner"
  detector_id = aws_guardduty_detector.this.id
  action      = "ARCHIVE" # ← これが「フィルタ」を「抑制ルール」にする
  rank        = 1         # フィルタの適用順（小さいほど先に評価）

  # なぜ消すかを description に必ず残す（レビューと棚卸しのための監査証跡）。
  description = "Vuln scanner (AMI ami-0a7a2070...) intentionally port-scans; benign. Reactive, scoped by imageId."

  finding_criteria {
    # 第1条件: finding 型を1つに固定（型を丸ごと広く消さない）。
    criterion {
      field  = "type"
      equals = ["Recon:EC2/Portscan"]
    }
    # 第2条件: スキャナの AMI に限定（ここが無いと全 Portscan を消す危険な抑制になる）。
    criterion {
      field  = "resource.instanceDetails.imageId"
      equals = ["ami-0a7a207083example"]
    }
  }
}
```

このコードの設計判断を明示します。

- **`action = "ARCHIVE"` が抑制の本体。** Terraform の `aws_guardduty_filter` の `action` は `"ARCHIVE"`（抑制）か `"NOOP"`（保存はするがアーカイブしない通常フィルタ）の2択です。抑制したいなら `ARCHIVE`。
- **criterion は必ず2つ以上。** 公式パターンどおり「型＋絞り込み」。`type` だけの criterion 1つで終わらせると、**それは「型を丸ごと消す」最も危険な抑制**になります（3章の罠）。
- **`description` に「なぜ・reactive である根拠」を残す。** 抑制は検知を削る操作なので、レビュー時に「これは本当に繰り返し誤検知だったのか」を判断できる証跡を必ず残します。
- **`rank` で適用順を意識する。** 複数フィルタがあるときの評価順。抑制ルールが意図せず広い finding を巻き込まないよう、スコープの狭いものを意識して管理します。

> **検証経路（公式）**：作った抑制ルールが「狙った finding だけ」を消し「それ以外」を消さないことは、`create-sample-findings` で各型のサンプルを発火させ、`service.archived = true` に落ちる finding と EventBridge に届く finding を見比べれば検証できます（サンプルは `[SAMPLE]` 接頭辞と `service.additionalInfo.sample = true` で見分けられます）。「検証経路を先に作る」原則は、検知を**消す**変更でこそ効きます。

---

## 3. THE 罠：広すぎる抑制が Extended Threat Detection を盲目にする

ここがこの記事で**最も重要な一節**です。抑制ルールの本当の危険は「ノイズが減りすぎる」ことではなく、**「ノイズと一緒に、攻撃の文脈そのものを消す」**ことにあります。

### 3.1 公式が明言する挙動

公式の Note を正確に引きます——**「攻撃シーケンスのためにイベントを相関する際、Extended Threat Detection はアーカイブされた finding を考慮しない。これには Suppression Rule によって自動的にアーカイブされた finding も含まれる」**。

つまり、[Extended Threat Detection（ETD）](/blog/aws-guardduty-threat-detection-multi-account-terraform-eventbridge-guide)が「弱いシグナルを24時間窓で相関して多段攻撃を1つの Critical な攻撃シーケンスに束ねる」仕組みは、**抑制でアーカイブした finding を材料に使えません**。1章で見たとおり、抑制された finding は90日 GuardDuty に残りますが——**「残っている」ことと「相関に使える」ことは別**なのです。

### 3.2 公式が挙げる具体例（EKS の型丸ごと抑制）

公式は具体例まで挙げています——**「特定の既知アクティビティを狙うのではなく、EKS クラスタ関連の finding をすべてアーカイブする抑制ルールを作ると、GuardDuty は『脅威アクターがコンテナを悪用 → 特権トークンを取得 → 機密リソースにアクセス』という攻撃シーケンスを、それらの finding を使って検知できなくなる」**。

これを絵にすると、こうです。

```text
                              ┌─ 個別 finding A（弱いシグナル）─┐
  攻撃の連鎖（多段）─────────────┼─ 個別 finding B（弱いシグナル）─┼─→ ETD が相関 → AttackSequence（Critical 9.0-10.0）
                              └─ 個別 finding C（弱いシグナル）─┘
                                          ▲
       「EKS finding を型ごと全部アーカイブ」する広い抑制ルール
                                          │
                              A・B・C が archived に落ちる
                                          │
                                          ▼
                       ETD はアーカイブ済みを相関材料にしない
                                          │
                                          ▼
              AttackSequence は「材料が無い」ため、二度と束ねられない（不可視化）
```

**誤検知を消したつもりが、最も重大な Critical の多段攻撃を、自分の手で検知不能にしている**——これが抑制ルールの罠です。個別 finding は「中くらいの不審な操作」に見えるので、つい広く消したくなる。けれどその一つひとつが、ETD にとっては攻撃シーケンスを束ねる**材料**なのです。

### 3.3 公式の推奨と、運用に落とした「やってよい／いけない」

公式は2点を推奨します——**①既知の信頼できるアクティビティからのアラートを減らすために抑制ルールは使い続けてよい。②ただし抑制ルールは『GuardDuty に finding を出してほしくない特定の挙動』に絞れ**。加えて Best practice として**「reactive に、自分の環境で繰り返し誤検知だと確認できた finding にのみ作れ」**。「念のため先に消しておく」は明確に禁物です。

これを運用ルールに落とすと、こうなります（[ETD スポーク記事の監査表](/blog/aws-guardduty-extended-threat-detection-attack-sequence-findings-guide)と同じ思想です。あちらは ETD 側から、本記事はチューニング側から同じ罠を扱っています）。

| ✅ やってよい抑制（スコープを絞った） | ❌ やってはいけない抑制（型を丸ごと） |
| --- | --- |
| `Recon:EC2/Portscan` を**スキャナの AMI/タグに限定** | `Recon:*` を型ごと全アカウントで抑制 |
| `UnauthorizedAccess:EC2/SSHBruteForce` を**特定 bastion のタグに限定** | EKS/S3 関連 finding を**リソース無指定で広く**抑制 |
| `InstanceCredentialExfiltration.OutsideAWS` を**オンプレ GW の固定 IP に限定** | 攻撃シーケンスの材料になり得る型を**予防的に**抑制 |

**鉄則は「抑制はリソース/IP/タグで絞ったピンポイントに限る。型を丸ごと消すのは、ETD の目を潰す行為」**。では「型単位でノイズだけ静かにしたい」ときはどうするか——**答えは『抑制（＝アーカイブ＝ETD から不可視）』ではなく、[EventBridge の通知側フィルタ](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide)で『通知だけ静かにする』**ことです。EventBridge ルールの `severity` 数値マッチや型ルーティングで「Slack に流さない」を実現すれば、**finding は GuardDuty 内にアクティブなまま残り、ETD の相関材料として生き続けます**。

> **使い分けの一行サマリ**：**「検知を消す」なら抑制（ただしピンポイントに）／「通知だけ静かにする」なら EventBridge フィルタ**。ノイズ低減の大半は、実は後者で十分です。抑制は「誤検知が構造的に確定している、絞り込めるノイズ」だけに使う最終手段だと考えてください。

### 3.4 既存の抑制ルールを棚卸しする（監査スクリプト）

「広すぎる抑制が無いか」は定期的に棚卸しすべきです。`action = ARCHIVE` のフィルタのうち、`criterion` が**型（`type`）だけ**でリソース絞り込みを持たないものが危険信号です。

```bash
# 委任管理者アカウントで実行：全フィルタを列挙し、action=ARCHIVE のものを監査する。
# criterion が type だけ（resource.* / IP / タグ無し）の抑制が「型丸ごと」の危険信号。
DETECTOR_ID="$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)"

for FILTER in $(aws guardduty list-filters --detector-id "$DETECTOR_ID" \
                  --query 'FilterNames[]' --output text); do
  echo "=== ${FILTER} ==="
  aws guardduty get-filter --detector-id "$DETECTOR_ID" --filter-name "$FILTER" \
    --query '{name:Name, action:Action, criterion:FindingCriteria.Criterion}'
done
```

> **監査の着眼点**：`action` が `ARCHIVE` で、`Criterion` のキーが `type` **だけ**のものを探します。特に EKS / S3 / IAM 系を型ごと消している抑制は、対応する攻撃シーケンス（それぞれ `AttackSequence:EKS/CompromisedCluster`・`S3/CompromisedData`・`IAM/CompromisedCredentials`）を不可視化している可能性が高い。発見したら、リソース指定で絞り込むか、抑制をやめて通知側フィルタへ移します。

---

## 4. 信頼リスト・脅威リストの深掘り：エンティティリストと IP リスト

3つ目・4つ目の道具がリストです。抑制が「finding の側」を見るのに対し、リストは**「ソースの側」**を見ます——「この IP/ドメインからは finding を出さない（信頼）／出す（脅威）」。

### 4.1 エンティティリスト（推奨）vs レガシー IP リスト

公式は2つの実装を提示し、**エンティティリスト（entity list）を推奨**しています。

| | **エンティティリスト（推奨）** | **レガシー IP リスト** |
| --- | --- | --- |
| 載せられるもの | **IP アドレス・ドメイン名・SHA-256 ファイルハッシュ** | **IP アドレスのみ** |
| 権限モデル | **直接 S3 アクセス ＋ 単一の IAM 権限**（複数リージョンで IAM ポリシーサイズを圧迫しない） | **サービスリンクロール（SLR）**。リージョンごとに IAM ポリシー更新が必要 |
| ハッシュ | **脅威エンティティリストでのみ** SHA-256 可（信頼リストには不可） | ハッシュ不可 |

> **設計への含意**：新規構築なら**エンティティリスト一択**です。レガシー IP リストは IP しか載らず、SLR ベースで**リージョン数だけ IAM ポリシーが肥大化**します。エンティティリストは単一 IAM 権限で済み、ドメインやハッシュ（脅威リストのみ）も扱えます。公式も移行手順（エンティティリストを追加・アクティベートしてから、対応する IP リストを deactivate/delete）を案内しています。

### 4.2 リストの制限（公式・正確に）

ここは**数字を絶対に発明してはいけない**ところです。公式が明記する制限を正確に：

| 制限 | 値（公式） |
| --- | --- |
| 信頼エンティティリスト | アカウント×リージョンあたり**1つ**まで |
| 信頼 IP リスト | アカウント×リージョンあたり**1つ**まで |
| 脅威リスト（エンティティ＋IP） | アカウント×リージョンあたり**最大6つ** |
| IP バージョン | **IPv4 のみ**（IPv6 は非対応） |
| 対象アドレス/ドメイン | **公開ルーティング可能な（publicly routable）IP/ドメインのみ** |
| ファイル最大サイズ | **35 MB** |
| 反映時間 | アクティベート/非アクティベート/削除は**約15分**で完了（場合により**最大40分**） |

> **per-list の entry 数は「公式で要確認」**：1つのリストに何件の IP/ドメインを載せられるか、という上限は本ガイドの一覧には**書かれていません**。公式は「エンティティリストと IP リストでクォータが異なる」とし、詳細を[GuardDuty quotas](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_limits.html)に委ねています。**件数の上限が要件に絡む場合は、必ず quotas ページで最新値を確認してください**（ここで具体的な数字を書くと、すぐ陳腐化し誤情報になります）。

### 4.3 適用範囲の違い（DNS に注意）と優先順位

リストには「どの finding に効くか」の範囲があり、**エンティティリストと IP リストで違います**。ここを取り違えると「DNS の悪性ドメインを IP リストに入れたのに効かない」事故になります。

| | エンティティリスト | IP リスト |
| --- | --- | --- |
| CloudTrail finding | 適用 | 適用 |
| VPC Flow Logs finding | 適用 | 適用 |
| **Route 53 Resolver DNS クエリログ finding** | **適用** | **非適用** |

公式どおり——**エンティティリストの entry は CloudTrail・VPC Flow Logs・Route 53 Resolver DNS クエリログの finding に適用される。IP リストの entry は CloudTrail・VPC Flow Logs に適用されるが、DNS クエリログ finding には適用されない**。ドメインを扱うなら（DNS に効かせたいなら）**エンティティリスト一択**である、もう一つの理由です。

優先順位も公式が明記——**同じ IP/ドメインを信頼リストと脅威リストの両方に入れた場合、信頼リストが優先**されます。GuardDuty は finding を生成しません。意図せず「悪性として登録したのに、別の信頼リストにも入っていて検知されない」という事故を避けるため、**信頼と脅威で entry が衝突していないか**は管理対象にします。

さらに**適用プランの例外**——リストは**基盤データソース＋保護プランの全体に効きますが、Runtime Monitoring だけは例外（適用されない）**です。Runtime Monitoring のプロセス/システムコール検知は、リストによる信頼/脅威の上書き対象外、と理解しておきます。

### 4.4 マルチアカウントと「再アクティベート」の運用

2つの運用上の落とし穴があります。

1. **マルチアカウントでは管理者だけがリストを管理。** 公式どおり——**マルチアカウント環境では、GuardDuty 管理者アカウントだけがリストを管理でき、設定は自動的にメンバーアカウントに適用される**。管理者の脅威ソースに載った悪性 IP/ドメインで finding が生成され、管理者の信頼ソースに載ったものでは生成されない、がメンバー全体に効きます。抑制ルールと同じく**統制が管理者に一元化**されます。
2. **S3 のファイルを編集したら、必ず再アクティベート。** 公式の明記——**リストの S3 バケット内のエントリを追加・更新したら、リストを再度アクティベートしなければならない**。「S3 を上書きしたから自動で反映される」と思い込むと、**新しい entry が効いていない**状態が（4.2 の15〜40分とあわせて）生まれます。IaC では「S3 オブジェクトの更新」と「リストの再アクティベート」を**1つの apply で連動**させるのが安全です。

### 4.5 信頼 IP / 脅威リストを IaC で管理する（Terraform）

エンティティリストは新しい機能のため、**2026年6月時点の AWS プロバイダには専用リソースが（まだ）見当たりません**——`aws_guardduty_ipset`（信頼 IP）と `aws_guardduty_threatintelset`（脅威）は IP リスト/脅威リスト相当です。**エンティティリストを Terraform で完全管理したい場合は、専用リソースの有無を必ず最新のプロバイダで確認してください**（無ければ S3 オブジェクト＋API/CLI で管理し、再アクティベートをパイプラインに組み込む）。ここでは確実に存在する2リソースで示します。

```hcl
# ── 信頼 IP リスト（aws_guardduty_ipset）──
# 自社の固定 egress IP など「正規ソース」を登録。ここからは finding を生成しない。
# format の許容値: TXT | STIX | OTX_CSV | ALIEN_VAULT | PROOF_POINT | FIRE_EYE
resource "aws_guardduty_ipset" "trusted" {
  detector_id = aws_guardduty_detector.this.id
  name        = "corporate-egress"
  format      = "TXT"
  # S3 上のリストファイル。中身を更新したら activate を打ち直す必要がある（4.4 参照）。
  location    = "https://s3.amazonaws.com/${aws_s3_object.trusted_ips.bucket}/${aws_s3_object.trusted_ips.key}"
  activate    = true # Active にして初めて検知に反映される
}

# ── 脅威リスト（aws_guardduty_threatintelset）──
# 自前で「悪性」と判断した IP を登録。一致すると .Custom メカニズムで finding が出る。
resource "aws_guardduty_threatintelset" "custom_threats" {
  detector_id = aws_guardduty_detector.this.id
  name        = "org-custom-threat-feed"
  format      = "TXT"
  location    = "https://s3.amazonaws.com/${aws_s3_object.threat_ips.bucket}/${aws_s3_object.threat_ips.key}"
  activate    = true
}

# リストファイル本体。content のハッシュが変わると Terraform が差分を検知し、
# 依存する ipset/threatintelset の再 apply（= 再アクティベート）が走るよう構成する。
resource "aws_s3_object" "trusted_ips" {
  bucket  = aws_s3_bucket.sec_config.id
  key     = "guardduty/trusted-ips.txt"
  content = "198.51.100.0/24\n203.0.113.10\n" # IPv4 のみ・公開アドレスのみ
}
```

> **再アクティベートを IaC で落とし込む**：上のように「S3 オブジェクトの `content`（または `etag`）変更 → ipset/threatintelset の再 apply」が連鎖するよう依存を張ると、**4.4 の『編集したら再アクティベート』を手作業に頼らず**保証できます。手で S3 を上書きして「反映されない」と悩む典型的な事故を、構造で消せます。

---

## 5. 決定フレームワーク：症状 → 正しい道具

ここまでの3（＋1）道具を、**「ノイズの症状」から逆引き**できる表にまとめます。チューニングの現場で最初に開くべき早見表です。

| 症状（ノイズの正体） | 正しい道具 | 具体策 | やってはいけない代替 |
| --- | --- | --- | --- |
| 自社スキャナの定期 portscan がうるさい | **Suppression Rule** | `Recon:EC2/Portscan` を AMI/タグで絞って ARCHIVE | `Recon:*` を型ごと抑制（ETD を盲目化） |
| bastion への SSH ブルートフォースが想定挙動 | **Suppression Rule** | `SSHBruteForce` を bastion タグで絞って ARCHIVE | 型ごと抑制 |
| 自社の固定 egress IP からの通信で finding が出る | **信頼リスト** | 該当 IP を信頼エンティティ/IP リストに登録 | その IP 由来の型を抑制（他ソースまで消える） |
| 監視 SaaS のドメインへの DNS 問い合わせがうるさい | **信頼エンティティリスト** | ドメインを信頼**エンティティ**リストに登録（IP リストは DNS に効かない） | 信頼 IP リストに入れる（DNS 非適用で効かない） |
| 自前で「これは悪性」と判断した IP/ドメインを検知したい | **脅威リスト** | 脅威エンティティ/IP リストに登録（`.Custom` で finding 化） | 抑制（逆方向の道具） |
| 既知マルウェアのハッシュで検知したい | **脅威エンティティリスト** | SHA-256 を**脅威**エンティティリストに登録 | 信頼リスト/IP リスト（ハッシュ非対応） |
| 「型単位でノイズだけ静かにしたい」（攻撃文脈は残したい） | **EventBridge 通知フィルタ** | [通知ルールの severity/型でフィルタ](/blog/aws-guardduty-eventbridge-automated-remediation-incident-response-guide)。finding は GuardDuty に残す | 抑制（アーカイブ＝ETD から不可視） |

### 5.1 コストの誤解を正す（最重要のお金の話）

最後に、**最も多い誤解**を潰します——**「ノイズを抑制すれば GuardDuty が安くなる」は誤り**です。

[GuardDuty の課金は『解析したログ量』に対して発生](/blog/aws-guardduty-cost-optimization-pricing-finops-guide)します（CloudTrail イベント数・VPC/DNS の GB・vCPU 時間など）。**finding の数で課金されるのではありません**。だから：

- **Suppression Rule はコストを1円も下げません。** 1章のとおり、抑制された finding も**生成されています**（解析は止まっていない）。アーカイブは「通知経路から外す」だけで、解析量は不変です。
- **信頼リストも解析量は減りません。** 信頼ソースについて finding を**生成しない**だけで、そのトラフィックの**ログ解析自体は行われています**。finding は減りますが、データは依然として解析され、課金されます。

> **結論**：**チューニング（抑制・リスト）は「ノイズ削減・誤検知削減・検知精度の調整」の道具であって、「コスト削減」の道具ではありません**。GuardDuty のコストを下げたいなら、抑制ではなく**保護プランの選定**（Runtime Monitoring を重要ワークロードに限定する等）で攻めます——詳しくは[コスト最適化のスポーク記事](/blog/aws-guardduty-cost-optimization-pricing-finops-guide)へ。「アラートがうるさい→抑制すれば安くなる」という**二重の勘違い**を、ここで断ち切ってください。

---

## 6. チューニングのランブック：測る → 特定 → 最小スコープで適用 → レビュー

道具と判断軸が揃ったので、**繰り返し回せる運用手順**に落とします。冪等で・レビュー可能で・IaC 中心、が原則です。

### Step 1. 測る（ノイズのベースラインを取る）

まず「何が・どれだけ・どこから」うるさいかを定量化します。感覚で抑制を作らない。

```bash
# 直近のアクティブな finding を型別に集計し、ノイズの上位を特定する。
# （ListFindings → GetFindings で型を取得して集計するのが基本。ここは骨子）
aws guardduty list-findings --detector-id "$DETECTOR_ID" \
  --finding-criteria '{ "Criterion": { "service.archived": { "Equals": ["false"] } } }' \
  --query 'FindingIds' --output text
# 取得した finding を GetFindings で型・ソース IP・リソースまで割り、上位ノイズを定量化する。
```

### Step 2. 特定する（「パターン」か「ソース」か、reactive か）

上位ノイズそれぞれについて、0章の分岐で道具を決めます。

- **同じ finding 型が、特定リソース（AMI/タグ）で繰り返し出る** → Suppression Rule（型＋絞り込み）。**かつ「繰り返し誤検知だと確認できた」reactive な根拠があること**。
- **特定の正規ソース IP/ドメインから出ている** → 信頼リスト（ドメインや DNS が絡むならエンティティリスト）。
- **型単位で静かにしたいだけ（攻撃文脈は残す）** → 抑制ではなく EventBridge 通知フィルタ。

### Step 3. 最小スコープで適用する（IaC）

決めた道具を、**可能な限り狭いスコープ**で IaC に書きます（2章・4.5 のとおり）。抑制なら必ず「型＋リソース絞り込み」の2条件、`description` に reactive の根拠。リストなら S3 更新と再アクティベートを連動。

### Step 4. レビューする（ETD を盲目化していないか）

適用後、**「この変更が攻撃シーケンスの材料を消していないか」**を必ず確認します。

- 3.4 の監査スクリプトで、`action=ARCHIVE` かつ `type` だけのフィルタが増えていないか棚卸し。
- 抑制した型が `AttackSequence:*` の材料になり得るか（EKS/S3/IAM 系は特に注意）を確認。材料になり得るなら、**抑制ではなく通知フィルタに切り替え**。
- 信頼/脅威リストで entry の衝突（同じ IP が両方に）が無いか確認（信頼が優先される事故を防ぐ）。

> **冪等性とレビュー可能性**：このランブックは全ステップが**コードと CLI**で完結します。抑制ルールもリストも Terraform の `apply` で**何度流しても同じ状態**に収束し（冪等）、`plan` の差分が**そのままレビュー対象**になります。「コンソールで誰かがこっそり検知を消していた」という、セキュリティ運用で最悪のサイレント変更を、構造的に排除できます。これは決済基盤で「正しさを注意深さではなく仕組みで担保する」のと同じ発想です。

---

## 7. まとめ：GuardDuty チューニング チートシート

迷ったときの早見表です。

- **道具は3つ・仕事も3つ**：**Suppression Rule**＝既知の無害な**finding パターン**を自動アーカイブ／**信頼リスト**＝既知の正規**ソース**から finding を出さない／**脅威リスト**＝既知の悪性**ソース**から finding を出す。「パターンか、ソースか」で道具が決まる。
- **抑制された finding に起きること/起きないこと**：Security Hub CSPM・S3・Detective・EventBridge に**送られない**、Malware Protection for EC2 も**起動しない**。でも finding は**生成され**、**archived として90日**保存（`service.archived = true` で参照可）。**抑制は検知を止めない、通知を止めるだけ**。
- **抑制は「型＋絞り込み」の2条件で**：公式の全ユースケースが型＋AMI/タグ/IP/プロセスの2条件。**`type` だけの抑制は最も危険**。
- **THE 罠（最重要）**：**ETD はアーカイブ済み（抑制で自動アーカイブされたものを含む）finding を相関材料にしない**。EKS 等を型ごと消す広い抑制は、`AttackSequence:*`（Critical 9.0-10.0）を丸ごと不可視化する。抑制は **reactive に・特定挙動へ絞る**。型単位で静かにしたいだけなら**抑制ではなく EventBridge 通知フィルタ**で。
- **リストはエンティティリストが推奨**：IP/ドメイン/SHA-256（ハッシュは**脅威**リストのみ）・単一 IAM 権限。レガシー IP リストは IP のみ・SLR。**信頼エンティティ1＋信頼 IP 1、脅威リスト最大6**（アカウント×リージョン）。**IPv4 のみ・公開アドレス/ドメインのみ・35 MB・編集後は再アクティベート（約15分、最大40分）**。
- **適用範囲**：エンティティリストは CloudTrail/VPC/**DNS** に適用、IP リストは CloudTrail/VPC のみ（**DNS 非適用**）。**信頼が脅威に優先**。リストは Runtime Monitoring 以外の全プランに適用。
- **マルチアカウント**：抑制ルールもリストも**委任管理者だけ**が管理（統制が一元化）。
- **コストの誤解を捨てる**：**抑制も信頼リストも GuardDuty コストを下げない**（課金は finding 数ではなく解析量）。コスト削減は保護プラン選定で。
- **ランブック**：測る → パターン/ソースを特定（reactive か）→ 最小スコープで IaC 適用 → ETD を盲目化していないかレビュー。**コンソールのクリックではなく Terraform/CLI で**。

GuardDuty のチューニングは「うるさいアラートを黙らせる作業」ではありません。**「対応すべき finding だけを残し、攻撃の文脈は一切失わない」という、検知能力を削らずにノイズだけを削る精密な運用**です。最大の落とし穴は、ノイズと一緒に Critical な攻撃シーケンスの材料を消してしまうこと。だからこそ——**抑制はピンポイントに・reactive に・IaC で**、が効きます。

私はマルチアカウントの[サーバーレス決済プラットフォーム](/case-studies/payment-platform-reliability)で、**実際の金銭・カーボンクレジット・地域通貨を扱う基盤の IAM・可観測性・DR を横断実装**し、「正しさ」を運用の注意深さではなく**コードの構造と冪等性**で担保してきました。GuardDuty のチューニングも同じ思想で設計します——**①ノイズをまず定量化し、②パターンかソースかで道具を選び、③最小スコープで IaC に落とし、④ETD を盲目化していないかをレビューで担保する**。「全部ミュート」して攻撃まで消す事故を、構造で防ぎます。

**「自社の GuardDuty、アラートがうるさいけど何を消していいか分からない」——Suppression Rule・信頼/脅威リストの設計、ETD を盲目化しない抑制の絞り込み、EventBridge 通知フィルタとの使い分け、IaC 化と監査の仕組みまで、一人 ×生成AI（Claude Code）で速く・安全に伴走できます。** 要件の整理段階からでも、お気軽にご相談ください。

---

### 参考（公式ドキュメント）

- [Suppression rules in GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/findings_suppression-rule.html) — 抑制＝自動アーカイブ・送られない先（Security Hub/S3/Detective/EventBridge）・90日保存・`service.archived`・管理者のみ作成・ETD との相互作用・代表ユースケース（型＋絞り込みの2条件）・reactive 推奨
- [Customizing threat detection with entity lists and IP address lists](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_upload-lists.html) — エンティティリスト（推奨）vs IP リスト・信頼/脅威の上限（1/1/最大6）・IPv4 のみ・公開アドレスのみ・DNS 適用差・信頼優先・再アクティベート（15〜40分）・35 MB・Runtime Monitoring 例外・対応形式
- [Filtering findings in GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_filter-findings.html) — フィルタ属性 1〜50・`Equals`/`NotEquals` 最大50値・属性は AND・`type`/`resource.instanceDetails.imageId`/`tags.key`/`tags.value`/`service.action.awsApiCallAction.remoteIpDetails.ipAddressV4` 等の正確な JSON フィールド名・`service.archived`
- [aws_guardduty_filter (Terraform AWS Provider)](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_filter) — `action`（`ARCHIVE`/`NOOP`）・`rank`・`finding_criteria { criterion { field, equals/not_equals/... } }`
- [aws_guardduty_ipset / aws_guardduty_threatintelset](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/guardduty_ipset) — 信頼 IP リスト/脅威リストの IaC 管理（`format`・`location`・`activate`）。エンティティリスト専用リソースの有無は最新プロバイダで要確認
- [GuardDuty quotas](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_limits.html) — リストごとの entry 件数など、本文に書かれていないクォータの正確な最新値
