- aura-cli config gains [transport] (order + per-transport ports + obfuscate/ masquerade); server binds all enabled transports via MultiServer, client uses dial() with UDP->TCP->QUIC handover. Config examples updated; backward-compatible (defaults to udp,tcp,quic). 21 cli tests incl. a real-UDP-transport loopback. - docs/sing-box.md: integration approach note (process-bridge now; native Go outbound for phones, with crypto-library mapping + KAT requirement). - Normalize rustfmt across the v2 transport files (tcp/dial/udp contract). Whole workspace: 97 tests pass, clippy -D warnings clean, fmt clean. Deploy flow (pki init/issue-server/issue-client) validated with the release binary. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4.0 KiB
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.
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 clientalready 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-boxsocksoutbound pointing at127.0.0.1:<port>.
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
0x01HS /0x02DATA) 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.mdthe single source of truth and version the wire protocol (the header already carriesversion = 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.