🐛

Keploy — eBPFでトラフィックを傍受しAPIテストを自動生成する仕組み

eBPFがカーネルでconnect()の宛先をこっそり書き換える透過プロキシパターン

Go製のCNCFプロジェクト。17k+スター。コード変更ゼロでAPIテストを自動生成する。

核心原理:eBPF宛先リダイレクト

全てのアプリは外部通信にカーネルsyscallを使う。connect(postgres:5432)を呼ぶとカーネルがTCP接続を作る。KeployはここにeBPFを付ける。

eBPFプログラムがSockOps(cgroup付着)とconnect4/6フックでアウトバウンド接続を監視。アプリがpostgres:5432にconnectしようとすると、eBPFが宛先を127.0.0.1:proxyPortに書き換える。元の宛先はredirectProxyMap共有マップに保存。

アプリはpostgresに接続したつもり。実際はKeployのプロキシに接続している。プロキシが元の宛先を照会して実際のpostgresに転送しつつ、往来するトラフィックを全て録画。

透過プロキシのプロトコル解析

プロキシは接続の先頭バイトでプロトコルを判別。HTTP、MySQL、PostgreSQL、MongoDB、Redis、Kafka、gRPC — それぞれ専用パーサーがリクエスト/レスポンスペアを捕捉。

録画結果:

  • インバウンドHTTP → TestCase(YAML)

  • アウトバウンドDB/外部API → Mock(YAML)

  • マッピング → どのMockがどのTestCaseに属するか

テスト(再生)モード

keploy testで実行すると録画済みHTTPリクエストをアプリに再送信。アプリのDB呼び出しにはプロキシがMockで応答。実DBなしでテストが動く。

限界

Linux専用 — eBPFはカーネル5.15+必要。macOS/WindowsはDocker経由のみ。

SQLite捕捉不可 — ネットワークソケットを使わない通信はeBPFフックに引っかからない。PostgreSQL/MySQLのみ。

統合テストのみ — ビジネスロジックの単体テストは生成しない。

スキーマ変更に脆弱 — DBカラム追加/削除でMockが壊れる。再録画が必要。

トラフィック依存 — 叩いてないAPIにはテストもない。エラーケース、エッジケースは手動で作成が必要。

動作フロー

1

eBPFがconnect() syscallを傍受して宛先をプロキシにリダイレクト(アプリは知らない)

2

透過プロキシが先頭バイトでプロトコル判別→専用パーサーでリクエスト/レスポンス捕捉

3

インバウンド(TestCase)+アウトバウンド(Mock)をgoroutineチャネルで同時収集→YAML保存

4

再生時MockがDB/外部APIを代替 — 実インフラなしでオフラインテスト

メリット

  • コード変更ゼロ — eBPFがカーネルで動作するためSDK不要、言語非依存
  • HTTP/gRPC/MySQL/Postgres/MongoDB/Redis/Kafka+TLS透過処理

デメリット

  • Linux専用(カーネル5.15+)。macOS/WindowsはDocker必須
  • SQLite等ネットワーク不使用DBは捕捉不可。統合テストのみ生成(単体テスト不可)

ユースケース

既存アプリにテストがない状態で実トラフィックベースのリグレッションテストを素早く確保 CI/CDで外部依存なしに統合テスト実行(DB、Redis、外部API全てMock)