# Integrating AuraVPN with sing-box (approach note) Goal: let a phone client running **sing-box** connect to an Aura server speaking the **AuraVPN** protocol (Aura's own tunneling — not a third party's). This is a short note on *how*; the wire protocol it must match is fully specified in [`protocol.md`](protocol.md). sing-box is written in Go and has no generic "load an arbitrary external wire protocol" plugin, so integration means giving sing-box a Go implementation (or a bridge) of the Aura protocol. Three realistic paths, cheapest first: ## Option A — Process bridge (fastest, desktop/server) Run the existing Rust `aura` client as a local process and expose a local proxy/TUN, then point sing-box at it: - `aura client` already creates a TUN and routes through the Aura tunnel; sing-box can route selected traffic into that interface, **or** - add a local **SOCKS5 inbound** to `aura-cli` (small addition) and configure a sing-box `socks` outbound pointing at `127.0.0.1:`. Pros: reuses the audited Rust core verbatim; no crypto re-implementation. Cons: two processes; weak fit for mobile (sing-box mobile apps embed the core and don't spawn helpers easily). ## Option B — Native Go outbound/inbound (the real target for phones) Implement the AuraVPN protocol natively in Go and register it as a sing-box **outbound** (client) and **inbound** (server), so the phone's embedded sing-box core speaks AuraVPN directly. This is the clean, performant, mobile-friendly path. Crypto maps cleanly to existing Go libraries: | Aura piece | Rust crate | Go equivalent | |---|---|---| | X25519 ECDH | `x25519-dalek` | `crypto/ecdh` (stdlib) | | ML-KEM-768 (FIPS 203) | `ml-kem` | `crypto/mlkem` (Go 1.24+) or `cloudflare/circl` | | ChaCha20-Poly1305 | `chacha20poly1305` | `golang.org/x/crypto/chacha20poly1305` | | HKDF-SHA256 | `hkdf` | `golang.org/x/crypto/hkdf` | | HMAC-SHA256 (Finished) | `hmac` | `crypto/hmac` + `crypto/sha256` | | ECDSA P-256 sigs (cert auth) | `ring` | `crypto/ecdsa` + `crypto/x509` | | X.509 verify + CRL | `rustls-webpki` | `crypto/x509` | What the Go code must reproduce **exactly** (see `protocol.md`): - 5-byte frame header `msg_type(1) || len(u24 BE) || version=0x01`. - Handshake order CH → SH → ServerAuth → ClientAuth → Finished(c→s) → Finished(s→c); transcript = `SHA-256(ClientHello_frame || ServerHello_frame)`; ECDSA-P256/SHA-256 signature over the transcript; HMAC-SHA256 Finished. - Hybrid shared secret = `x25519_ss || mlkem_ss`; HKDF salt = `client_nonce || server_nonce`, info = `b"aura-v1-session"`. - Data record (datagram/UDP) = `seq(8 BE) || ChaCha20Poly1305(frame, aad = seq)`, nonce = `LE(seq) || 0x00000000`; replay window 64. (Stream/TCP record adds the 5-byte header to the AAD.) - Transport selection: UDP (type `0x01` HS / `0x02` DATA) primary; TCP/443 and QUIC fallbacks. To de-risk the Go port, export **known-answer test vectors** from the Rust side (a captured handshake transcript + derived keys + a sealed data record) and assert the Go implementation reproduces them byte-for-byte. The ML-KEM KAT already lives in `aura-crypto/tests/kat_kyber.rs`. ## Option C — Rust core via cgo (`cdylib`) Compile the Aura Rust core to a C-ABI shared library and call it from a thin sing-box Go shim via cgo. Reuses the audited crypto/handshake with no Go re-implementation, but cgo + per-platform (Android/iOS) packaging is fiddly and complicates sing-box's pure-Go build. ## Recommendation - **Now:** Option A (process bridge) for desktop/server validation — minimal work, real protocol. - **For the phone:** Option B (native Go outbound), built against `protocol.md` + exported Rust test vectors. It is the only option that fits sing-box's embedded mobile core well. - Keep `protocol.md` the single source of truth and version the wire protocol (the header already carries `version = 0x01`) so the Rust and Go implementations stay in lockstep. > Status: this is a design note. No Go code or sing-box module is implemented yet — that is a > separate deliverable tracked for after the Rust transport stabilizes.