f68a61f7609d282325b67c863aab921e22fb237d
20 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7c2080321b |
feat(cli,tunnel): v3.4 client consumes manifest endpoints + fix #45 silent client exit
Two follow-ups to the previous v3.4 commit (
|
||
|
|
ba8d6b796f |
feat(transport,cli,tunnel): v3.4 port auto-detect + bug fixes from live test
Live macOS test against the production server uncovered six bugs (one of which turned out to be a port collision with sing-box, not a real bug); this commit addresses all of them and adds v3.4 port discovery so the same collision is handled transparently next time. ## v3.4 server port-discovery - Defaults moved off 443/444 to 8443/8443/8444 (TransportSection::default, ServerInitOpts, ProvisionClientOpts, CLI flags). 443 is heavily contested in practice (sing-box, Hysteria2, reverse proxies) and the previous default silently lost the bind when a co-tenant was already there. - MultiServer::bind_with_outer_or_scan: scans forward up to DEFAULT_PORT_SCAN_MAX (20) candidates per transport when the requested port is occupied; QUIC keeps walking if it lands on the custom-UDP port. - MultiServer::bound_addrs(): the actual addresses each transport bound to. - Server logs the bound addresses and writes a runtime snapshot (server.toml.runtime.json) when they differ from the requested ones, so `aura sign-bridges` can re-sign the bridges manifest later. - BridgeManifest gains an optional `endpoints: Vec<BridgeEndpoint>` field with per-transport ports. Backward-compatible: old v3.3 clients ignore the field and continue to use the v1 `bridges` line. - `aura sign-bridges --endpoints HOST:tcp=N:quic=N:udp=N` to mint v3.4 manifests; bridges line is auto-synthesised for v3.3 clients. ## Bug fixes from the live test - macOS TUN naming (#41): the tun crate rejects names that don't match ^utun[0-9]+$. On macOS we now substitute `""` (kernel auto-assigns utunN), capture the assigned name via inner.tun_name(), and propagate it through to os_routes::OsRouteGuard::install — so `route add -interface utunN` uses the real interface, not "aura0". - Packet counters (#42): Stats { tx_packets, rx_packets } are now actually bumped by the data path. `aura status` shows live numbers instead of permanent zeros. - render_client_toml schema (#44): provisioner emits proper `[[tunnel.split.vpn]] cidr = "..."` / `[[tunnel.split.direct]]` blocks from new --vpn-cidrs / --direct-cidrs flags. The v3.3 `vpn_cidrs = [...]` flat array was silently ignored by serde, leaving users with `rules: 0` even when their CIDRs looked right. - #43 / #46 (TCP/443 dial early-eof / no payload back): diagnosed as the sing-box port collision, not an Aura bug. The v3.4 port-scan path makes it go away — the server picks a free port and clients learn it from the manifest. ## Test coverage Three new unit tests for the port-scanner (UDP busy, TCP busy, zero budget); two new tests for v3.4 BridgeManifest round-trip with endpoints; one integration test for the new `[[tunnel.split.vpn]]` rendering; tests for the runtime-state file write/read round-trip; agent-added router-counter tests in aura-tunnel/tests/routes.rs. cargo test --workspace, cargo clippy --workspace -- -D warnings, and cargo fmt --check all pass. #45 (silent client exit when underlying QUIC transport breaks) is still outstanding — needs deeper investigation; deferred to a follow-up. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
a173ced9b2 |
feat(cli,pki): v3.3 bridge discovery via signed CA manifest
Closes the v3.3 "bridges by hand" honest limitation. Admins now publish a
CA-signed manifest with the current bridge list; clients re-read it from
disk on a timer and merge it with the static [client] bridges. Cuts the
"rotate the bridge list" cycle from "edit every client config" to
"distribute one signed file".
- New aura sign-bridges CLI:
aura sign-bridges --ca /etc/aura/pki \
--bridges "ip1:443,ip2:443" \
--ttl-days 7 \
--out /var/aura/bridges.signed
- Manifest format (single file, text + signature block, same shape as the
in-band CRL):
AURA-BRIDGES-v1
{"version":1,"generated_at":...,"expires_at":...,"bridges":[...]}
--SIGNATURE--
<hex ECDSA-P256/SHA-256 over body>
- aura-pki now exports `sign_ecdsa_p256` / `verify_ecdsa_p256` so CRL and
bridges share ONE signing primitive (no copy-paste). CRL keeps working.
- aura-cli::bridges::BridgeManifest + BridgesDiscoveryWatcher: new
module. encode_signed/load_signed_verified verifies signature + rejects
expired manifests. Watcher spawns a tokio interval that re-reads the
file; on load failure (truncated, expired, bad sig) the previous
snapshot is kept — bridges never collapse to empty.
- New [client.bridges_discovery] {enabled, manifest_path,
refresh_interval_secs}; serde(default) so v3.2 configs keep working.
- Merge strategy: manifest EXTENDS static [client] bridges, dedup by
SocketAddr, static-first ordering. Static remains as fallback.
- 13 new tests (8 lib unit + 4 integration + 1 config). Workspace: 310
tests passed (+13), clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
5e553b79df |
feat(cli): v3.3 circuit rotation — background rebuild every N seconds
Adds RotatingCircuit: the multi-hop circuit is silently torn down and
rebuilt on a configurable interval (default off) so a long-running
client periodically rotates its on-wire path. Application packets never
see the swap.
- RotatingCircuit::new(hops, udp_opts, interval) seeds an initial
CircuitConnection synchronously (errors surface), then spawns a
background rotator that every `interval`:
1. dial_circuit(&hops, udp_opts) -> next: CircuitConnection
2. std::mem::replace inside Arc<RwLock<Arc<CircuitConnection>>>
3. old Arc dropped when its last in-flight Arc clone is released
(its Drop aborts forwarders / closes outers).
send_packet/recv_packet grab a cheap snapshot of the current Arc
before awaiting, so reads/writes never block under the rotator.
- [client.circuit] rotation_interval_secs: u64 (default 0 = disabled);
serde(default) keeps old configs working. When 0, the path is exactly
the v3.2 dial_circuit + optional CellPaddingConn wrap (back-compat).
- CellPaddingConn wraps RotatingCircuit on the OUTSIDE so every new
circuit shares the same cell_size — on-wire size signature stays
stable across rotations.
- Integration test multihop_rotation::rotating_circuit_swaps_inner_
under_traffic: 6 s of 100-ms ping/echo at interval=1.5s -> 37 sent,
37 received, 2 rotations counted via test-only AtomicU64 counter.
- Synchronous-failure test confirms initial dial errors bubble up from
::new without spawning the rotator task.
Workspace: 297 tests passed (+4), clippy -D warnings clean, fmt clean.
293 baseline tests unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
5ea643a9e5 |
feat(cli,tunnel,docs): full Windows support — OS routes + wintun audit
Windows is now first-class for client use: - aura-cli::os_routes Windows path is no longer a stub. Real install via `route ADD <net> MASK <mask> <gw> METRIC 1` for DIRECT bypass (rollback: `route DELETE ...`) and `netsh interface ipv4 add route <cidr> "Aura" <tun_local_ip> store=active` for VPN default/CIDR (rollback: `netsh ... delete route ...`). Default-gateway detection by parsing `route print 0` output via parse_windows_route_print_default; rejects `On-link` rows. Dry run works on every host. - aura-tunnel::tun wintun audit fixed a real bug: AuraTun was holding only Arc<Session> while Session does NOT keep Arc<Adapter> alive (only the Wintun DLL handle). On Drop the adapter was being closed under the session. Fixed by adding _adapter: Arc<wintun::Adapter> to AuraTun, with field order ensuring Session is dropped before Adapter so end-session precedes close-adapter. Also wired mtu into write_packet (hard limit) + read_packet (warn). - Cross-compile verified: cargo check --target x86_64-pc-windows-gnu --workspace and clippy on the windows target are both clean (added mingw-w64 + x86_64-pc-windows-gnu via rustup). - docs/deployment.md: §6 updated (Windows OS-routes now Done), new §8 «Windows как клиент» with download wintun.dll, Admin run, [tunnel.os_routes] enabled, known no-ops (run_as, [server.nat]). 9 new tests (7 parser/plan/undo unit + 1 windows dry-run integration + 1 existing). Workspace: 293 tests passed (+9), clippy -D warnings clean, fmt clean. macOS host + windows-gnu cross-target both green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e0e53665f1 |
feat(crypto,cli,docs): russian SNI palette + RF-billing deployment scenario
Adds a way to make the outer-TLS SNI rotate among popular Russian-language
domains so that Russian carriers — who may start metering "foreign traffic"
separately — see the user's first hop as a domestic CDN/site request, not
as an exotic foreign destination.
- aura-crypto::masks:
- SNI_PALETTE_RUSSIAN (15 real domains: mail.yandex.ru, vk.com, www.ozon.ru,
dzen.ru, ya.ru, www.gosuslugi.ru, www.wildberries.ru, rutube.ru,
news.rambler.ru, hh.ru, www.tinkoff.ru, lenta.ru, www.kinopoisk.ru,
afisha.yandex.ru, music.yandex.ru).
- enum SniPalette { Default, Russian, Mixed } (Default = v2 behavior).
- derive_mask_for_msk_date_with_palette(...): pick from chosen palette,
Mixed flips ~50/50 by HKDF okm[8]&1. Old derive_mask_for_msk_date kept
as a thin wrapper -> byte-for-byte unchanged Default.
- aura-cli::masks::MaskRotator gains new_with_palette(...); the spawn loop
uses the stored palette. Old new() preserves Default.
- aura-cli config: [transport.masks] palette = "default"|"russian"|"mixed"
(serde rename_all = "lowercase", default Default).
- server.rs/client.rs read cfg.transport.masks.palette and pass it to the
rotator at startup; logged at INFO so the operator sees the choice.
- docs/deployment.md: new §7 "Сервер в РФ против тарификации иностранного
трафика" — context, ASCII topology, recommended RF providers, full
server.toml + client.toml examples wiring [server.relay] + russian
palette + LE outer cert + multi-hop, plus an honest list of what this
does and does not give.
- config/{server,client}.toml.example updated with palette = "default".
Workspace: 284 tests passed (+8 new = 4 crypto + 2 cli masks + 2 config),
clippy -D warnings clean, fmt clean. 276 baseline tests untouched.
Backward-compatible: configs without palette default to Default, identical
to v2 wire behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
9b98004424 |
feat(cli): v3.2 multi-hop — per-hop cert, cell padding, 3-hop, CIDR whitelist
Closes the v3.1 unlinkability gap and resists volume/timing correlation:
1) Per-hop client cert (identity-unlinkable hops). [[client.circuit.hops]]
now accepts {addr, cert_path, key_path, [server_name]} per hop — each
hop sees a different CN, so a relay and an exit cannot correlate the
same client by certificate. Old flat `hops = ["ip:port"]` form still
parses (serde untagged enum) and falls back to [pki] cert/key.
`aura provision-client --circuit-hops N` mints N fresh UUIDv4 certs.
2) Cell padding. CellPaddingConn wrapper pads every outgoing packet to a
fixed size (default 1280 bytes; `cell_size = N` configurable) before
it hits the inner AEAD. Format: u16_be(real_len) || pkt || zero_pad.
On-wire sizes become constant -> defeats volume/timing fingerprints.
Opt-in via [client.circuit] cell_padding = true and the mirror
[server] cell_padding_for_circuit_clients = true.
3) 3-hop support. dial_circuit now accepts N >= 2 hops; iterative
ExtendBridge nests N-1 forwarders and N handshakes. Client owns the
full chain via CircuitConnection (forwarders abort on drop).
New integration test multihop_v3_2_three_hops_end_to_end runs three
in-process actors (A relay -> B relay -> C exit) on loopback and
verifies peer_id == C's CN.
4) CIDR whitelist. [server.relay] allow_extend_to entries accept
"10.0.0.0/24" (subnet, any port), "10.0.0.0/24:443" (subnet + port),
"[2001:db8::/32]:443" (IPv6 with port), as well as exact IP:port.
Empty list keeps the v3.1 open-relay (warn).
19 new tests; workspace 276 passed (+19), clippy -D warnings clean, fmt clean.
257 baseline tests untouched; all v2 / v3.1 / LE configs work as before.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
f26ed7fce0 |
feat(cli,transport): Let's Encrypt outer-cert support on TLS-443/QUIC
Server admins can now point the outer TLS layer at a real CA-signed cert
(e.g. Let's Encrypt fullchain.pem) so the on-wire HTTPS camouflage is
indistinguishable from a normal CA-trusted HTTPS server. The inner Aura
mutual-auth handshake still uses the Aura CA (necessarily — that's where
the PQ mutual auth lives).
- aura-cli config: optional [server.outer_cert] {cert_path, key_path}.
Both fields together (or neither); resolve() reads PEMs and returns
(cert, key) tuple. Absent section -> falls back to reusing the Aura
server cert (v2 behavior, fully back-compat).
- aura-transport: additive MultiServer::bind_with_outer and
TcpServer::bind_with_outer that accept an optional separate outer cert.
Old MultiServer::bind / TcpServer::bind preserved as thin wrappers
(back-compat: existing callers untouched). AuraServer::bind already
took outer cert separately.
- UDP transport doesn't have outer TLS, so outer cert is irrelevant
there — only QUIC + TCP layers benefit.
- 4 new tests (parsing, back-compat, partial-section validation, two-CA
loopback verifying inner peer_id is the inner CN). Workspace: 257 tests
passed (+4), clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
fe618b839d |
feat(cli): v3.1 multi-hop runtime — circuit client + relay rendezvous
Completes v3.1 multi-hop / onion routing (2 hops: client → entry-relay →
exit-server). Combined with the scaffold commit (
|
||
|
|
6c14c0d103 |
feat(proto,cli): v3.1 multi-hop scaffold — control kinds + config sections
Foundation for v3.1 onion routing (client → entry-relay → exit-server).
The relay/circuit runtime is implemented in a follow-up commit; this
scaffold lands the wire-level control extensions and the config schema:
- aura-proto: ControlKind gains ExtendBridge (client→relay), CircuitReady
(relay→client), CircuitFailed (relay→client, with utf-8 reason); helpers
encode_extend_bridge / decode_extend_bridge (1-byte family + 4/16 addr
bytes + u16 port). Integration test in tests/control_extend.rs covers
IPv4/IPv6 roundtrip + full magic-envelope wrap.
- aura-cli config: [server.relay] {enabled, allow_extend_to} +
[client.circuit] {enabled, hops} sections; relay_whitelist() helper
parses IP:port literals. All new fields serde-default, back-compat.
- crl_push.rs touched only to leave the new ControlKinds passing through
the existing magic-envelope dispatcher unchanged.
Workspace: 247 tests passed (+12), clippy/fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
35d94dee33 |
feat(proto,pki,cli): in-band CRL push (closes last v2 limitation)
Server now pushes its signed CRL to each connecting client right after the
handshake; the client verifies the signature against the CA and applies the
revocation list to its verifier (and caches it on disk for restarts).
Removes the v1 "CRL distributed out-of-band" honest limitation.
Wire (multiplexed over existing PacketConnection, no trait change):
control envelope = MAGIC[4]=[0xAA,0xAA,0xC0,0x01] || kind(u8) || u32_be(len)
|| payload. IPv4/IPv6 start with 0x4X/0x6X, so 0xAA cannot collide; an old
peer just drops it as a junk packet in the TUN — back-compat preserved.
- aura-proto: ControlKind { CrlPush, CrlAck, Unknown }, encode/decode_control_
envelope, CONTROL_ENVELOPE_MAGIC; 7 frame tests.
- aura-pki: CrlStore::{encode_signed, save_signed, decode_signed_verified,
load_signed_verified} — ECDSA-P256/SHA-256 from the CA private key against
a textual "CRL-Aura-v1" body + --SIGNATURE--; 7 signing tests. ring 0.17
added crate-local (already in lockfile via rustls-webpki).
- aura-cli: crl_push module — server pushes via conn.send_packet on accept;
client wraps the Arc<dyn PacketConnection> in AcceptPushedCrlConn which
sniffs the magic in recv_packet, verifies the signature, updates the
AuraCertVerifier, caches to disk. PkiSection gets ca_key, crl_push (default
true), accept_pushed_crl (default true).
- 5 in_band_crl integration tests via mock PacketConnection.
Workspace: 235 tests passed (+28), clippy -D warnings clean, fmt clean. v2
COMPLETE — all 9 honest v1 limitations resolved (except sing-box, per user).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
8f0cf1f017 |
feat(cli): automation bundle + identity-minimization features
Reduces manual setup steps and trims user-identifying data exposed by the server/client, in the spirit of the deployment story: an operator on the wire sees less, and the admin types fewer commands. New CLI subcommands: - `aura server-init`: one shot — pki init + issue-server + writes a ready server.toml with auto-detected egress iface; flags --enable-knock, --enable-cover-traffic, --no-nat, --run-as toggle the new transport defenses and privilege drop. - `aura provision-client`: issues a client cert and assembles the full bundle (ca.crt + client.crt + client.key + client.toml in one directory) ready to hand over to the client device. --id is optional (defaults to a fresh UUIDv4, so client identities don't have to encode anything real). Identity / log minimization: - `aura pki issue-client --id` is now optional — UUIDv4 by default. - `[server]/[client] no_logs = true` filters peer_id, client_ip, source_addr, client_id, local_ip, user, id, assigned_ip, peer field values through a custom tracing FormatFields layer (events still fire but the identifying fields are redacted before being written). - `[client] bridges = [...]`: secondary server addresses; build_dial_targets shuffles them after the primary, so blocking one IP doesn't kill the client. - Auto-detect egress iface in [server.nat] (via detect_default_egress_iface); egress_iface in config becomes optional with graceful fallback. Config examples updated; backward-compatible (all new sections optional with serde defaults). Workspace: 207 tests passed (+22), clippy -D warnings clean, fmt clean. No new workspace deps. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
65b26b555d |
feat(cli): OS-level split-tunnel routes (removes send_direct stub)
DIRECT-destination traffic now bypasses the TUN entirely via OS routing
table edits, instead of going through user-space and hitting the v1
send_direct stub. The user-space router only sees VPN-bound packets,
making the split-tunnel real.
- aura_cli::os_routes::OsRouteGuard: RAII install + rollback of OS routes.
Linux: `ip route show default` parser -> DIRECT CIDRs via original gw,
VPN default via TUN with metric 50. macOS: `route -n get default`
parser -> `route add -net/-host ... <gw>` for DIRECT, `route add -net
... -interface <tun>` for VPN. Windows: stub + warning (v3).
- dry_run works on every platform (logs `would run: ...`); useful for
tests and operator confidence-checks.
- SplitRoutes::from_config folds [[tunnel.split.direct]]/[[...vpn]] +
resolved domains (via AuraDns) into one declarative plan.
- New [tunnel.os_routes] {enabled (default true), dry_run, gateway,
egress_iface}; absent section = old user-space behavior (back-compat).
- client::run installs routes after AuraTun::create, before privdrop;
guard's Drop reverts everything on shutdown.
- aura-tunnel::router unchanged; AuraRouter::send_direct kept as a
defensive fallback (in v2 it should never fire — OS routes prevent
DIRECT packets from reaching the TUN at all).
20 new tests (linux/macos parser unit tests, install dry-run, config
back-compat). Workspace: 174 tests passed (+19), clippy -D warnings
clean, fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
c6f0d7af9b |
feat(cli): auto-NAT + privilege drop + Windows named-pipe admin
Three v2-hardening features in aura-cli, one pass:
- nat::NatGuard: RAII auto-config of IP forwarding + MASQUERADE on server
startup. Linux (sysctl ip_forward + iptables -t nat MASQUERADE) and
macOS (sysctl ip.forwarding + pfctl with /tmp/aura-nat.conf). dry_run
works on every platform (logs "would run: ..."). Reverts everything in
Drop. New [server.nat] {auto, egress_iface, dry_run}; absent section =
back-compat no-op. Removes v1's "manual NAT/forwarding" step.
- privdrop::drop_to_user: drop euid/gid after binding TUN + privileged
ports. Linux setresuid/setresgid, macOS setgid+setuid (permanent drop),
Windows no-op with warning. New [server] / [client] run_as = "..."
(optional). Skipped with info-log if already non-root.
- admin: split transport into cfg(unix) Unix-socket and cfg(windows) Tokio
named-pipe modules sharing one JSON-line serve/request flow over
AsyncRead/AsyncWrite. DEFAULT_SOCKET = "/tmp/aura-admin.sock" on Unix,
r"\\.\pipe\aura-admin" on Windows. Removes v1's "admin Unix-only".
Deps: nix 0.29 user feature under [target.'cfg(unix)'.dependencies] (cli-
local, not workspace). Workspace: 155 tests passed (+13), clippy -D warnings
clean, fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
821f7711e7 |
feat(transport): real TLS-443 on the TCP backend (replaces HTTP/1.1 masquerade)
The TCP fallback now does a full outer TLS handshake (tokio-rustls 0.26 over
rustls 0.23, ring provider) before the Aura proto handshake, exactly like the
QUIC backend: on the wire it is indistinguishable from genuine HTTPS until the
inner Aura mutual-auth handshake starts. Removes v1's "light HTTP masquerade"
limitation; the real security boundary remains the inner PQ handshake.
- aura-transport::tcp: dropped the HTTP/1.1 preamble helpers and TcpOpts
fields (masquerade, host, user_agent, server_header). New flow:
TlsAcceptor::accept (server) / TlsConnector::connect (client) →
tokio::io::split(TlsStream) → server_handshake / client_handshake → Session.
Client reuses crate::quic::AcceptAnyServerCert (outer SNI not authenticated;
inner handshake is the security boundary). Outer server cert auto-sourced
from proto_cfg.server_cert_pem (no API change for the CLI's bind).
- ALPN default: ["h2", "http/1.1"] (DEFAULT_TCP_ALPN, exported).
- TcpOpts: now just { alpn: Option<Vec<Vec<u8>>> }.
- TcpClient::connect gains an outer-SNI &str param; DialConfig.sni passes it
through (separate from the inner proto_cfg.server_name).
- tokio-rustls 0.26 added as a transport-local dependency (not workspace).
CLI updates: removed dead host/user_agent/server_header wiring; mask rotation
no longer touches TCP outer parameters (TLS doesn't have a Host header on
the wire). [transport] masquerade kept as a no-op for back-compat with old
configs (documented).
3 new tcp_loopback tests (default ALPN end-to-end, custom ALPN, outer SNI
mismatch still connects = proves accept-any is in effect). Workspace: 142
tests passed (+1), clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
0a73d5298b |
feat(cli): server IP pool + per-client routing (multi-client VPN concentrator)
Server now assigns each connected client an IP from a configurable pool and
maintains a client_ip -> AuraConnection map so packets read from the shared
TUN are dispatched to the right client (and each client's recv loop writes
back to the TUN). Removes v1's "single shared TUN, no NAT/pool" limitation;
turns the server into a proper multi-client VPN concentrator (paired with the
already-landed UDP multi-client demux).
- aura_cli::pool: IpPool + PoolStrategy {StaticOnly, DynamicOnly,
StaticOrDynamic}; reserves network/broadcast/server-own IP; 15 tests.
- aura_cli::server_router: ServerRouter + ServerRoutes (Arc<RwLock<HashMap>>);
central TUN read loop dispatching by dst_ip; spawn_inbound_forwarder per
conn auto-unregisters and releases the IP on disconnect; 4 tests via
MockTun + MockConn.
- aura_cli::config: [server.pool] {cidr, strategy, static} added with
serde(default); legacy configs (only [tunnel] pool_cidr) fall back to a
DynamicOnly pool (backward compatible, tested).
- aura_cli::server: accept loop now: pool.assign(peer_id) -> register ->
spawn_inbound_forwarder; rejected static_only mismatches dropped+logged.
- config/server.toml.example: documented [server.pool] section.
Workspace: 141 tests passed (+24), clippy -D warnings clean, fmt clean. No
new workspace deps (async-trait added to cli dev-deps for mock traits in tests).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
c95e1a482c |
feat(crypto,cli,transport): daily protocol-mask rotation at 05:00 MSK
Both server and client deterministically rotate the on-wire obfuscation mask (SNI, HTTP Host/User-Agent/Server headers, UDP padding profile) at 05:00 Moscow time (02:00 UTC) every day, derived from the CA fingerprint + UTC date — no network coordination needed. - aura-crypto::masks: MaskSet + 4 palettes (16 SNI, 10 UA, 5 Server, 4 padding profiles); derive_mask_for_msk_date via HKDF-SHA256(salt="aura-mask-v1-salt", ikm=ca_fp||"YYYY-MM-DD", info="aura-mask-v1"); ca_fingerprint with built-in base64 PEM decode (no new deps). - aura-cli::masks: MaskRotator (Arc<RwLock<MaskSet>>) + Hinnant's civil_from_days for manual UTC date math; scheduler picks next 02:00 UTC strictly (avoids busy-loop at boundary); spawned at startup in server::run/client::run. - aura-transport: PADDING_PROFILES + next_bucket_for_profile (profile 0 byte-for- byte equals legacy pad_to_https_size); TcpOpts gains user_agent/server_header; UdpOpts gains padding_profile; MultiServer holds Arc<UdpServer>/Arc<TcpServer> with set_udp_opts/set_tcp_opts so rotation propagates without restart. - Backward-compatible: defaults preserve previous behavior; existing 97 tests unchanged. 17 new tests (derive determinism + date variation, civil-from-days known points incl. 1970-01-01/2000-02-29/2024->2025, next-rotation boundary, msk_today offset, profile equivalence, base64 round-trip, full mask-driven UDP loopback). Total: 114 passed, clippy/fmt clean. No new workspace deps. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
d5b9a8611d |
feat(cli): select transport in config; server MultiServer + client dial handover
- 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> |
||
|
|
cb89312a27 |
feat(cli): implement Wave 4 — aura binary (PKI, server/client, admin, bench)
aura-cli: clap command tree (pki init/issue-server/issue-client/revoke/list,
server, client, route add/list/remove, status, bench-crypto); TOML config with
~ expansion and split-tunnel rules -> RouteTable; JSON-over-Unix-socket admin
IPC; server/client data paths wiring transport + tunnel (TUN run needs root).
config/{server,client}.toml.example. 15 tests (pki roundtrip, config parse,
admin-socket roundtrip, loopback connection). Verified the real binary: --help,
bench-crypto, and a full CA->server->client cert workflow.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
f78633e04f |
chore: scaffold Aura workspace skeleton (Stage 0)
- 6-crate Cargo workspace, dependency tree frozen (cargo check green in ~1m) - ml-kem 0.3 (FIPS 203) replaces spec's pqcrypto-kyber for ML-KEM-768 - fix invalid target-gated workspace.dependencies: Windows deps (wintun/windows) declared untargeted, cfg-gated per-crate in aura-tunnel - version bumps vs spec: tun 0.8, rcgen 0.14, wintun 0.5 - stub lib/main per crate; real implementations land wave by wave Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |