Files

195 lines
11 KiB
Markdown

# Architecture Overview
NexusGuard is a three-component SD-WAN system: a central API server, a web dashboard, and cross-platform device agents. All communication is encrypted. Tunnels are fileless. Access is zero-trust.
## High-Level Architecture
```
┌─────────────────────────────────────────────────────────────────────┐
│ Dashboard (Vue 3) │
│ Glassmorphism Web Interface │
│ Manages: Nodes, Devices, Rules │
└───────────────────────────────────┬─────────────────────────────────┘
│ HTTP (port 80)
┌─────────────────────────────────────────────────────────────────────┐
│ Nginx Reverse Proxy │
│ Routes: /api/ → :8080, / → SPA │
└───────────────────────────────────┬─────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ Server Core (Go/Gin) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ HTTP API │ │ gRPC │ │ IPAM │ │ nftables │ │
│ │ (20+ │ │ Signaling│ │ Manager │ │ Firewall │ │
│ │ handlers)│ │ (cmux) │ │ │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL Database │ │
│ │ (wg_servers, devices, rules, users) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ Redis │ │ WireGuard │ │
│ │ (Heartbeat TTL) │ │ (wg0 interface) │ │
│ └──────────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
│ │
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ Device Agent (Linux) │ │ Device Agent (Win/Mac) │
│ Systemd Daemon │ │ System Tray │
│ Memory-injected WG │ │ Memory-injected WG │
└───────────────────────────┘ └───────────────────────────┘
```
## Component Breakdown
### Server Core
The central API and VPN hub. Written in Go with Gin framework.
| Responsibility | Implementation |
|----------------|----------------|
| API endpoints | 20+ Gin handlers (`api/` directory) |
| gRPC signaling | Bidirectional streaming via cmux (port 8080) |
| IPAM | IP pool allocation from CIDR per node |
| Firewall | nftables rule management (add/remove per peer) |
| WireGuard | Interface control, peer sync, config push |
| Auth | JWT middleware, admin-only enforcement |
| Heartbeat | Config sync, handshake monitoring |
### Dashboard UI
Admin web interface. Built with Vue 3 and glassmorphism design system.
| Responsibility | Implementation |
|----------------|----------------|
| Node management | Register/edit WireGuard servers |
| Device management | CRUD, provisioning tokens, QR codes |
| Firewall rules | Per-peer nftables rule editor |
| Live telemetry | 10s polling for device health |
| Traffic history | Time-range filtering, export |
### Device Agent
Stealth VPN daemon. Cross-platform Go binary.
| Responsibility | Implementation |
|----------------|----------------|
| Provisioning | HTTP POST with AES-256-GCM encrypted response |
| Tunnel | Memory-injected WireGuard (no disk files) |
| Heartbeat | HTTP/gRPC, config sync, handshake monitoring |
| gRPC | Bidirectional stream for real-time commands |
| Self-healing | Exponential backoff reconnection |
## Data Flow
### Provisioning Flow
```
1. Admin creates device via Dashboard → API generates registration token
2. Agent sends token + HWID to POST /api/v1/provision
3. Server validates token, allocates IP from pool
4. Server responds with WireGuard config (AES-256-GCM encrypted)
5. Agent decrypts config, injects into WireGuard via IpcSet
6. Tunnel established — no files written to disk
```
### Heartbeat Flow
```
Every 30 seconds:
1. Agent reads last_handshake_time from WireGuard IPC
2. Agent POSTs {device_id, tunnel_up, last_handshake} to server
3. Server loads Device + WgServer fresh from DB (dynamic, not cached)
4. Server computes config_hash = SHA256(tunnelFields) + ":" + SHA256(forwards)
- Tunnel fields: server_pub, endpoint, internal_ip, private_key, preshared_key, allowed_ips, dns
- Forwards: sorted protocol:publicPort->targetIP:targetPort:ID
5. Server responds with full config + config_hash
6. Agent compares config_hash with previous → if different → rebuild tunnel/reload forwards
```
> **Design**: Peers (devices) store only their own data (keys, IP, settings). Node data (endpoint, public key) is loaded fresh from DB on every heartbeat. This ensures config always reflects the latest node state without requiring agent restart.
### Suspend/Resume Flow
```
Suspend:
1. Admin clicks "Suspend" in Dashboard
2. Dashboard POSTs /api/v1/devices/:id/suspend
3. Server updates DB (is_suspended = true)
4. Server sends gRPC SuspendCommand to agent
5. Server removes WireGuard peer from kernel
6. Agent receives command → stops tunnel
Resume:
1. Admin clicks "Resume" in Dashboard
2. Server updates DB (is_suspended = false)
3. Server re-adds WireGuard peer to kernel
4. Server sends gRPC ResumeCommand with full ConfigUpdate
5. Agent receives command → rebuilds tunnel
```
## Security Model
### Zero-Trust Principles
| Principle | Implementation |
|-----------|----------------|
| No public registration | `/auth/register` locked; admin via CLI only |
| Encrypted provisioning | AES-256-GCM for WireGuard config transfer |
| Fileless tunnels | WireGuard config in process memory only |
| Hardware binding | HWID (DMI/CPU serial) bound to registration token |
| Per-peer isolation | nftables rules per device, default deny |
| JWT authentication | All API endpoints require valid token |
### Trust Boundaries
```
┌─────────────────────────────────────────────────────────┐
│ Trusted Zone │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ Server │ │ Database │ │ WireGuard Interface │ │
│ │ Core │ │ (PG) │ │ (wg0) │ │
│ └──────────┘ └──────────┘ └──────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Encrypted Channel
(AES-256-GCM / WG)
┌─────────────────────────────────────────────────────────┐
│ Untrusted Zone │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Device Agent │ │
│ │ (Memory-only WireGuard config) │ │
│ └──────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
## Port Multiplexing
Server Core uses cmux to serve both HTTP and gRPC on port 8080:
```go
m := cmux.New(lis)
grpcLis := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings(
"content-type", "application/grpc",
))
httpLis := m.Match(cmux.Any())
```
- gRPC matched by `content-type: application/grpc` header
- HTTP matched by `Any()` (catch-all)
- Single port, single listener, zero extra config