P7 spec rev3: X25519-only browser keygen (no ECDSA fallback), unblock row + honest semantics everywhere, three-zone WG firewall model

This commit is contained in:
Hermes committed 2026-10-03 21:25:17 -07:00
1 parent 26f4aa8ad0
commit 6e25001738
2 files changed
+24 -9

No files matched your search

+17 -5
View File
@@ -19,6 +19,7 @@ Two network modes, one product:
| Control plane | api.tailscale.com (OAuth client preferred; API key fallback) | DashCaddy itself (host wg-quick + key store) |
| Invites | Tailscale user-invites API, link-first (no email required) | DashCaddy invite link + QR config |
| Block/remove | API device expire/delete + ACL deny | Remove peer from hub + firewall rule |
| Unblock | Re-allow at ACL level; expired device keys must re-authenticate (see §5) | Re-add peer from stored record (immediate) |
| Rules | Tailnet policy ACLs compiled by DashCaddy | Hub firewall (nftables set-based) compiled by DashCaddy |
| Outside dependency | Yes | None |
@@ -164,15 +165,26 @@ Builds on the existing DashCA pipeline (routes/ca.js, DC-076). Changes:
peer→peer traffic; peer→hub-resource traffic is local. No NAT/masquerade on
dcnet0 — all resource access is to hub-local services on 10.53.0.1 or to
other peers' /32s, so addresses stay routable and firewall rules match peers.
- Firewall baseline: dcnet0 input allows only WireGuard UDP (listen port),
ICMP from 10.53.0.0/16, and the per-resource ports from 10.53.0.0/16;
admin ports (API/SSH) on 10.53.0.1 are restricted to admin peers only.
- Firewall baseline — three distinct zones, never conflated:
(a) **External input**: the WireGuard UDP listen port arrives on the EXTERNAL
interface (e.g. eth0), not dcnet0 — its accept rule is scoped to the external
interface name (captured at setup).
(b) **dcnet0 local input** (iifname dcnet0): ICMP from 10.53.0.0/16, admin
ports (API/SSH on 10.53.0.1) from admin peers only, per-resource ports to
10.53.0.1; drop other new inbound to 10.53.0.1.
(c) **dcnet0 forwarding** (ip_forward=1): peer→resource gated by per-resource
sets; peer→peer default DROP (both iifname and oifname dcnet0 tails) unless a
grant implies it.
### 8.2 Key lifecycle (no server-side private-key storage)
- **Client keypairs are generated in the invitee's browser** at redemption time
(WebCrypto: X25519 where available, fallback ECDSA-P256; wireguard-tools
accepts any interface config — DashCaddy consumes the resulting public key).
using WebCrypto **X25519** — WireGuard requires Curve25519 key material; there
is NO fallback algorithm (a browser lacking X25519 support gets an explicit
"browser not supported" error, not a degraded key). Raw key serialization:
the browser exports the 32-byte raw key, base64-encoded (standard WireGuard
private-key format, `wg genkey`-compatible). The server receives the base64
public key (44 chars ending '=') and validates length/charset before use.
- The redemption page posts ONLY the public key to the server; the server
registers it as a WireGuard peer (10.53.x.y/32) and returns the client
config (Address, DNS, PublicKey of hub, AllowedIPs = 10.53.0.0/16).