【実務・中級編】APIゲートウェイにおけるレート制限とWAFによるDDoS防御 – アプリケーションセキュリティ & 安全な開発防御ガイド

APIは「性善説」で動いていない:ゲートウェイとWAFで防御する「リソース枯渇」の防衛線

現場のエンジニア諸君、お疲れ様。今日はAPIのセキュリティ、特に「レート制限」と「WAFによる防御」について、教科書には載っていない泥臭い話をしよう。

多くの開発者がAPIを作るとき、機能実装に忙殺されて「誰が、どのくらいの頻度で叩いてくるか」を忘れがちだ。だが、現実は甘くない。君たちが書いたAPIは、リリースしたその瞬間に、世界中のボットネットから「食い物」としてスキャンされている。

今日は、APIを守るための防衛線をどう構築するか、実践的な話をしよう。

—

1. なぜ「レート制限」が必要なのか?(PoC的視点)

攻撃者が狙うのは、単なるデータの窃取だけではない。「DoS(サービス拒否)攻撃」によるリソース枯渇だ。

例えば、DBのJOINを多用する重い検索APIがあるとしよう。攻撃者は次のようなスクリプトを数百台のノードから同時に叩き込む。

攻撃者の視点:リソースを枯渇させるための単純な並列スキャン
import requests
import threading

def attack():
while True:
# 認証不要の重いAPIエンドポイントを狙い撃ち
requests.get(“https://api.example.com/v1/search?query=a”)

for _ in range(50):
threading.Thread(target=attack).start()

これをやられると、DBのコネクションプールは一瞬で埋まり、他の正規ユーザーが「503 Service Unavailable」を拝むことになる。これこそが、APIゲートウェイでのスロットリング(レート制限)が不可欠な理由だ。

—

2. APIゲートウェイ(Nginx)でのレート制限設定

APIゲートウェイやリバースプロキシのレベルで、IPアドレス単位の制限をかけるのが最初の防壁だ。Nginxを使っているなら、limit_req モジュールを適切に設定する。

Nginx設定ファイル: レート制限の定義
1分間に20回まで許可(burstは一時的なバーストを許容する数)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=20r/m;

server {
location /api/ {
# 制限超過時は503を返す
limit_req zone=api_limit burst=5 nodelay;
proxy_pass http://backend_upstream;
}
}

ポイント: burstを設定しないと、正規ユーザーが少し速くクリックしただけでエラーが出る。UXを損なわない絶妙な値を見つけるのが腕の見せ所だ。

—

3. AWS WAFによる「レートベース」の防御

クラウド環境なら、アプリケーションの手前でAWS WAFを噛ませるのが定石だ。ここで重要なのは「レートベースのルール」だ。

AWS WAFのレートベースルール設定の考え方はこうだ。

  • 評価スコープ: 特定のAPIパス(例: /v1/login や /v1/search)に限定する。
  • レート閾値: 「5分間で100リクエスト」など、平常時の最大トラフィックの2〜3倍程度に設定する。
  • アクション: 最初は「カウントのみ」でログを分析し、誤検知がないことを確認してから「ブロック」に切り替える。

Terraformでの設定例(抜粋)

resource “aws_wafv2_web_acl” “api_acl” {
name = “api-security-acl”
scope = “REGIONAL”

rule {
name = “RateLimitRule”
priority = 1

statement {
rate_based_statement {
limit = 1000 # 5分間で1000回まで
aggregate_key_type = “IP”
}
}

action {
block {} # 閾値を超えたら即ブロック
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = “RateLimitMetric”
sampled_requests_enabled = true
}
}
}

—

4. 現場で生き残るための「心構え」

ここまで実装すれば安心……と言いたいところだが、一つだけ注意点がある。「攻撃者は動的IPを使いこなす」という点だ。

単一のIPをブロックするだけでは、ボットネットは数十万のIPをローテーションして攻撃を継続する。だからこそ、以下の2段構えが必須になる。

1. 異常検知: ユーザーエージェントの偏りや、APIの叩き方の「不自然な規則性」をCloudWatch Logs等で監視する。
2. 認証の強制: そもそも、重要なエンドポイントにはAPIキーやJWTによる認証を必須とし、認証後のユーザーID単位でレート制限をかける。

Node.js (Express) でのユーザー単位レート制限の例

const rateLimit = require(“express-rate-limit”);

const apiLimiter = rateLimit({
windowMs: 15 60 1000, // 15分
max: 100, // ユーザーIDごとに100回
keyGenerator: (req) => req.user.id, // IPではなくユーザーIDで制限
message: “レート制限を超過しました。しばらく待ってください。”
});

app.use(“/api/v1/protected”, apiLimiter, (req, res) => {
// 処理ロジック
});

—

まとめ:セキュリティは「多層」で戦え

APIゲートウェイ、WAF、そしてアプリケーションコード。これらを組み合わせることで初めて「堅牢」と言える。

「自分たちのサービスは小さいから狙われない」と思っているなら、今すぐその考えを捨てろ。攻撃者は君たちのサービスそのものよりも、脆弱なAPIを「踏み台」にして他の攻撃へ繋げることを狙っているんだ。

まずはWAFのログを眺めるところから始めてみよう。そこには、君たちの想像を超えた「悪意あるトラフィック」の姿が刻まれているはずだ。

守りを固めることは、開発者の責任だ。健闘を祈る。

コメント

タイトルとURLをコピーしました