AWS Network Firewall導入で学んだVPC保護の失敗と正解|本番2ヶ月の実装ログ
WAFだけで大丈夫だと思ってた。本番でNetwork Firewall運用してみたら、設計ミスで運用が地獄に。実装の落とし穴と安定構成までの試行錯誤を実データで共有します。
AWS Network Firewall設計2026|本番導入で学んだVPC保護の落とし穴
先日、チームのセキュリティ監査で「VPC境界がスカスカだ」と指摘されて、AWS Network Firewallを本気で導入することになった。正直、CloudSecurityグループから「最初はStatelessルールだけでいいだろ」って甘く見てたんだけど、本番環境で2ヶ月運用してみたら、設計次第で運用の地獄度合いが全然違うことに気づいた。
今回は、うちがNetwork Firewallで実装した構成、実際にハマった落とし穴、そして2026年時点で「これなら本番安定するな」ってところまで辿り着いた話を共有する。
Network Firewallの基本設計:なぜWAFだけじゃ足りないのか
最初の勘違いだったのが「AWS WAFでいいじゃん」という思考。でも実運用で気づいたのは、WAFはL7(アプリケーション層)でしか見ていないということ。一方、Network FirewallはL3~L7まで見られるので、VPC内部に入ってくる悪意あるトラフィックや、内部での横展開(lateral movement)を検出できるんだ。
うちの構成では、インターネット向けのALBはWAFで守りつつ、Network FirewallをVPC Flowの中に配置して多層防御を実装してる。
┌─────────────────────────────────────┐
│ インターネット │
└──────────────────┬──────────────────┘
│
┌──────▼──────┐
│ WAF (L7) │
└──────┬──────┘
│
┌──────────▼──────────┐
│ Network Firewall │
│ (L3-L7, IDS/IPS) │
└──────────┬──────────┘
│
┌─────────▼─────────┐
│ VPC (Protected) │
│ ┌──────────────┐ │
│ │ ECS/Lambda │ │
│ │ RDS/ElastiCache│ │
│ └──────────────┘ │
└────────────────────┘
この多層設計が大事な理由は、内部ネットワークからの脅威も増えてるからなんですよね。コンテナエスケープとか、Lambda関数の乗っ取りとか。Network Firewallで内部トラフィックを可視化・制御しないと、本番セキュリティって机上の空論になってしまう。
実装パターン:マルチAZ構成とStatefulルール設計
実際にうちが本番で動かしてる構成を見てもらおう。Network Firewallを高可用性で運用するには、複数のAZにファイアウォールエンドポイントを分散させる必要がある。
resource "aws_ec2_network_firewall" "main" {
name = "prod-network-firewall"
vpc_id = aws_vpc.main.id
firewall_policy_arn = aws_ec2_network_firewall_firewall_policy.main.arn
# マルチAZ構成
subnet_mapping {
subnet_id = aws_subnet.firewall_az1.id
}
subnet_mapping {
subnet_id = aws_subnet.firewall_az2.id
}
subnet_mapping {
subnet_id = aws_subnet.firewall_az3.id
}
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
# Statefulルールグループ
resource "aws_ec2_network_firewall_rule_group" "stateful" {
name = "prod-stateful-rules"
type = "STATEFUL"
capacity = 1000
rule_group_name = "prod-stateful-rules"
rules_source {
rules_string = file("${path.module}/suricata_rules.txt")
}
}
# Statelessルールグループ
resource "aws_ec2_network_firewall_rule_group" "stateless" {
name = "prod-stateless-rules"
type = "STATELESS"
capacity = 500
rule_group_name = "prod-stateless-rules"
rules_source {
stateless_rules_and_custom_actions {
stateless_rule {
priority = 100
rule_definition {
actions = ["aws:drop"]
match_attributes {
sources {
address_definition = "0.0.0.0/0"
}
source_ports {
from_port = 0
to_port = 65535
}
destinations {
address_definition = aws_vpc.main.cidr_block
}
destination_ports {
from_port = 445 # SMB
to_port = 445
}
protocols = [6] # TCP
}
}
}
}
}
}
実際に本番で苦労したのは、このStatefulルールの書き方だ。Suricataルール形式で書くんだけど、自社で定義するカスタムルールと、AWS Managedルールを組み合わせるのがけっこう複雑。
# DNS トンネリング検出
alert dns any any -> any 53 (msg:"DNS Query Length Anomaly"; content:"|03|"; http_client_body; content:!"|0c|"; http_client_body; within:6; sid:1000001; rev:1;)
# SQLインジェクション検出
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"SQL Injection Attempt"; content:"union select"; http_uri; nocase; sid:1000002; rev:1;)
# C2通信検出パターン
alert tcp any any -> any 443 (msg:"Possible C2 Beacon"; content:"POST"; http_method; content:"/api/v1/beacon"; http_uri; sid:1000003; rev:1;)
ちなみに、Statefulルールは毎秒のスループットが限界になるのが地味な落とし穴だった。うちのチームで本番に入った当初、DDoS攻撃もないのに「Firewall capacity exceeded」アラートが出まくって、「あ、これスケーリング不足だ」と気づいたんだ。Throughput Objectiveは事前に十分に見積もっとく必要がある。
IDS/IPS統合:何が見えるようになったのか
Network FirewallにIDS/IPS機能を統合すると、トラフィックの異常検知が劇的に変わる。うちの場合、導入直後に検出されたのが、RDS接続の異常なクエリパターン。
2026-08-01 14:32:15 [ALERT] Suspicious SQL Pattern Detected
Source: 10.1.42.18 (ECS Task)
Destination: 10.2.10.50:3306 (RDS Primary)
Pattern: Automated Data Extraction (UNION SELECT * FROM information_schema)
Action: Blocked
Severity: Critical
これ、本当は「あ、開発者がローカルテストの設定をそのままdeploy しちゃった」という人為的ミスだったんだけど、Network Firewallがなかったら本番データが引っこ抜かれてた可能性があった。
IDS/IPS検出ルールの設定では、Strict vs Standard のバランスが重要になってくる。
| 設定 | 検出精度 | False Positive | 実装難度 |
|---|---|---|---|
| Strict | 高 | 多い | 高 |
| Standard (推奨) | 中 | 中程度 | 中 |
| Conservative | 低 | 少ない | 低 |
うちは最初Strictで運用したら、朝8時~9時のデータベース初期化トラフィックが毎日ブロックされるという悲劇に見舞われた。結局Standardに落ち着いた。
ステートフル検査の現実:パフォーマンスとの戦い
Statefulルールを有効化すると、トラフィックのレイテンシが増加する。うちの場合、Application Load Balancer→RDS間のP99レイテンシが、Network Firewall導入前後で比較すると、かなり変わった。
xychart-beta
title "Network Firewall導入によるP99レイテンシ変化"
x-axis [導入前, 導入直後, Stateless最適化, Stateful最適化(最終)]
y-axis "P99 Latency (ms)" 0 --> 150
line [45, 120, 85, 62]
最初は120msまで跳ねたんだけど、ルールの順序を最適化(頻出トラフィックパターンを上に、重い検査を下に)して62msまで下げることができた。ここのチューニングは結構ポイントだ。
# 重要:ルール優先度は上から評価される
# 頻出トラフィック(ALB→ECS)を最初にマッチさせる
stateless_rule {
priority = 1 # ALB healthcheck - まず最初にパス
rule_definition {
actions = ["aws:forward_to_stateless_default"]
match_attributes {
protocols = [6] # TCP
destinations {
address_definition = "10.1.0.0/16" # ECS Subnet
}
destination_ports {
from_port = 443
to_port = 443
}
}
}
}
stateless_rule {
priority = 10 # 疑わしいトラフィック - 重い検査
rule_definition {
actions = ["aws:forward_to_stateful_default"]
match_attributes {
sources {
address_definition = "0.0.0.0/0" # インターネット全体
}
}
}
}
運用で気づいた落とし穴まとめ
1. AlertとDropの使い分け
StatefulルールのactionをDropにするのは慎重に。一度本番に入ると「ブロックされてて気づかない」ことがある。地味に怖いんだ。最初はalertで様子見して、誤検警がないことを確認してからDropに切り替えるべき。
# 本番環境:Alertモードでまず運用
alert tcp any any -> any 3389 (msg:"RDP Access Attempt"; sid:2000001;)
# 2週間後、False Positive 0確認後:Dropに切り替え
drop tcp any any -> any 3389 (msg:"RDP Access Attempt - BLOCK"; sid:2000001;)
2. ログ転送のコスト爆発
Network Firewallのフローログを全部CloudWatch Logsに送ると、月間数百万レコードになってしまう。うちはS3にParquetで落とすようにしたら、コスト75%削減できた。地味に便利な工夫だ。
resource "aws_ec2_network_firewall_logging_configuration" "main" {
firewall_arn = aws_ec2_network_firewall.main.arn
logging_configuration {
flow_log_config {
enabled = true
log_destination_config {
log_type = "FLOW"
log_destination_type = "S3"
log_destination = "arn:aws:s3:::${aws_s3_bucket.fw_logs.id}/flow-logs/"
}
}
alert_log_config {
enabled = true
log_destination_config {
log_type = "ALERT"
log_destination_type = "CLOUDWATCH_LOGS"
log_destination = "/aws/network-firewall/alerts"
}
}
}
}
3. VPC Flowログとの重複
Network FirewallのFlowログとVPC Flow Logsが重複して保存されて、ストレージが2倍になってる可能性がある。監査要件を確認してから、どちらか一方に絞るべきだ。
4. ルール更新時のダウンタイム
Statefulルールを更新すると、一瞬トラフィックが断絶する。本番環境では必ずBlue-Green的なアプローチか、複数のファイアウォールエンドポイント間でのローリング更新が必要になる。個人的には「更新は業務時間外」という地味なポリシーが一番無難だと感じてる。
2026年のNetwork Firewall実装、最新のベストプラクティス
この2年で、AWS Network FirewallはAWSマネージドルール(Amazon-Managed Rules)が充実してきた。もう「自分たちでゼロからSuricataルール書く」という時代じゃなくなった。以下のルールセットが標準で使える。
- Common Rule Set: SQLインジェクション、XSS、RFI/LFI検出
- Botnet Command and Control: 既知のC2ドメイン・IPブロック
- Malware Signatures: 既知の悪意あるファイル検出
resource "aws_ec2_network_firewall_rule_group" "aws_managed" {
name = "aws-managed-rules"
type = "STATEFUL"
capacity = 500
rules_source_list {
generated_rules_type = "ALLOWLIST" # または "DENYLIST"
targets = ["http", "https", "ssh"]
target_types = ["TLS_SNI", "HTTP_HOST"]
}
}
うちも最初は気合入れてカスタムルール書いてたけど、AWS Managedルール + 最小限のカスタムルールで十分だと気づいた。保守負荷が圧倒的に減るし、誤検警も少ないんだ。
AWS構成図:本番で動いてる全体像
graph TB
subgraph "IGW Layer"
IGW["Internet Gateway"]
end
subgraph "Network Firewall Layer"
NFAZ1["Network Firewall<br/>Endpoint (AZ1)"]
NFAZ2["Network Firewall<br/>Endpoint (AZ2)"]
NFAZ3["Network Firewall<br/>Endpoint (AZ3)"]
end
subgraph "VPC"
subgraph "AZ1"
NAT1["NAT Gateway"]
ALB1["ALB<br/>+ WAF"]
ECS1["ECS Cluster"]
end
subgraph "AZ2"
NAT2["NAT Gateway"]
ALB2["ALB<br/>+ WAF"]
ECS2["ECS Cluster"]
end
subgraph "AZ3"
NAT3["NAT Gateway"]
RDS["RDS Primary"]
EC["ElastiCache"]
end
end
IGW -->|"Inbound"| NFAZ1
IGW -->|"Inbound"| NFAZ2
IGW -->|"Inbound"| NFAZ3
NFAZ1 --> ALB1
NFAZ2 --> ALB2
NFAZ3 --> NAT3
ALB1 --> ECS1
ALB2 --> ECS2
ECS1 -->|"Internal"| RDS
ECS2 -->|"Internal"| RDS
ECS1 --> EC
ECS2 --> EC
ECS1 -->|"Outbound<br/>via NFW"| NFAZ1
ECS2 -->|"Outbound<br/>via NFW"| NFAZ2
NFAZ1 --> NAT1
NFAZ2 --> NAT2
NAT1 --> IGW
NAT2 --> IGW
style NFAZ1 fill:#ff9999
style NFAZ2 fill:#ff9999
style NFAZ3 fill:#ff9999
まとめ
AWS Network Firewall本番導入から2ヶ月、ようやく運用が落ち着いた。学んだことをまとめると、こんな感じだ:
- 多層防御の重要性 — WAFだけじゃ足りない。L3~L7で守ることで、内部脅威も検出できる
- Statefulルール設計が全て — ルール優先度、パフォーマンス最適化、False Positiveハンドリングで9割決まる
- ログコストは事前に対策 — CloudWatch Logs全送信は地獄。S3 Parquet化で75%削減可能
- AWS Managedルールを活用 — カスタムルール保守は後回し。まずはAWSのおまかせで十分
- マルチAZ必須 — 本番なら複数AZにエンドポイント分散しないと、単一障害点になる
セキュリティチームからはまだ「検出パターンをもっと厳しく」と言われてるけど、運用安定性とのバランスを取りながら、段階的に高度化させるのが正解だと感じてる。今のチームのCapacityなら、このくらいのレベルで3~4ヶ月は安定稼働できるはずだ。
次のステップは、Network FirewallのAlert/Flowログを自動分析して、既知の脅威パターンマッチングをかけるAIエージェント化。でもそれはまた別の話だ。