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>
This commit is contained in:
xah30
2026-05-27 01:41:29 +03:00
parent 4d1bdba55d
commit 0a73d5298b
9 changed files with 1702 additions and 42 deletions
+25 -1
View File
@@ -18,13 +18,37 @@ cert = "~/.aura/server.crt"
key = "~/.aura/server.key"
[tunnel]
# Address pool for clients; v1 uses a single shared server-side TUN on this network.
# Address pool / TUN network. v2 reads the active pool config from [server.pool] below; this value
# is kept as the v1-compatible fallback (used when [server.pool] is omitted entirely) and as the
# network the server-side TUN brings up. The server's own TUN IP is the network's first usable host
# (e.g. 10.7.0.1 for 10.7.0.0/24).
pool_cidr = "10.7.0.0/24"
# TUN MTU (leave headroom under the path MTU for QUIC + Aura framing).
mtu = 1420
# DNS server advertised to clients (informational in v1).
dns = "10.7.0.1"
# v2 per-client IP pool. Each authenticated client gets its own address from `cidr`; the server's
# in-memory `client_ip -> connection` map demultiplexes TUN reads by destination IP. Omit the
# whole [server.pool] section to get the v1-compatible fallback: [tunnel] pool_cidr is reused as a
# dynamic-only pool with no static reservations.
[server.pool]
# Pool CIDR. Optional; defaults to [tunnel] pool_cidr when omitted. Must contain the server's own
# TUN address (the network's first host) and every entry in [server.pool.static].
cidr = "10.7.0.0/24"
# Allocation strategy:
# "static_only" — only ids listed in [server.pool.static] are admitted; unknowns refused.
# "dynamic_only" — static map is ignored; everyone gets the next free address.
# "static_or_dynamic" — static reservation wins; unknown ids get a dynamic address (default).
strategy = "static_or_dynamic"
# Optional `client_id -> ip` pinnings. The key is the verified Common Name from the client's
# certificate (see `aura pki issue-client --id <name>`); the value must lie inside `cidr` above and
# must not collide with the server's own address or another reservation.
[server.pool.static]
# "phone-1" = "10.7.0.20"
# "laptop-1" = "10.7.0.21"
[mimicry]
# Outer-TLS camouflage hostname the server presents/expects.
sni = "cdn.example.com"