From ce4c412cf584c078416ef7b902990ef90dae3298 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 15 Jul 2026 12:26:52 +0000 Subject: [PATCH] Rewrite README, document Java integration, dedupe AI docs README.md was a 3-line stub; it now covers features, quickstart, CLI overview, and doc links. AGENTS.md (the canonical AI-agent doc, symlinked as CLAUDE.md) was missing the entire Java -javaagent integration (runner.rs injection, phantom-java-agent crate, build.rs auto-build, and its integration test) and the --fault flag details, despite both being implemented and tested. GEMINI.md had drifted into its own inconsistent copy (stale manual Java build steps, missing --bind/--fault/PHP docs); it's now a symlink to AGENTS.md like CLAUDE.md, so there's a single source of truth. docs/how-to-use.ja.md is also fixed: missing `run` subcommand in every example, stale manual Java Agent build steps, LD_PRELOAD listed as HTTP-only (it now covers HTTPS too), and a missing PHP section. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01D3AJ8QJXCGkqj2FgPajyNP --- AGENTS.md | 47 +++++++++++++++++++- GEMINI.md | 100 +----------------------------------------- README.md | 78 ++++++++++++++++++++++++++++++++ docs/how-to-use.ja.md | 49 ++++++++++++--------- 4 files changed, 153 insertions(+), 121 deletions(-) mode change 100644 => 120000 GEMINI.md diff --git a/AGENTS.md b/AGENTS.md index 3917574..8e043c0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,19 +20,23 @@ crates/ phantom-capture/ # Hudsucker MITM proxy + LD_PRELOAD (Linux) CaptureBackend phantom-tui/ # Ratatui terminal UI phantom-agent/ # LD_PRELOAD dylib (Linux only, hooks libc send/recv) + phantom-java-agent/ # Java -javaagent premain (not a Cargo crate; built by build.rs via javac/jar) tests/ proxy_node_integration.rs # Integration tests: Node.js proxy capture (HTTP + HTTPS) proxy_php_integration.rs # Integration test: PHP curl via proxy backend (HTTP + HTTPS) proxy_php_ldpreload_integration.rs # Integration test: PHP curl via ldpreload backend (Linux only) + proxy_java_clients_integration.rs # Integration test: Java HTTP clients via proxy backend (HTTP + HTTPS) proxy_bind_integration.rs # Integration test: --bind 0.0.0.0 + ca.pem export (Docker sidecar mode) cli_query_integration.rs # Integration tests: exit-code propagation, JSONL purity, list/get/clear, store lock UX mcp_stdio_integration.rs # Integration test: MCP server via raw JSON-RPC over stdio apps/node-app/ # Test Node.js app (client.js, client-alts.js, proxy-preload.js) apps/php-app/ # Test PHP app (client.php, curl extension, PHP 5.3-compatible) + apps/java-http-clients/ # Test Java app (JDK HttpClient, Apache HttpClient 5; Maven project) integration/ # Shell-based integration tests examples/ docker-sidecar/ # phantom as a Docker Compose sidecar tracing a peer container Cargo.toml # Workspace root + binary crate +build.rs # Compiles crates/phantom-java-agent into phantom-java-agent.jar at build time plan.md # Japanese-language technical design document ``` @@ -103,7 +107,7 @@ make check # fmt + clippy + build + test (full CI locally) | `--bind ` | `127.0.0.1` | IP address the proxy binds to. `0.0.0.0` exposes it to other hosts/containers (Docker sidecar mode) — no auth, trusted networks only | | `--insecure` | off | Disable TLS verification for backend servers (self-signed certs) | | `--agent-lib ` | — | Path to `libphantom_agent.so` (ldpreload backend) | -| `--fault ` | — | Fault injection rules (repeatable) | +| `--fault ` | — | Fault injection rules (repeatable, proxy backend only). `delay:100ms`, `delay:100ms-500ms`, `delay:200ms:/api` (URL substring filter), `error:503`, `error:503:0.5` (probability), `error:500:0.1:/api`. Rules apply in order; delays and errors can be combined | | `--max-body ` | `0` (unlimited) | Truncate bodies in JSONL output to N bytes | | `--headers-only` | off | Omit bodies from JSONL output (sizes still reported) | | `-- ` | — | Command to spawn and trace automatically | @@ -165,6 +169,30 @@ Unlike Node.js, PHP requires **no injected script**: libcurl (the library backin --- +## Java Transparent Proxy Injection + +When the command after `--` is `java` or `javaw`, phantom automatically: + +1. Writes the embedded `phantom-java-agent.jar` (`include_bytes!`, built by `build.rs`) to a PID-scoped temp file. +2. Appends JVM system properties and `-javaagent:` to `JAVA_TOOL_OPTIONS`: `-Dhttp.proxyHost`/`-Dhttp.proxyPort`/`-Dhttps.proxyHost`/`-Dhttps.proxyPort` (pointed at the phantom proxy) and `-Dhttp.nonProxyHosts=`/`-Dhttps.nonProxyHosts=` (clears any default exclusion list so local targets aren't bypassed). +3. Any pre-existing `JAVA_TOOL_OPTIONS` in the environment is preserved and appended to, not overwritten. +4. Deletes the temp jar after the child exits (`TempScript` RAII guard, same mechanism as Node/PHP). + +Unlike Node.js, Java requires no request-level monkey-patching: the injected `-javaagent` premain (`crates/phantom-java-agent/src/com/example/phantom/Agent.java`) installs a global `ProxySelector` forcing all connections through the phantom proxy, and replaces the JVM's default `SSLContext`/`HostnameVerifier` with a trust-all implementation so HTTPS via the MITM proxy doesn't fail certificate validation. Both HTTP and HTTPS are captured with zero application code changes. + +**`phantom-java-agent.jar` build (`build.rs`):** +- Compiles `Agent.java` with `javac` and packages it with `jar` (`Premain-Class: com.example.phantom.Agent`) into `crates/phantom-java-agent/phantom-java-agent.jar`, rebuilt whenever the Java source changes (`cargo:rerun-if-changed`). +- If `javac` is not found (e.g. a JDK-less CI/Docker image), `build.rs` writes an empty placeholder jar instead of failing, so the base `phantom` binary still builds. In that case `-javaagent` injection still fires but the agent does nothing — Java capture requires rebuilding with a JDK present. + +**Supported libraries:** JDK standard `java.net.http.HttpClient` (Java 11+), Apache HttpClient 5, OkHttp, and any client that honours the JVM's `http(s).proxyHost`/`proxyPort` system properties. Libraries with their own network stack (Netty, Jetty) are out of scope unless the application itself enables "use system proxy". + +**Known limitations:** +- The agent disables JVM-wide TLS certificate verification (rather than injecting phantom's MITM CA into a truststore, as Node/PHP do via a specific CA file). This is broader than the Node/PHP approach and is intended for development/tracing use, not for tracing security-sensitive production workloads. +- Requires JDK 11+ (for `java.net.http.HttpClient` coverage in tests) though the agent itself only needs a JVM supporting the `java.lang.instrument` premain API. +- See `tests/proxy_java_clients_integration.rs` and `tests/apps/java-http-clients/` (Maven project) for the integration test coverage. + +--- + ## Docker Sidecar Mode (`--bind`) phantom can trace an arbitrary web app already running in its own Docker container, without spawning or managing it — run phantom as a **sidecar container** on the same Docker network, and configure the target container's `HTTP_PROXY`/`HTTPS_PROXY` to point at it. This is the same "manual" proxy-configuration mode phantom always supported on a single host (`HTTP_PROXY=http://127.0.0.1:8080 your-app`), extended across a Docker network boundary via `--bind`. @@ -266,6 +294,9 @@ cargo test --test proxy_php_integration -- --nocapture cargo build -p phantom-agent cargo test --test proxy_php_ldpreload_integration -- --nocapture +# Java HTTP clients proxy integration test (requires JDK 17+ and mvn in PATH) +cargo test --test proxy_java_clients_integration -- --nocapture + # --bind 0.0.0.0 + ca.pem export test (Docker sidecar mode; requires curl) cargo test --test proxy_bind_integration -- --nocapture @@ -299,6 +330,10 @@ Both tests: Both auto-skip if `php` (or its curl extension) is not available. `client.php` (shared by both tests, `tests/apps/php-app/client.php`) is written in PHP 5.3-compatible syntax and takes an optional `PHANTOM_TEST_INSECURE` env var to disable curl peer verification for the ldpreload test, where there is no phantom CA to trust against the mock backend's self-signed cert. +### Java Integration Test (`tests/proxy_java_clients_integration.rs`) + +Verifies phantom's proxy backend captures HTTP and HTTPS traffic from JVM HTTP client libraries that honour JVM system proxy properties: JDK `java.net.http.HttpClient` (built-in, Java 11+) and Apache HttpClient 5. The proxy and `-javaagent` are injected transparently via `JAVA_TOOL_OPTIONS`, mirroring the Node.js `proxy-preload.js` injection pattern — the Java test app (`tests/apps/java-http-clients/`, a Maven project) contains zero proxy configuration code. Each client adds an `x-phantom-client` request header so traces can be identified in JSONL output, the same pattern as `test_proxy_captures_alternative_http_clients`. Requires `java` (17+) and `mvn` on `PATH`; auto-skips otherwise. + ### Docker Sidecar Test (`tests/proxy_bind_integration.rs`) Verifies `--bind 0.0.0.0` still proxies correctly (reachable via loopback, since an unspecified bind always includes it) and that `/ca.pem` is written once the proxy is ready. Drives `phantom run ... -- curl ...` rather than a truly standalone/no-child invocation, since JSONL mode only auto-exits on child completion or ctrl-c — the CA-export code path runs unconditionally before the child-spawn branch either way, so this still fully exercises what a Docker sidecar run would do. The fully standalone case is verified manually via `examples/docker-sidecar/`. @@ -465,6 +500,8 @@ pub enum StorageError { | `tests/proxy_php_integration.rs` | Integration test: PHP curl HTTP/HTTPS via `proxy` backend (`-d curl.cainfo=` injection) | | `tests/proxy_php_ldpreload_integration.rs` | Integration test: PHP curl HTTP/HTTPS via `ldpreload` backend (Linux only) | | `tests/apps/php-app/client.php` | Test client: curl extension, PHP 5.3-compatible syntax; shared by both PHP tests | +| `tests/proxy_java_clients_integration.rs` | Integration test: Java HTTP clients (JDK `HttpClient`, Apache HttpClient 5) via `proxy` backend (`JAVA_TOOL_OPTIONS` injection) | +| `tests/apps/java-http-clients/` | Test Java app (Maven project): JDK `HttpClient` and Apache HttpClient 5 usage | | `tests/proxy_bind_integration.rs` | Integration test: `--bind 0.0.0.0` and `/ca.pem` export (Docker sidecar mode) | | `examples/docker-sidecar/compose.yaml` | Example: phantom as a Docker Compose sidecar tracing a peer `app` container via HTTP_PROXY | | `examples/docker-sidecar/README.md` | Walkthrough: sidecar pattern, `--bind` security note, per-client CA trust table | @@ -478,10 +515,12 @@ pub enum StorageError { | `crates/phantom-capture/src/proxy.rs` | MITM proxy implementation (cross-platform); `bind_ip` field controls listen address; also exposes `ca_cert_pem()` for PHP `curl.cainfo` injection and Docker sidecar CA export | | `crates/phantom-capture/src/ldpreload.rs` | LD_PRELOAD capture backend (Linux only) | | `crates/phantom-agent/src/lib.rs` | LD_PRELOAD dylib: hooks libc `send`/`recv`/`close` and OpenSSL `SSL_write`/`SSL_read` (HTTPS) | +| `crates/phantom-java-agent/src/com/example/phantom/Agent.java` | Java `-javaagent` premain: disables JVM-wide TLS verification so the MITM proxy can intercept HTTPS | | `crates/phantom-tui/src/app.rs` | TUI state (`App`) and all state mutation | | `crates/phantom-tui/src/ui.rs` | Ratatui rendering functions | | `crates/phantom-tui/src/lib.rs` | TUI entry point and event loop | | `crates/phantom-tui/src/event.rs` | `EventHandler`: crossterm key events + tick | +| `build.rs` | Builds `crates/phantom-java-agent` into `phantom-java-agent.jar` via `javac`/`jar`; writes an empty placeholder if no JDK is present | | `plan.md` | Comprehensive technical design (Japanese) | --- @@ -509,6 +548,12 @@ Node.js auto-injection (proxy mode, -- node app.js): → patches http.request, https.request, undici dispatcher, globalThis.fetch → all outbound Node requests → phantom MITM proxy +Java auto-injection (proxy mode, -- java ...): + → runner.rs spawn_proxy_child() # writes embedded phantom-java-agent.jar to a temp file + → JAVA_TOOL_OPTIONS: proxy system properties + -javaagent: + → Agent.java premain disables JVM-wide TLS verification + → JVM HTTP clients honouring system proxy properties → phantom MITM proxy + LD_PRELOAD flow (Linux only): → phantom-agent dylib hooks send()/recv() # intercepts plain-text HTTP/1.x → sends JSON datagrams over UnixDatagram # PHANTOM_SOCKET env var diff --git a/GEMINI.md b/GEMINI.md deleted file mode 100644 index c05dd35..0000000 --- a/GEMINI.md +++ /dev/null @@ -1,99 +0,0 @@ -# Phantom Project Context - -Phantom is a next-generation API observability and automatic workflow generation tool written in Rust. It captures network traffic (HTTP/HTTPS) using multiple backends and provides both a terminal-based interface (TUI) and a JSON Lines stream to explore, analyze, and store API traces. - -## 🚀 Quick Start - -### Building and Running -- **Build the project:** `cargo build` -- **Run with Proxy (default):** `phantom run -- ` (e.g., `phantom run -- node app.js`) -- **Run with LD_PRELOAD (Linux only):** - `cargo run -- run --backend ldpreload --agent-lib ./target/debug/libphantom_agent.so -- curl http://example.com` -- **Run in JSONL mode:** `phantom run --output jsonl -- ` (exits with the child's exit code) -- **Query stored traces:** `phantom list --status 5xx --since 10m`, `phantom get ` -- **MCP server for AI agents:** `phantom mcp` (register: `claude mcp add phantom -- phantom mcp`) -- **Run tests:** `cargo test` - -### Common Examples -- **Trace a Node.js app (HTTP + HTTPS captured automatically):** - `phantom run -- node app.js` -- **Stream traces to jq for filtering:** - `phantom run --output jsonl -- node app.js | jq 'select(.status_code >= 400)'` -- **Capture plain HTTP for any command:** - `phantom run -- curl http://api.example.com/v1/users` - -## 🛠 CLI Structure -`phantom ` with global `-d, --data-dir ` and `-q, --quiet`. -Subcommands: `run` (capture), `list`/`get`/`search`/`stats`/`clear` (offline queries), `mcp` (MCP server over stdio). - -`run` flags: -- `-b, --backend `: Capture backend to use (`proxy` or `ldpreload`). Default: `proxy`. -- `-o, --output `: Output mode (`tui` or `jsonl`). Default: `tui`. -- `-p, --port `: Port for the proxy backend. Default: `8080`. -- `--insecure`: Disable TLS certificate verification for backend connections. -- `--agent-lib `: Path to `libphantom_agent.so` (required for `ldpreload`). -- `--max-body ` / `--headers-only`: Limit body output in JSONL mode. -- `-- `: The command to run with interception injected. - -### JSONL Output Schema -When using `run --output jsonl`, each line is a JSON object with: -- `trace_id`: W3C-compatible 128-bit trace ID (hex). -- `span_id`: 64-bit span ID (hex). -- `timestamp_ms`: Unix epoch milliseconds. -- `duration_ms`: Round-trip latency in ms. -- `method`: HTTP verb (GET, POST, etc.). -- `url`: Full request URL. -- `status_code`: HTTP response status. -- `protocol_version`: e.g., "HTTP/1.1". -- `request_headers` / `response_headers`: Header maps. -- `request_body` / `response_body`: UTF-8 decoded bodies (optional). -- `request_body_bytes` / `response_body_bytes`: Original body sizes (optional). -- `request_body_truncated` / `response_body_truncated`: Present when `--max-body` truncated (optional). - -## 🏗 Architecture & Tech Stack - -The project is organized as a Rust workspace: - -- **`phantom-core`**: Defines core traits (`TraceStore`, `CaptureBackend`) and `HttpTrace`. -- **`phantom-storage`**: Implements `TraceStore` using **Fjall** (LSM-tree). -- **`phantom-capture`**: Implements `CaptureBackend`. - - **ProxyBackend**: MITM HTTPS interception using `hudsucker`. - - **Node.js Integration**: Automatically injects `proxy-preload.js` via `--require` to capture HTTPS without code changes. - - **LdPreloadBackend**: Receives traces from `phantom-agent` via Unix Domain Sockets. -- **`phantom-agent`**: Linux-only `LD_PRELOAD` library hooking `libc` `send`/`recv`. -- **`phantom-tui`**: Interactive UI using **Ratatui**. - -### Key Technologies -- **Async Runtime:** `tokio` -- **Storage:** `fjall` (LSM-tree with key-value separation). -- **TUI:** `ratatui` -- **Proxy/MITM:** `hudsucker` -- **Serialization:** `serde`, `serde_json` - -## 🛠 Development Conventions - -### Coding Style -- Use `anyhow` for applications, `thiserror` for libraries. -- Prefer `Arc` for component sharing. -- Follow standard Rust idioms and `clippy`. - -### Testing -- `phantom-storage` uses `tempfile` for disk-based tests. -- **Integration Tests:** `tests/proxy_node_integration.rs` verifies the Node.js proxy injection. -- Run all tests: `cargo test`. - -### Project Roadmap (from `plan.md`) -- **Userspace eBPF:** Integration with `bpftime` for zero-instrumentation capture (10x faster than uprobes). -- **Workflow Inference:** Automatic generation of **Arazzo Specification** using **LLM** (`candle`) and semantic value correlation. -- **GUI:** Cross-platform desktop interface using **Tauri**. - -## 📂 Key Files -- `src/main.rs`: CLI entry point (subcommand dispatch, exit-code mapping). -- `src/cli.rs` / `src/runner.rs` / `src/commands/`: clap definitions, child spawning, run/query handlers. -- `src/mcp/`: MCP server (`rmcp` stdio, capture sessions + trace query tools). -- `crates/phantom-core/src/trace.rs`: `HttpTrace` definition. -- `crates/phantom-storage/src/fjall_store.rs`: Primary storage implementation. -- `crates/phantom-capture/src/proxy.rs`: Proxy-based interception logic. -- `crates/phantom-agent/src/lib.rs`: The `LD_PRELOAD` injection agent. -- `tests/proxy_node_integration.rs`: Node.js integration test suite. -- `plan.md`: Comprehensive technical design (Japanese). diff --git a/GEMINI.md b/GEMINI.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/README.md b/README.md index 6daa252..6832c5e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,81 @@ # Phantom [![CI](https://github.com/epli2/phantom/actions/workflows/ci.yml/badge.svg)](https://github.com/epli2/phantom/actions/workflows/ci.yml) + +Phantom is a zero-instrumentation HTTP/HTTPS API observability tool, written in Rust. It captures traffic from any process via a MITM proxy (or an `LD_PRELOAD` agent on Linux), and lets you explore it in an interactive terminal UI, stream it as JSON Lines, query it offline, or hand it to an AI coding agent over MCP — without touching the target application's code. + +## Features + +- **Interactive TUI** — browse captured requests/responses live, filter by URL. +- **JSON Lines streaming** — `phantom run --output jsonl` prints one JSON object per trace to stdout and exits with the traced process's exit code, ideal for scripting and CI. +- **Offline queries** — `phantom list` / `get` / `search` / `stats` filter and inspect previously captured traces without a live capture running. +- **MCP server** — `phantom mcp` exposes capture control and trace queries as tools for AI coding agents (e.g. Claude Code). +- **Zero-instrumentation capture** for common languages: + - **Node.js** — HTTPS captured transparently via an injected preload script (`http`, `https`, `undici`, `fetch`, `axios`, all supported). + - **PHP** — libcurl-based HTTP/HTTPS captured via injected `curl.cainfo`, no code changes. + - **Java** — JVM HTTP clients captured via an injected `-javaagent` and JVM proxy system properties. + - **Anything else** — `HTTP_PROXY`/`HTTPS_PROXY` are set automatically for the spawned command. +- **`LD_PRELOAD` backend** (Linux only) — hooks libc `send`/`recv` and OpenSSL directly, capturing HTTP + HTTPS for any dynamically linked process with no proxy configuration at all. +- **Docker sidecar mode** (`--bind 0.0.0.0`) — trace a target container you don't spawn, over a shared Docker network. +- **Fault injection** (`--fault`) — inject delays or error responses into proxied traffic for resilience testing. + +## Quickstart + +Build from source (requires Rust stable; a JDK is optional and only needed for Java capture support): + +```sh +cargo build --release +``` + +Trace a command — HTTP and HTTPS are captured with zero application changes: + +```sh +phantom run -- node app.js +phantom run -- java -jar app.jar +phantom run -- php app.php +phantom run -- curl http://api.example.com/v1/users +``` + +Stream traces as JSON Lines for scripting (exits with the child's exit code): + +```sh +phantom run --output jsonl -- node app.js | jq 'select(.status_code >= 400)' +``` + +Query traces captured in a previous run: + +```sh +phantom list --status 5xx --since 10m +phantom get +``` + +Run as an MCP server for AI coding agents: + +```sh +claude mcp add phantom -- phantom mcp +``` + +## CLI + +| Subcommand | Purpose | +|---|---| +| `run` | Capture traffic; optionally spawn and trace a command (`-- `) | +| `list` | Query stored traces (newest first) with filters | +| `get ` | One trace as pretty JSON | +| `search ` | Shorthand for `list --url ` | +| `stats` | Trace count and data directory as JSON | +| `clear --yes` | Delete all traces | +| `mcp` | MCP server over stdio, for AI coding agents | + +Run `phantom --help` for the full flag reference, or see [`AGENTS.md`](AGENTS.md) for the complete CLI structure, JSONL schema, and MCP tool list. + +## Documentation + +- [`docs/how-to-use.ja.md`](docs/how-to-use.ja.md) — detailed Japanese-language usage guide. +- [`AGENTS.md`](AGENTS.md) — architecture, CLI reference, and conventions for AI coding agents working on this repository (also available as `CLAUDE.md` / `GEMINI.md`). +- [`examples/docker-sidecar/`](examples/docker-sidecar/) — running phantom as a Docker Compose sidecar. +- [`plan.md`](plan.md) — technical design document (Japanese). + +## License + +Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option. diff --git a/docs/how-to-use.ja.md b/docs/how-to-use.ja.md index a717708..1b64e44 100644 --- a/docs/how-to-use.ja.md +++ b/docs/how-to-use.ja.md @@ -28,7 +28,7 @@ Phantom は **ゼロ計装の HTTP/HTTPS 観測ツール**です。アプリケ | 機能 | 詳細 | |------|------| | キャプチャ方式 | MITM プロキシ(透過的インジェクション対応) または LD_PRELOAD | -| 対応プロトコル | HTTP / HTTPS(プロキシ)、HTTP のみ(LD_PRELOAD) | +| 対応プロトコル | HTTP / HTTPS(プロキシ、LD_PRELOAD 両方) | | 対応 OS | プロキシ: macOS / Linux / Windows、LD_PRELOAD: Linux のみ | | 表示形式 | インタラクティブ TUI または JSON Lines (stdout) | | データ永続化 | Fjall KV ストア(LSMツリーによる高速保存) | @@ -39,7 +39,7 @@ Phantom は **ゼロ計装の HTTP/HTTPS 観測ツール**です。アプリケ **前提条件**: - Rust 1.75 以降(stable) -- **(Java 連携用)**: JDK 11 以降 +- **(Java 連携用、任意)**: JDK 11 以降 ```bash # リポジトリを取得 @@ -48,16 +48,10 @@ cd phantom # 本体 (Rust) のビルド cargo build --release - -# Java Agent のビルド (Java アプリを追跡する場合に必要) -# ※ 詳細は crates/phantom-java-agent 参照 -cd crates/phantom-java-agent -javac -d out src/com/example/phantom/Agent.java -echo "Premain-Class: com.example.phantom.Agent" > manifest.txt -jar cvfm phantom-java-agent.jar manifest.txt -C out . -cd ../.. ``` +`cargo build` 実行時に `build.rs` が `crates/phantom-java-agent/` の Java Agent (`Agent.java`) を `javac`/`jar` で自動ビルドし、`phantom-java-agent.jar` として埋め込みます。JDK が見つからない環境(JDKなしのCI/Dockerイメージなど)では、ビルド自体は空のプレースホルダjarで継続されますが、その場合 Java アプリのトレース機能(`-javaagent` 注入)だけが無効になります。手動でのビルド操作は不要です。 + --- ## クイックスタート @@ -66,23 +60,23 @@ cd ../.. ### 1. Node.js アプリをトレース ```bash -phantom -- node app.js +phantom run -- node app.js ``` ### 2. Java アプリをトレース (HTTP/HTTPS 両対応) -Phantom は自動的に Java Agent を注入し、プロキシ設定と SSL 検証の無効化(MITM 対応)を強制します。 +Phantom は `JAVA_TOOL_OPTIONS` 経由でプロキシ設定 (`-Dhttp(s).proxyHost/Port`) と Java Agent (`-javaagent:phantom-java-agent.jar`) を自動的に注入し、JVM 全体の SSL 検証を無効化(MITM 対応)します。 ```bash -phantom -- java -jar my-app.jar +phantom run -- java -jar my-app.jar ``` ### 3. 一般的なコマンドをトレース (HTTP のみ) ```bash -phantom -- curl http://httpbin.org/get +phantom run -- curl http://httpbin.org/get ``` -### 3. JSONL モードでストリーム処理 +### 4. JSONL モードでストリーム処理 ```bash -phantom --output jsonl -- node app.js | jq 'select(.status_code >= 400)' +phantom run --output jsonl -- node app.js | jq 'select(.status_code >= 400)' ``` --- @@ -94,33 +88,40 @@ phantom --output jsonl -- node app.js | jq 'select(.status_code >= 400)' MITM(中間者)プロキシとして動作します。クロスプラットフォーム対応で、HTTPS もキャプチャ可能です。 #### Node.js の自動連携 -`phantom -- node app.js` のように実行すると、Phantom は `--require` 引数を用いて透過的にプロキシ設定を注入します。これにより、**axios, undici, fetch() などを用いた HTTPS 通信もコード変更なしでキャプチャ可能**です。 +`phantom run -- node app.js` のように実行すると、Phantom は `--require` 引数を用いて透過的にプロキシ設定を注入します。これにより、**axios, undici, fetch() などを用いた HTTPS 通信もコード変更なしでキャプチャ可能**です。 #### Java の自動連携 -`phantom -- java ...` のように実行すると、Phantom は環境変数 `JAVA_TOOL_OPTIONS` を介して **Phantom Java Agent** を注入します。 +`phantom run -- java ...` のように実行すると、Phantom は環境変数 `JAVA_TOOL_OPTIONS` を介して **Phantom Java Agent** を注入します。 - **SSL 検証の自動回避**: Phantom が生成する自己署名証明書を自動的に信頼させるため、`SSLHandshakeException` を回避できます。 - **プロキシの強制適用**: アプリ側でプロキシ設定が書かれていなくても、通信を強制的に Phantom へ誘導します。 - **対応ライブラリ**: JDK 標準の `HttpClient`、`Apache HttpClient`、`OkHttp` など。 - ※ `Netty` や `Jetty` など独自のネットワークスタックを持つライブラリは、ライブラリ側の設定で「システムプロキシを使用する」オプションを有効にしてください。 +#### PHP の自動連携(curl 拡張) +`phantom run -- php app.php` のように実行すると、Phantom が生成した MITM CA 証明書を一時 PEM ファイルへ書き出し、`-d curl.cainfo=` として自動注入します。libcurl は `HTTP_PROXY`/`HTTPS_PROXY` を標準で読むため、コード注入なしで curl 拡張の HTTP/HTTPS 通信(Guzzle のデフォルトハンドラを含む)をキャプチャできます。 + +- 対象は **curl 拡張のみ**(`file_get_contents` などの PHP streams は対象外)。 +- `curl.cainfo` の利用には **PHP 5.3.7 以降**が必要です。 +- アプリ側が `CURLOPT_CAINFO`/`CURLOPT_SSL_VERIFYPEER` を明示的に設定している場合、Phantom の CA 注入が上書きされ HTTPS キャプチャが失敗することがあります。 + #### その他のアプリケーション 環境変数 `HTTP_PROXY` を自動設定します。 ```bash # 明示的にポートを指定して起動 -phantom --port 9090 -- curl http://example.com +phantom run --port 9090 -- curl http://example.com ``` ### LD_PRELOAD モード(Linux 限定) -アプリケーションのシステムコールを直接フックします。プロキシ設定を無視するツールや、コンテナ内での利用に適していますが、**平文 HTTP のみ**対応です。 +アプリケーションの libc 呼び出し(`send`/`recv`)と OpenSSL 呼び出し(`SSL_write`/`SSL_read`)を直接フックします。プロキシ設定を無視するツールや、コンテナ内での利用に適しており、**HTTP・HTTPS の両方**に対応します(プロキシ証明書は関与しません)。動的リンクされたプロセスであれば言語を問わず動作します。 ```bash # エージェントをビルド cargo build -p phantom-agent # トレース実行 -phantom --backend ldpreload \ +phantom run --backend ldpreload \ --agent-lib ./target/debug/libphantom_agent.so \ -- curl http://example.com ``` @@ -166,9 +167,15 @@ OPTIONS: -b, --backend [proxy, ldpreload] (デフォルト: proxy) -o, --output [tui, jsonl] (デフォルト: tui) -p, --port プロキシポート (デフォルト: 8080) + --bind プロキシのバインドアドレス (デフォルト: 127.0.0.1) + 0.0.0.0 で他ホスト/コンテナから到達可能に(認証なし、信頼できるネットワークのみ) --insecure バックエンド接続時の TLS 検証を無効化 -d, --data-dir データ保存先 --agent-lib libphantom_agent.so のパス (ldpreload 用) + --fault フォルトインジェクション(繰り返し指定可、proxy バックエンドのみ) + 例: delay:100ms, delay:100ms-500ms, error:503, error:500:0.1:/api + --max-body JSONL 出力時のボディを N バイトに切り詰め (0 = 無制限) + --headers-only JSONL 出力からボディを省略 -- 実行・追跡するコマンド ```