Add daemon RPCs, Apple and GTK import flows, packet proxy runtime support, diagnostics, and BEPs for proxy subscription handling. Redact subscription URL secrets from fetch errors before they reach logs or UI surfaces.
8.9 KiB
BEP-0009 - Trojan Proxy and Subscription Import
Status: Superseded
Proposal: BEP-0009
Authors: gpt-5.5
Coordinator: gpt-5.5
Reviewers: Pending
Constitution Sections: II, IV, V
Implementation PRs: Pending
Decision Date: 2026-05-27
Summary
Superseded by evolution/proposals/BEP-0010-proxy-subscriptions-as-packet-tunnel-networks.md.
Burrow should add daemon-owned Trojan proxy support as a proxy egress transport, plus a subscription importer that can parse base64 URI subscriptions containing trojan:// nodes. This proposal covers Trojan profile ingestion, validation, storage, runtime boundaries, and user-facing import behavior without claiming broader Clash or Mihomo protocol parity.
Trojan support should be implemented as an explicit Burrow protocol family with tested URI parsing and daemon-managed runtime behavior. Apple clients may present imported profiles and statuses, but they must continue to talk only to the daemon over gRPC.
Motivation
- Real-world proxy subscriptions commonly expose Trojan nodes as base64-encoded lists of
trojan://URIs rather than static Clash YAML. - Users should be able to import a subscription URL and let Burrow identify compatible nodes without leaking tokens into logs, source files, or UI copy.
- Trojan is different from WireGuard, Tailnet, and future MASQUE
CONNECT-IP; it needs an explicit profile model, TLS validation policy, and proxy egress runtime. - Supporting one proxy protocol first gives Burrow a concrete path for future proxy families without adding an unbounded "Clash compatible" claim.
Detailed Design
- Add a new daemon-owned network/profile type for Trojan proxy egress.
- The stable code/protocol identifier should use
trojan. - User-facing copy should spell the project name as
Burrowand should name the protocol asTrojan. - The profile type should be distinct from
WireGuardandTailnet.
- The stable code/protocol identifier should use
- Define a
TrojanProfilepayload with at least:- display name
- server host
- server port
- password or credential reference
- TLS server name indication
- optional peer/host metadata when present in imported subscriptions
- transport, initially restricted to
tcp - certificate verification policy
- source metadata such as imported subscription name and refresh timestamp
- Add a subscription import flow owned by the daemon.
- Fetch subscription URLs in daemon code, not Swift UI.
- Redact query tokens and credentials from logs and errors.
- Accept base64 URI subscriptions whose decoded body is a newline-separated URI list.
- Parse
trojan://URIs and reject unknown schemes unless future proposals add them. - Preserve node labels from URI fragments as display names after normalization.
- Treat
allowInsecure=1,skip-cert-verify=true, or equivalent flags as an explicit insecure TLS policy. - Deduplicate imported nodes by stable profile fields rather than display label alone.
- Add daemon gRPC methods before any Apple UI work.
- A minimal shape is
SubscriptionImportPreview,SubscriptionImportApply, andSubscriptionRefresh. - Preview should return compatible profile counts, rejected entry counts, redacted warnings, and normalized display labels.
- Apply should write only selected compatible profiles.
- Refresh should preserve local enable/order choices where possible.
- A minimal shape is
- Add runtime support in stages.
- Stage 1: parser, preview, storage, and tests only.
- Stage 2: daemon-managed Trojan outbound connector for TCP proxy egress.
- Evaluate
trojan-rust/trojan-rustas the first implementation dependency for this stage.- Prefer the narrowest usable crate, likely
trojan-protofor protocol parsing/serialization ortrojan-clientfor a SOCKS5-backed client runtime. - Avoid depending on the top-level
trojancrate with default features unless Burrow needs the bundled CLI, certificate, SQL, or agent features. - Wrap any external runtime API behind a Burrow-owned adapter so profile storage, logging, kill-switch behavior, and daemon lifecycle remain local.
- Prefer the narrowest usable crate, likely
- Stage 3: route/DNS integration with Burrow's tunnel and proxy selection model.
- Stage 4: UI controls for import, refresh, certificate policy warnings, and per-profile status.
- Keep the runtime boundary explicit.
- Apple UI may display forms, previews, warning states, and daemon statuses.
- Apple UI must not fetch subscription URLs directly.
- Apple UI must not open Trojan sockets directly.
- Any helper process must be brokered and supervised by the daemon.
Security and Operational Considerations
- Subscription URLs often contain bearer tokens. Burrow must treat full subscription URLs as secrets.
- Imported Trojan URIs contain passwords. Burrow must avoid writing decoded raw subscriptions to logs, crash reports, test snapshots, or telemetry.
- Certificate verification defaults should be secure. Insecure imported nodes may be stored only with an explicit warning field and UI-visible risk state.
- Passwords should move into the same secret-storage path Burrow uses for other long-lived credentials instead of remaining in plain payload blobs.
- The importer must set fetch limits for response size, redirect depth, and timeout.
- The parser must be independent and fuzzable enough to handle malformed URI lists without panics.
- Runtime support should include a kill-switch path so disabling a profile tears down active sockets and route state.
- Burrow must not present Trojan as a VPN with the same security or routing semantics as WireGuard. It is a proxy egress transport unless later proposals define full-device routing behavior.
Contributor Playbook
- Add parser-only fixtures for representative
trojan://URIs, including TLS SNI, host, peer, TCP transport, fragments, duplicate labels, malformed ports, unsupported schemes, and insecure certificate flags. - Add a redacted subscription fixture that mirrors a real base64 URI-list response without preserving live tokens, passwords, or hostnames that identify a paid account.
- Extend
proto/burrow.protowith daemon-owned subscription preview/apply/refresh RPCs before adding Apple UI. - Add daemon storage for
trojanprofiles and migrate old payload storage only if the profile model requires it. - Verify generated Swift and Rust bindings compile after proto changes.
- Implement runtime behind a feature flag or internal capability gate until end-to-end proxy egress tests exist.
- Run:
cargo test --workspace --all-features
python3 Scripts/check-bep-metadata.py
- For Apple work, verify no Swift UI or support code fetches subscription URLs or talks to Trojan endpoints directly.
Alternatives Considered
- Import full Clash or Mihomo YAML first. Rejected for this proposal because it would imply a broad compatibility contract across many protocols before Burrow has a proxy abstraction.
- Shell out to Mihomo as a helper. Rejected as the default path because it would create a large external runtime dependency and make Burrow's protocol guarantees harder to test. A future proposal may revisit helper-based compatibility as an explicit adapter.
- Vendor or reimplement the Trojan wire protocol immediately. Rejected as the default path while
trojan-rust/trojan-rustappears to provide GPL-compatible Rust crates for protocol parsing and client behavior. Burrow should still keep an adapter boundary so it can replace the dependency if maintenance, API, or security review fails. - Treat Trojan nodes as WireGuard-like networks. Rejected because Trojan is proxy egress over TLS, not a packet VPN with WireGuard peer semantics.
- Let Apple UI fetch and parse subscriptions for convenience. Rejected because it violates the daemon IPC boundary and spreads subscription tokens into UI code.
Impact on Other Work
- Depends on the daemon boundary in BEP-0005.
- Should align with the transport-neutral route and policy work described in BEP-0003, but should not block parser-only subscription import.
- Creates a path for future Shadowsocks or VLESS proposals by forcing shared subscription parsing and redaction rules.
- May require a follow-up secret-storage proposal if current network payload storage cannot safely hold proxy credentials.
Decision
Superseded by evolution/proposals/BEP-0010-proxy-subscriptions-as-packet-tunnel-networks.md on 2026-05-27.
References
- Trojan protocol: https://trojan-gfw.github.io/trojan/protocol.html
- Trojan config: https://trojan-gfw.github.io/trojan/config.html
- Trojan reference implementation: https://github.com/trojan-gfw/trojan
- Rust Trojan implementation candidate: https://github.com/trojan-rust/trojan-rust
- Rust
trojan-clientcrate: https://crates.io/crates/trojan-client - Rust
trojan-protocrate: https://crates.io/crates/trojan-proto - Mihomo Trojan proxy configuration: https://wiki.metacubex.one/en/config/proxies/trojan/
- BEP-0003:
evolution/proposals/BEP-0003-connect-ip-and-negotiation-roadmap.md - BEP-0005:
evolution/proposals/BEP-0005-daemon-ipc-and-apple-boundary.md - Burrow protocol schema:
proto/burrow.proto