Files

11 KiB

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:

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