From 0325592e280b04f73f800ee33d9637524ffcf34d Mon Sep 17 00:00:00 2001 From: GenSpark AI Developer Date: Wed, 3 Jun 2026 00:19:51 +0000 Subject: [PATCH] docs(adr): document Rust-core/Xray boundary (ADR-0007); clarify XDP model The integration proposals (Topology A/B SOCKS5 handoff, TCP sequence-number injection, SNI spoofing, eBPF/XDP packet rewriting, 'Rust as egress engine') all assume the Rust core forwards bytes to the internet. Verified against the source, it does not: - PolicyAwareTlsBackend has no socket dialing; it only models ALPN lock/bypass. - main.rs handle_client reads+parses a ClientHello and runs JA3 self-audit; it never forwards upstream or hands off to Xray. - the only TcpStream::connect in src/ is a unit-test client. - xdp/tun/overlay/scheduler modules are models and regression fixtures. This is exactly the confusion ADR-0001 anticipates but states too briefly, so: - ADR-0007: the Rust core is a validation/parsing/policy-modeling library plus a self-audit harness, explicitly NOT the data plane. Packet-injection / SNI-spoofing / raw-socket / eBPF-on-egress and 'Rust as egress' are out of scope (would require a new ADR revisiting ADR-0001 + threat-model + the consent-based privilege story from ADR-0002/0006). Notes that process_supervisor.py already gives atomic Rust+Xray lifecycle containment without changing the byte path. - architecture.md: add a 'Rust core: validation library, not a data plane' section making the Xray=data-plane / Rust=validate-around-it split visible. - ingress_xdp_gateway.rs: module doc comment clarifying it is a model/fixture, not a loaded eBPF program (the most misleading module name). - repository-structure.md: index ADR-0007. Docs + one harmless Rust doc-comment. Full offline suite: 34/34 pass. --- ...-rust-core-is-validation-not-data-plane.md | 76 +++++++++++++++++++ docs/architecture.md | 21 +++++ docs/repository-structure.md | 1 + src/ingress_xdp_gateway.rs | 8 ++ 4 files changed, 106 insertions(+) create mode 100644 docs/adr/0007-rust-core-is-validation-not-data-plane.md diff --git a/docs/adr/0007-rust-core-is-validation-not-data-plane.md b/docs/adr/0007-rust-core-is-validation-not-data-plane.md new file mode 100644 index 0000000..114ad9f --- /dev/null +++ b/docs/adr/0007-rust-core-is-validation-not-data-plane.md @@ -0,0 +1,76 @@ +# ADR 0007: The Rust Core Is A Validation Library, Not A Data Plane + +## Status + +Accepted. + +## Context + +The `src/*.rs` tree looks, at a glance, like a live proxy engine: it has an +ingress trait (`ingress.rs`, `ingress_loopback.rs`, `ingress_android_tun.rs`, +`ingress_xdp_gateway.rs`), a `handle_client` accept loop in `main.rs`, a TLS +orchestrator (`tls_orchestrator.rs`), a ClientHello parser (`parser.rs`), JA3 +logic (`ja3.rs`), and a scheduler. This naming repeatedly invites proposals to: + +- modify `handle_client` to dial upstream over a SOCKS5 handshake to Xray; +- add raw-socket TCP sequence-number injection / SNI-spoofing inside the + orchestrator; +- load eBPF/XDP programs from `ingress_xdp_gateway.rs` to rewrite live packets; +- treat the Rust binary as the egress data plane with Xray as a sidecar. + +These proposals assume the Rust core forwards bytes to the internet. **It does +not.** Establishing the actual boundary as an accepted decision stops this +confusion from recurring and prevents accidental scope creep into a second, +competing runtime (which ADR-0001 already rules out, but only briefly). + +What the Rust core actually does today (verified against the source): + +- `PolicyAwareTlsBackend` (`tls_orchestrator_backend.rs`) implements ALPN + negotiation/lock policy and bypass decisions. It contains **no socket dialing** + and never connects upstream. +- `main.rs` `handle_client` reads a ClientHello off a loopback socket, parses it, + runs ALPN orchestration *modeling* and an optional JA3 self-audit + (`MITM_STREAM_EXPECTED_JA3`), and reports. It does **not** forward traffic to a + destination or to Xray. +- The only `TcpStream::connect` in `src/` is the client side of a unit test in + `ingress_loopback.rs`. +- `ingress_xdp_gateway.rs`, `ingress_android_tun.rs`, `cooperative_overlay.rs`, + `h2_coalescing.rs`, and `scheduler.rs` are modeled abstractions and regression + fixtures, not loaded kernel programs or a live scheduler on the egress path. + +## Decision + +The Rust core is a **validation, parsing, and policy-modeling library plus a +self-audit harness**. It is explicitly *not* the runtime data plane and must not +be wired into the live traffic path. Xray is the data plane (ADR-0001). + +Concretely: + +- The Rust core may parse, classify, score, model, and self-audit (e.g. confirm + that a configured uTLS fingerprint produces the expected JA3). Its outputs are + evidence and regression signals, not forwarded bytes. +- The Rust core must not open upstream connections, perform SOCKS5 client + handshakes to Xray, manipulate raw packets, inject TCP segments, or load + eBPF/XDP. Those belong to Xray (or, if ever justified, to a future Go/Xray-core + contribution per ADR-0001). +- Integration with Xray is **config-and-evidence**, not in-band byte handoff: + the toolchain generates and validates Xray config, runs Xray as the runtime, + and the Rust core validates/observes around it. + +## Consequences + +- Proposals to add packet injection / SNI-spoofing / sequence-number tricks, or + to make the Rust binary the egress engine, are out of scope here. They would + require: (a) a new ADR revisiting ADR-0001, (b) a real threat-model review, and + (c) the privilege/safety story (`CAP_NET_RAW`, Administrator) that ADR-0002 and + ADR-0006 deliberately keep consent-based. +- `process_supervisor.py` already provides atomic, kill-on-close lifecycle + containment (Windows Job Object, POSIX process group). A "run Rust + Xray as + one machine" conductor can be built on it *without* changing the byte path — + the Rust process stays a self-audit/observer alongside Xray, not an inline hop. +- If a Rust capability is ever promoted to the data plane, it should be + implemented where the data plane lives (Xray-core in Go), not by turning the + validation library into a parallel proxy. +- Module names that imply a live data plane (e.g. `ingress_xdp_gateway`) should + carry doc comments clarifying they are models/fixtures, to reduce future + confusion. diff --git a/docs/architecture.md b/docs/architecture.md index 1373c64..434aeb7 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -49,6 +49,27 @@ generate cert -> install cert -> import config -> run client -> use browser Add maintainability around that path through docs and scripts, not through a complex runtime architecture. +## Rust core (`src/`): validation library, not a data plane + +The `src/*.rs` tree is named like a proxy engine (ingress traits, a +`handle_client` loop, a TLS orchestrator, a scheduler), but it is **not** on the +live traffic path. It parses ClientHellos, models ALPN/JA3/routing policy, and +runs a self-audit/regression harness. It does not forward bytes to the internet +and does not hand traffic to Xray over SOCKS5. + +```text +Xray = data plane (proxy, routing, MITM, domain-fronting, uTLS) — see ADR-0001 +Rust = parse / classify / model / self-audit around Xray's config and behavior + (no upstream dialing, no raw-packet manipulation, no eBPF on egress) +``` + +Integration between the two is **config + evidence**, never an in-band byte +handoff. See `docs/adr/0007-rust-core-is-validation-not-data-plane.md` for the +full boundary, including why packet-injection / SNI-spoofing / "Rust as egress +engine" proposals are out of scope. Process lifetime (running the Rust self-audit +alongside Xray) is handled by `scripts/core/process_supervisor.py`, which already +provides atomic kill-on-close containment without changing the byte path. + ## Diagnostic and governance layer Local validation sits beside the runtime graph. Nothing in this layer uploads telemetry or changes runtime config automatically. The GUI may write local-only operational telemetry under `.local-state/` for status history, command durations, and redacted troubleshooting evidence. diff --git a/docs/repository-structure.md b/docs/repository-structure.md index c429b6d..40519a1 100644 --- a/docs/repository-structure.md +++ b/docs/repository-structure.md @@ -54,6 +54,7 @@ MITM-DomainFronting/ 0004-ja3-oracle-honesty.md 0005-local-source-labeled-telemetry.md 0006-target-user-and-progressive-disclosure.md + 0007-rust-core-is-validation-not-data-plane.md fa/ quick-start.md reference/ diff --git a/src/ingress_xdp_gateway.rs b/src/ingress_xdp_gateway.rs index 8a97358..9253c93 100644 --- a/src/ingress_xdp_gateway.rs +++ b/src/ingress_xdp_gateway.rs @@ -1,3 +1,11 @@ +//! Model/fixture for an XDP-style batch packet ingress. +//! +//! NOTE: This is a validation model, not a loaded eBPF/XDP program on the live +//! egress path. The Rust core is a validation library, not the data plane — see +//! `docs/adr/0007-rust-core-is-validation-not-data-plane.md` and ADR-0001. Do +//! not wire raw-packet manipulation or kernel programs in here; the data plane +//! is Xray. + use crate::ingress::{BatchPacketBuffer, IngressError, PacketIngress, PacketRef}; #[derive(Debug, Clone, Copy, PartialEq, Eq)]