Files
wgcloak/docs/ARCHITECTURE.md

78 lines
3.7 KiB
Markdown

# Architecture
wgcloak is a single Linux userspace process with a `client` or `server` role.
The core moves opaque datagrams between a local UDP socket and a transport
session. It does not know whether the payload is WireGuard, DNS, or another UDP
protocol.
```text
CLIENT SERVER
local UDP peer transport listener
│ │
▼ ▼
local listener ── tunnel core ── transport ── authenticated session
│
▼
dedicated connected UDP backend socket
│
▼
configured UDP backend
```
## Ownership boundaries
- The local listener receives datagrams and remembers the most recently active
local peer for return traffic. One active peer per v1 tunnel is sufficient.
- The core owns session lifecycle, limits, datagram-size checks, reconnect
policy, and statistics. Payload bytes remain opaque.
- A transport owns connection establishment and wire representation. Every
transport exposes the same logical send/receive/close behavior and a maximum
datagram size.
- Authentication is a separate concern. Direct UDP uses the documented
challenge/HMAC packet protocol; TLS-capable transports authenticate the
client after transport establishment.
- The server creates a backend UDP socket only after client authentication and
maps that socket to one session. A backend response therefore has natural
session ownership without inspecting the backend protocol.
## Transport lifecycle
The client state machine is:
```text
STARTING → RESOLVING → PROBING → AUTHENTICATING → CONNECTED
│ │
└───────────┘ failure
▼
RECONNECTING
│
└→ PROBING
```
In `auto` mode the configured order defaults to direct UDP, QUIC DATAGRAM,
HTTP/3 CONNECT-UDP, then TLS/TCP. Authentication rejection is a configuration
error, not permission to probe indefinitely. Network failures use bounded
exponential backoff with jitter (250 ms to 30 s), reset after a successful
connection. These transports are wired into the current runtime; the
acceptance checklist distinguishes implementation from completed v1 sign-off.
## Server isolation
One malformed or unauthenticated packet must be rejected without terminating
the listener or affecting another client. Server limits cover active sessions,
per-source sessions, pending handshakes, handshake duration, authentication
attempts, and maximum datagram size. Expiry closes the backend socket and
releases replay/session state.
## Privileges and filesystem
Normal operation uses ordinary UDP/TCP/Unix sockets and needs no root,
`CAP_NET_ADMIN`, or `CAP_SYS_ADMIN`. `CAP_NET_BIND_SERVICE` is optional when a
reviewed deployment must bind a port below 1024. The control socket is local
and protected by filesystem ownership/mode; it is not a network listener.
Configuration reload and certificate/key reload are not implemented. The
control `reload` command returns an explicit unsupported response. The
`reconnect` command applies to the client, while the server supports `status`,
`stats`, and graceful `shutdown`.