feat: complete nx9-wg v0.8.0 platform
This commit is contained in:
1 parent
c75e5c4e71
commit
c8a9b7cde6
52 files changed
+7751
-725
No files matched your search
@@ -0,0 +1,42 @@
|
||||
# NX9 WireGuard Documentation Index
|
||||
|
||||
Welcome to the official documentation for the **NX9 WireGuard (`nx9-wg`)** appliance and management platform.
|
||||
|
||||
---
|
||||
|
||||
## 1. Getting Started & Philosophy
|
||||
- [**NX9 Design Principles**](design-principles.md) — Architectural philosophy, self-hosted sovereignty, zero scripting runtime, and SQLite authority.
|
||||
- [**Installation & Deployment Guide**](installation.md) — Production installation, systemd service, admin bootstrap, first interface, and peer setup.
|
||||
- [**Linux Platform & Kernel Requirements**](linux_requirements.md) — Kernel 5.6+, in-tree WireGuard module, Netlink sockets, `libnftables.so.1`, and capabilities.
|
||||
|
||||
---
|
||||
|
||||
## 2. Architecture & Native Linux Execution
|
||||
- [**System Architecture & Workspace Structure**](architecture.md) — Six-crate workspace breakdown, layer boundaries, and end-to-end data flows.
|
||||
- [**Native WireGuard Netlink Engine**](native-wireguard.md) — Direct RTNETLINK and Generic Netlink (`wireguard`) protocol implementation.
|
||||
- [**Native Network & Routing Engine**](native-network.md) — RTNETLINK link/address/route lifecycle and direct procfs IP packet forwarding.
|
||||
- [**Native nftables Engine**](nftables.md) — In-process `libnftables.so.1` FFI transactions and dedicated `table inet nx9_wg` scoping.
|
||||
- [**Firewall & NAT Domain Model**](firewall_nat.md) — Typed rules, protocol groups, port ranges, priorities, and outbound NAT masquerading.
|
||||
|
||||
---
|
||||
|
||||
## 3. Control Plane, UI & Telemetry
|
||||
- [**Reconciliation Engine & Convergence**](reconciliation.md) — Closed-loop drift detection, read-only planning, serialized apply, and convergence lifecycle states.
|
||||
- [**Web User Interface (SPA)**](ui.md) — Zero-dependency embedded HTML5/CSS/JS frontend, theme engine, and all 15 application routes.
|
||||
- [**Axum REST API & WebSocket Protocol**](api.md) — Complete endpoint reference, JSON schemas, error handling, and real-time event broadcaster.
|
||||
- [**Native CLI Command Reference**](cli.md) — Full reference for all 17 CLI subcommands, multi-format output (`table`/`json`/`yaml`/`csv`), and secret files.
|
||||
|
||||
---
|
||||
|
||||
## 4. Security & Disaster Recovery
|
||||
- [**Security Model & Privilege Architecture**](security.md) — Single admin model (`CHECK (id=1)`), Argon2id hashing, SHA-256 tokens, permissions matrix, and brute-force protection.
|
||||
- [**Backup & Disaster Recovery Guide**](backup_restore.md) — Atomic online SQLite backups (`VACUUM INTO`), SHA-256 manifests, and pre-restore safety snapshots.
|
||||
|
||||
---
|
||||
|
||||
## 5. Operations, Development & Release
|
||||
- [**Release Engineering & Packaging**](release.md) — Standalone distribution packages (`.tar.gz`/`.tar.xz`), systemd sandboxing, installer, and rollback strategy.
|
||||
- [**Quality Assurance & Testing Strategy**](testing.md) — Multi-tiered test suites, SAFE mode (`LIVE=0`) vs real-kernel mode (`LIVE=1`), and automated security audits.
|
||||
- [**Developer & Contributing Guide**](development.md) — Building, testing, linting, and workspace contribution standards.
|
||||
- [**Configuration Reference**](configuration.md) — TOML configuration format and `NX9_WG_*` environment variable precedence.
|
||||
- [**Docker & Container Deployment**](docker.md) — Containerized deployment with Linux capability isolation and volume persistence.
|
||||
+130
-70
@@ -1,85 +1,145 @@
|
||||
# REST API and WebSocket Reference
|
||||
# Axum REST API & WebSocket Protocol Reference
|
||||
|
||||
All REST endpoints are nested under the `/api/v1` prefix.
|
||||
The `nx9-wg` API daemon serves JSON REST endpoints and a real-time WebSocket event bus under the base path `/api/v1`.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
## 1. Authentication & Session Model
|
||||
|
||||
The API supports two authentication mechanisms:
|
||||
1. **Session Cookie**: `nx9_session=<SESSION_UUID>` (HttpOnly, SameSite=Strict).
|
||||
2. **Bearer Token**: `Authorization: Bearer nx9_<TOKEN_BASE64>` (Hashed with SHA-256 on the server).
|
||||
Authentication is supported via two mechanisms:
|
||||
|
||||
### A. HTTP Session Cookie (`nx9_session`)
|
||||
Obtained via `POST /api/v1/auth/login`. Returned in the `Set-Cookie` response header and automatically attached by web browsers.
|
||||
|
||||
### B. Bearer API Token
|
||||
Passed in the `Authorization` header:
|
||||
```http
|
||||
Authorization: Bearer nx9_<uuid>_<random>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
## 2. Standard Error Response Model
|
||||
|
||||
### 1. Public Endpoints
|
||||
- `POST /api/v1/auth/login`: Authenticates administrator with username and password. Sets session cookie.
|
||||
- `GET /api/v1/system/health`: Service and database health check.
|
||||
- `GET /api/v1/system/version`: Version and build metadata.
|
||||
- `GET /api/v1/ws`: WebSocket real-time event stream.
|
||||
All non-2xx responses return a structured JSON error body:
|
||||
|
||||
### 2. Administrator & Session Management
|
||||
- `POST /api/v1/auth/logout`: Invalidates the current session.
|
||||
- `GET /api/v1/auth/session`: Returns information about the active session.
|
||||
- `POST /api/v1/auth/password`: Changes password and terminates all other sessions.
|
||||
- `GET /api/v1/auth/tokens`: Lists all provisioned API tokens.
|
||||
- `POST /api/v1/auth/tokens`: Creates a new API token.
|
||||
- `DELETE /api/v1/auth/tokens/{id}`: Revokes an API token.
|
||||
```json
|
||||
{
|
||||
"error": "Descriptive error message",
|
||||
"status": 404
|
||||
}
|
||||
```
|
||||
|
||||
### 3. WireGuard Interfaces
|
||||
- `GET /api/v1/interfaces`: Lists all interfaces.
|
||||
- `POST /api/v1/interfaces`: Creates an interface.
|
||||
- `GET /api/v1/interfaces/{id}`: Interface details.
|
||||
- `PUT /api/v1/interfaces/{id}`: Updates interface settings.
|
||||
- `DELETE /api/v1/interfaces/{id}`: Deletes interface.
|
||||
- `POST /api/v1/interfaces/{id}/enable`: Enables interface.
|
||||
- `POST /api/v1/interfaces/{id}/disable`: Disables interface.
|
||||
- `GET /api/v1/interfaces/{id}/status`: Live statistics, listen port, and connected peer metrics.
|
||||
|
||||
### 4. WireGuard Peers
|
||||
- `GET /api/v1/interfaces/{id}/peers`: Lists peers for a specific interface.
|
||||
- `POST /api/v1/interfaces/{id}/peers`: Enrolls a new peer.
|
||||
- `GET /api/v1/peers/{id}`: Peer details.
|
||||
- `PUT /api/v1/peers/{id}`: Updates peer configuration.
|
||||
- `DELETE /api/v1/peers/{id}`: Deletes peer.
|
||||
- `POST /api/v1/peers/{id}/enable`: Activates peer.
|
||||
- `POST /api/v1/peers/{id}/disable`: Disables peer.
|
||||
- `POST /api/v1/peers/{id}/revoke`: Revokes peer.
|
||||
- `GET /api/v1/peers/{id}/config`: Downloads standard client `.conf` file.
|
||||
- `GET /api/v1/peers/{id}/qr`: Returns SVG, PNG base64, and Data URL QR code representations.
|
||||
|
||||
### 5. Networks & Routing
|
||||
- `GET /api/v1/networks`, `POST /api/v1/networks`, `DELETE /api/v1/networks/{id}`
|
||||
- `GET /api/v1/routes`, `POST /api/v1/routes`, `DELETE /api/v1/routes/{id}`
|
||||
|
||||
### 6. Firewall & nftables
|
||||
- `GET /api/v1/firewall/rules`, `POST /api/v1/firewall/rules`, `DELETE /api/v1/firewall/rules/{id}`
|
||||
- `POST /api/v1/firewall/rules/{id}/enable`, `POST /api/v1/firewall/rules/{id}/disable`
|
||||
|
||||
### 7. Audit Log
|
||||
- `GET /api/v1/audit`: Paginated and filtered query of security and system events.
|
||||
|
||||
### 8. Backups
|
||||
- `GET /api/v1/backups`: Lists existing backup records.
|
||||
- `POST /api/v1/backups/create`: Creates a new snapshot and manifest.
|
||||
- `GET /api/v1/backups/{id}/download`: Downloads backup archive.
|
||||
- `POST /api/v1/backups/{id}/restore`: Safely restores database.
|
||||
- `DELETE /api/v1/backups/{id}`: Deletes backup archive and metadata.
|
||||
|
||||
### 9. Reconciliation
|
||||
- `GET /api/v1/reconcile/plan`: Returns detected drift without making changes.
|
||||
- `POST /api/v1/reconcile/apply`: Applies reconciliation plan to live kernel.
|
||||
### Common HTTP Status Codes:
|
||||
- `200 OK`: Request succeeded.
|
||||
- `400 Bad Request`: Validation failure on input parameters.
|
||||
- `401 Unauthorized`: Missing, invalid, or expired session/token.
|
||||
- `404 Not Found`: Resource ID does not exist in SQLite.
|
||||
- `409 Conflict`: Unique constraint violation (e.g. duplicate interface name or IP).
|
||||
- `422 Unprocessable Entity`: Semantic constraint failure.
|
||||
- `429 Too Many Requests`: Brute-force rate limiting triggered.
|
||||
- `500 Internal Server Error`: Native Linux execution plane or storage failure.
|
||||
|
||||
---
|
||||
|
||||
## WebSocket Telemetry (`/api/v1/ws`)
|
||||
## 3. REST API Endpoint Inventory
|
||||
|
||||
Upon connection, clients receive a stream of JSON `SystemEvent` frames:
|
||||
- `InterfaceChanged { id, action }`
|
||||
- `PeerChanged { id, action }`
|
||||
- `NetworkChanged { id, action }`
|
||||
- `RouteChanged { id, action }`
|
||||
- `FirewallChanged { id, action }`
|
||||
- `AuditEvent { event_type, message, resource_type, resource_id }`
|
||||
### Authentication & Tokens
|
||||
- `POST /api/v1/auth/login`: Authenticate with `{ "username": "admin", "password": "..." }`. Returns session cookie and user metadata.
|
||||
- `POST /api/v1/auth/logout`: Invalidate current active session.
|
||||
- `GET /api/v1/auth/session`: Query authenticated session info.
|
||||
- `POST /api/v1/auth/password`: Update administrator password `{ "current_password": "...", "new_password": "..." }`. Invalidates all active sessions.
|
||||
- `GET /api/v1/auth/tokens`: List all API token metadata.
|
||||
- `POST /api/v1/auth/tokens`: Generate API token `{ "name": "ci-token", "expires_in_days": 30 }`. Returns `{ "raw_token": "...", "meta": {...} }`.
|
||||
- `DELETE /api/v1/auth/tokens/{id}`: Revoke an API token.
|
||||
|
||||
### System & Health
|
||||
- `GET /api/v1/system/health`: Public system health check `{ "status": "healthy", "database": "connected" }`.
|
||||
- `GET /api/v1/system/version`: Public version and build information.
|
||||
- `GET /api/v1/system`: System operational overview and interface/peer counts.
|
||||
- `GET /api/v1/system/settings`: List all key-value settings.
|
||||
- `PUT /api/v1/system/settings`: Upsert setting `{ "key": "...", "value": "...", "description": "..." }`.
|
||||
|
||||
### WireGuard Interfaces
|
||||
- `GET /api/v1/interfaces`: List all WireGuard interfaces.
|
||||
- `POST /api/v1/interfaces`: Create interface `{ "name": "wg0", "address_v4": "10.100.0.1/24", "listen_port": 51820, "mtu": 1420 }`.
|
||||
- `GET /api/v1/interfaces/{id}`: Get interface details.
|
||||
- `PUT /api/v1/interfaces/{id}`: Update interface configuration.
|
||||
- `DELETE /api/v1/interfaces/{id}`: Delete interface (cascades to peers).
|
||||
- `POST /api/v1/interfaces/{id}/enable`: Set interface `IFF_UP`.
|
||||
- `POST /api/v1/interfaces/{id}/disable`: Set interface `IFF_DOWN`.
|
||||
- `GET /api/v1/interfaces/{id}/status`: Query live kernel netlink telemetry.
|
||||
|
||||
### Peers & Client Configs
|
||||
- `GET /api/v1/peers`: List all peers across all interfaces.
|
||||
- `GET /api/v1/interfaces/{id}/peers`: List peers for specific interface.
|
||||
- `POST /api/v1/interfaces/{id}/peers`: Enroll peer `{ "name": "alice", "profile": "full_tunnel", "mtu": 1280, ... }`.
|
||||
- `GET /api/v1/peers/{id}`: Get peer details.
|
||||
- `PUT /api/v1/peers/{id}`: Update peer parameters.
|
||||
- `DELETE /api/v1/peers/{id}`: Delete peer.
|
||||
- `POST /api/v1/peers/{id}/enable`: Enable peer.
|
||||
- `POST /api/v1/peers/{id}/disable`: Disable peer.
|
||||
- `GET /api/v1/peers/{id}/config`: Download WireGuard `.conf` file (supports `?device=...&connection=...`).
|
||||
- `GET /api/v1/peers/{id}/qr`: Generate QR code SVG/PNG (supports `?qr_format=svg`).
|
||||
|
||||
### Networks & Subnets
|
||||
- `GET /api/v1/networks`: List subnet networks.
|
||||
- `POST /api/v1/networks`: Create subnet `{ "name": "clients", "cidr": "10.100.1.0/24" }`.
|
||||
- `GET /api/v1/networks/{id}`: Get network details.
|
||||
- `DELETE /api/v1/networks/{id}`: Delete network.
|
||||
- `GET /api/v1/networks/{id}/available`: List unallocated IP addresses.
|
||||
|
||||
### Routing
|
||||
- `GET /api/v1/routes`: List routing table entries.
|
||||
- `POST /api/v1/routes`: Add route `{ "destination": "192.168.50.0/24", "gateway": "10.100.0.2", "metric": 100 }`.
|
||||
- `DELETE /api/v1/routes/{id}`: Delete route.
|
||||
|
||||
### Firewall & NAT
|
||||
- `GET /api/v1/firewall/rules`: List nftables rules.
|
||||
- `POST /api/v1/firewall/rules`: Create rule `{ "name": "allow-ssh", "protocol": "tcp", "port": "22", "action": "accept" }`.
|
||||
- `DELETE /api/v1/firewall/rules/{id}`: Delete rule.
|
||||
- `POST /api/v1/firewall/rules/{id}/enable`: Enable rule.
|
||||
- `POST /api/v1/firewall/rules/{id}/disable`: Disable rule.
|
||||
|
||||
### Reconciliation
|
||||
- `GET /api/v1/reconcile/plan`: Query read-only drift plan between SQLite and Linux kernel.
|
||||
- `POST /api/v1/reconcile/apply`: Execute native mutations and verify convergence.
|
||||
|
||||
### Diagnostics
|
||||
- `GET /api/v1/diagnostics/all`: Run automated checks across all 9 subsystems.
|
||||
- `GET /api/v1/diagnostics/{subsystem}`: Run checks for a single subsystem.
|
||||
|
||||
### Backups
|
||||
- `GET /api/v1/backups`: List backup snapshots.
|
||||
- `POST /api/v1/backups/create`: Trigger atomic online backup snapshot (`VACUUM INTO`).
|
||||
- `GET /api/v1/backups/{id}/download`: Download raw SQLite database backup file.
|
||||
- `POST /api/v1/backups/{id}/restore`: Restore database from snapshot.
|
||||
- `DELETE /api/v1/backups/{id}`: Delete backup record and snapshot file.
|
||||
|
||||
### Audit Trail
|
||||
- `GET /api/v1/audit`: List append-only security and operational audit records.
|
||||
|
||||
---
|
||||
|
||||
## 4. Real-Time WebSocket Protocol (`/api/v1/ws`)
|
||||
|
||||
Connect to `ws://<host>/api/v1/ws` (or `wss://`) to receive real-time JSON events:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "AuditEvent",
|
||||
"payload": {
|
||||
"event_type": "peer_created",
|
||||
"message": "Peer 'alice-phone' enrolled on interface wg0",
|
||||
"resource_type": "peer",
|
||||
"resource_id": "974755a9-74d9-4488-85c9-f057230ab8e2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Event Types:
|
||||
- `AuditEvent`: Security and state mutation events.
|
||||
- `InterfaceChanged`: Interface status toggle or link state change.
|
||||
- `PeerChanged`: Peer parameter update or state transition.
|
||||
- `PeerHandshake`: Real-time cryptographic handshake update.
|
||||
- `SettingsChanged`: Key-value configuration change.
|
||||
+100
-19
@@ -1,25 +1,106 @@
|
||||
# NX9 WireGuard Architecture Blueprint
|
||||
# NX9 WireGuard — System Architecture & Workspace Structure
|
||||
|
||||
## System Overview
|
||||
`nx9-wg` is structured as a modular six-crate Rust workspace designed for separation of concerns, strict failure domains, and testability.
|
||||
|
||||
`nx9-wg` is structured as a modular Rust workspace consisting of six specialized crates and a root binary.
|
||||
|
||||
| Crate | Responsibility | Dependencies |
|
||||
| :--- | :--- | :--- |
|
||||
| **`nx9-wg-core`** | Domain entities, cryptographic utilities (Argon2id, x25519, SHA-256), data validation, and configuration types. | `serde`, `argon2`, `x25519-dalek`, `sha2`, `ipnet`, `chrono`, `uuid` |
|
||||
| **`nx9-wg-db`** | Authoritative persistence layer using SQLite with WAL mode, automated migrations, and isolated repository modules. | `nx9-wg-core`, `sqlx` (sqlite) |
|
||||
| **`nx9-wireguard`**| WireGuard interface controller, client `.conf` configuration builder, live telemetry inspection, and pure Rust QR engine. | `nx9-wg-core`, `qrcode`, `image`, `base64` |
|
||||
| **`nx9-wg-network`** | Linux kernel IP forwarding, routing table synchronization, and atomic `inet nx9_wg` nftables ruleset generator. | `nx9-wg-core`, `ipnet` |
|
||||
| **`nx9-wg-api`** | Axum REST API, session and token authentication middleware, WebSocket live event broadcast, and Reconciliation Engine. | `nx9-wg-core`, `nx9-wg-db`, `nx9-wireguard`, `nx9-wg-network`, `axum`, `tower` |
|
||||
| **`nx9-wg-ui`** | Dioxus web client shell (client only, business logic isolated in backend). | `nx9-wg-core` |
|
||||
| **`nx9-wg`** | Primary application binary providing CLI operations and HTTP daemon server. | All workspace crates, `clap` |
|
||||
```
|
||||
nx9-wg (Workspace Root & Binary Executable)
|
||||
├── crates/nx9-wg-core (Domain models, validation, cryptography, config)
|
||||
├── crates/nx9-wg-db (SQLite store, migrations, repositories, WAL)
|
||||
├── crates/nx9-wireguard (WireGuard Netlink execution, config builder, QR engine)
|
||||
├── crates/nx9-wg-network (RTNETLINK networking, route management, nftables, procfs)
|
||||
├── crates/nx9-wg-api (Axum REST API, WebSockets, auth, reconciliation, allocator)
|
||||
└── crates/nx9-wg-ui (Design tokens, CSS engine, view models, SPA integration)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Architectural Invariants
|
||||
## 1. Crate Inventory & Layer Responsibilities
|
||||
|
||||
1. **Strict SQL Isolation**: All raw SQL queries and SQLite interactions are confined entirely to `crates/nx9-wg-db/`. No other crate or handler interacts with SQLite directly.
|
||||
2. **Zero Shelling Out**: WireGuard, routing, and packet filtering interact with kernel abstractions and netlink without executing `wg`, `wg-quick`, or `iptables` subprocesses.
|
||||
3. **Single Administrator Model**: The system maintains exactly one administrative identity with `CHECK (id = 1)`. No RBAC, multi-tenant, or organization complexity is introduced.
|
||||
4. **Secret Redaction**: Passwords, private keys, preshared keys, and API tokens are never logged, persisted in plaintext, or exposed in error messages. All secret wrapper types implement custom `Debug` redactions (`[REDACTED]`).
|
||||
5. **Deterministic Reconciliation**: Desired state in SQLite is the single source of truth. The reconciler computes drift and idempotently applies adjustments without touching unmanaged Linux resources.
|
||||
### `nx9-wg-core`
|
||||
- **Domain Entities**: Typed domain structures (`Interface`, `Peer`, `Network`, `Route`, `FirewallRule`, `Setting`, `Admin`, `Session`, `ApiToken`, `BackupMeta`, `AuditEvent`).
|
||||
- **Validation**: Strict RFC-compliant validators for CIDRs, IP addresses, MTU ranges, listen ports, interface names, peer names, and password strength.
|
||||
- **Cryptography**: Argon2id password hashing, SHA-256 token digest generation, X25519 keypair generation, and secure random string generation.
|
||||
- **Configuration**: Hierarchical TOML and `NX9_WG_*` environment variable configuration loader.
|
||||
|
||||
### `nx9-wg-db`
|
||||
- **Authoritative Persistence**: Migration-driven SQLite storage using `sqlx` in Write-Ahead Logging (WAL) mode.
|
||||
- **Single Admin Invariant**: SQL constraint `CHECK (id = 1)` enforcing single-administrator identity.
|
||||
- **Repositories**: Isolated data access layers for admin, auth, audit, backups, client profiles, interfaces, login attempts, networks, peers, routes, sessions, settings, and tokens.
|
||||
- **Transactional Consistency**: Foreign key cascades (`ON DELETE CASCADE`) between interfaces and peers.
|
||||
|
||||
### `nx9-wireguard`
|
||||
- **Native Netlink Engine**: `NativeLinuxWireGuardEngine` interacting with Linux RTNETLINK for link lifecycle and Generic Netlink family `wireguard` (`SET_DEVICE`, `GET_DEVICE`, `ReplacePeers`).
|
||||
- **Client Config Generation**: Pure Rust `.conf` generation supporting full-tunnel and split-tunnel topologies.
|
||||
- **QR Code Engine**: High-resolution SVG, PNG byte streams, and UTF-8 ASCII terminal QR code rendering.
|
||||
- **Simulation Engine**: `SimulatedWireGuardEngine` for non-Linux platform development and testing.
|
||||
|
||||
### `nx9-wg-network`
|
||||
- **Native Network Engine**: `NativeLinuxNetworkEngine` managing RTNETLINK interfaces, IPv4/IPv6 addresses, and route tables.
|
||||
- **nftables Netfilter Engine**: `NativeLinuxNftablesEngine` utilizing `libnftables.so.1` for transactional rule generation in `table inet nx9_wg`.
|
||||
- **Kernel IP Forwarding**: Direct `/proc/sys/net/ipv4/ip_forward` and `/proc/sys/net/ipv6/conf/all/forwarding` mutation.
|
||||
- **Simulation Engine**: `SimulatedNetworkEngine` for local platform testing.
|
||||
|
||||
### `nx9-wg-api`
|
||||
- **REST Router**: Axum HTTP handlers for auth, interfaces, peers, networks, routes, firewall, NAT, forwarding, settings, backups, diagnostics, and audit logs.
|
||||
- **WebSocket Event Bus**: Tokio broadcast channel broadcasting real-time system events (`AuditEvent`, `InterfaceChanged`, `PeerChanged`, `PeerHandshake`, `SettingsChanged`).
|
||||
- **Reconciliation Engine**: Mutex-serialized continuous drift detection and convergence controller.
|
||||
- **Deterministic IP Allocator**: Collision-resistant next-IP allocation engine for managed subnets.
|
||||
- **Backup & Restore Service**: Online SQLite atomic snapshot (`VACUUM INTO`) and verification engine.
|
||||
|
||||
### `nx9-wg-ui`
|
||||
- **Design Tokens**: Structured CSS variable tokens for Dark and Light themes.
|
||||
- **Stylesheet Generator**: In-process CSS compiler producing responsive layouts (`@media (max-width: 768px)`).
|
||||
- **View Models**: Strongly-typed Rust UI state representations for dashboards, diagnostics, client export modals, and peer management tables.
|
||||
|
||||
---
|
||||
|
||||
## 2. End-to-End Control and Execution Plane
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph ControlPlane["Control Plane (User & Administration)"]
|
||||
User["Administrator (Browser / CLI)"]
|
||||
SPA["Embedded SPA Web UI"]
|
||||
CLI["Native CLI (nx9-wg)"]
|
||||
API["Axum REST API / WebSockets"]
|
||||
DB[("Authoritative SQLite Database")]
|
||||
end
|
||||
|
||||
subgraph ReconciliationLayer["Reconciliation & Engine Layer"]
|
||||
Reconciler["Reconciliation Engine (Serialized Mutex)"]
|
||||
WGEngine["WireGuard Engine (Genl / RTNETLINK)"]
|
||||
NetEngine["Network Engine (RTNETLINK & procfs)"]
|
||||
NftEngine["Nftables Engine (libnftables Netfilter)"]
|
||||
end
|
||||
|
||||
subgraph LinuxKernel["Linux Kernel Execution Plane"]
|
||||
WGSocket["WireGuard Kernel Module (wireguard.ko)"]
|
||||
RTNL["Kernel RTNETLINK (Links, Addrs, Routes)"]
|
||||
Procfs["/proc/sys/net (IP Forwarding)"]
|
||||
Netfilter["Netfilter Subsystem (table inet nx9_wg)"]
|
||||
end
|
||||
|
||||
User -->|HTTPS / WSS| SPA
|
||||
User -->|CLI Invocations| CLI
|
||||
SPA -->|REST API Calls| API
|
||||
CLI -->|In-Process Service Calls| API
|
||||
API -->|Authoritative Mutations| DB
|
||||
DB -->|Desired State Snapshot| Reconciler
|
||||
Reconciler -->|Read Live Telemetry| WGEngine
|
||||
Reconciler -->|Read Live Routes/Forwarding| NetEngine
|
||||
Reconciler -->|Read Live Ruleset| NftEngine
|
||||
WGEngine -->|Generic Netlink Messages| WGSocket
|
||||
NetEngine -->|RTM_NEWLINK / NEWROUTE| RTNL
|
||||
NetEngine -->|Write 1/0| Procfs
|
||||
NftEngine -->|Atomic Netfilter Transactions| Netfilter
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Subsystem Invariants & Security Boundaries
|
||||
|
||||
1. **Subprocess Isolation**: Zero invocations of `std::process::Command` or shell scripts across the entire production codebase.
|
||||
2. **Persistence Authority**: SQLite remains the single authoritative source of truth. Kernel state is continuously reconciled to match database state.
|
||||
3. **Firewall Isolation**: All nftables operations are confined to `table inet nx9_wg`. Unmanaged host tables are untouched.
|
||||
4. **Route Safety**: Default gateway routes and host networking routes are protected against accidental deletion or flushing.
|
||||
5. **Secret Redaction**: Private keys, preshared keys, password hashes, and token hashes are masked in `Debug` formatters, CLI outputs, and API responses.
|
||||
+70
-91
@@ -1,49 +1,48 @@
|
||||
# Native CLI Command Reference (`nx9-wg`)
|
||||
|
||||
The `nx9-wg` binary provides 100% native CLI coverage for the entire NX9 WireGuard application stack.
|
||||
The CLI directly executes native Rust application services (`Store`, `WireGuardEngine`, `NetworkEngine`, `ReconciliationEngine`, `BackupService`, `AuthService`) without calling external subprocesses.
|
||||
The `nx9-wg` binary provides 100% native CLI coverage across all 17 application subcommands without spawning external subprocesses.
|
||||
|
||||
---
|
||||
|
||||
## Global Options
|
||||
## 1. Global Options
|
||||
|
||||
- `-c, --config <PATH>`: Path to configuration file (env: `NX9_WG_CONFIG`, default: `/etc/nx9-wg/config.toml`)
|
||||
- `-d, --data-dir <PATH>`: Path to data directory (env: `NX9_WG_DATA_DIR`, default: `/var/lib/nx9-wg`)
|
||||
- `--database <PATH>`: Explicit SQLite database path or URL (env: `NX9_WG_DATABASE`)
|
||||
- `--format <table|json|yaml|csv>`: Output formatting style (default: `table`)
|
||||
- `--json`: Output strictly in formatted JSON
|
||||
- `-q, --quiet`: Suppress status and conversational messages
|
||||
- `-v, --verbose`: Enable debug trace output
|
||||
- `--log-level <LEVEL>`: Log verbosity level (`trace`, `debug`, `info`, `warn`, `error`, env: `NX9_WG_LOG_LEVEL`)
|
||||
| Option | Environment Variable | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `-c, --config <PATH>` | `NX9_WG_CONFIG` | Path to configuration file (default: `/etc/nx9-wg/config.toml`) |
|
||||
| `-d, --data-dir <PATH>` | `NX9_WG_DATA_DIR` | Path to data directory (default: `/var/lib/nx9-wg`) |
|
||||
| `--database <PATH>` | `NX9_WG_DATABASE` | Specific SQLite database file path or URL |
|
||||
| `--format <FORMAT>` | N/A | Output format (`table`, `json`, `yaml`, `csv`, default: `table`) |
|
||||
| `--json` | N/A | Convenience flag for strict JSON output |
|
||||
| `-q, --quiet` | N/A | Suppress status and conversational messages |
|
||||
| `-v, --verbose` | N/A | Enable verbose trace logging |
|
||||
| `--log-level <LEVEL>` | `NX9_WG_LOG_LEVEL` | Log verbosity level (`trace`, `debug`, `info`, `warn`, `error`) |
|
||||
|
||||
---
|
||||
|
||||
## Command Groups
|
||||
## 2. Command Groups Reference
|
||||
|
||||
### 1. `version`
|
||||
Displays version, build metadata, target architecture, and feature capabilities.
|
||||
Displays version, build edition, architecture, OS platform, and security flags.
|
||||
```bash
|
||||
nx9-wg version
|
||||
nx9-wg version --format json
|
||||
```
|
||||
|
||||
### 2. `serve`
|
||||
Starts the Axum REST API, WebSocket event streamer, and background reconciliation daemon.
|
||||
Starts the Axum REST API daemon, WebSocket streamer, and background reconciliation scheduler.
|
||||
```bash
|
||||
nx9-wg serve
|
||||
|
||||
# To intentionally expose the management API on all interfaces:
|
||||
nx9-wg serve --bind 0.0.0.0:8080
|
||||
```
|
||||
|
||||
### 3. `init`
|
||||
Initializes the single administrator account across 7 supported bootstrap sources.
|
||||
Initializes the single administrator account across 7 bootstrap sources.
|
||||
```bash
|
||||
# Generated password:
|
||||
nx9-wg init --generate-password --write-password-file /root/admin-pw.txt
|
||||
# Generated secure password:
|
||||
nx9-wg init --generate-password --write-password-file /var/lib/nx9-wg/admin-password
|
||||
|
||||
# Password from standard input:
|
||||
echo "SecureSecret123!" | nx9-wg init --password-stdin
|
||||
# Password via stdin:
|
||||
echo "StrongPassword123!" | nx9-wg init --password-stdin
|
||||
|
||||
# Password from file:
|
||||
nx9-wg init --password-file /run/secrets/admin_pw
|
||||
@@ -51,103 +50,83 @@ nx9-wg init --password-file /run/secrets/admin_pw
|
||||
|
||||
### 4. `system`
|
||||
- `nx9-wg system status`: System database statistics and object counts.
|
||||
- `nx9-wg system health`: System and database connectivity health check.
|
||||
- `nx9-wg system health`: System and SQLite connectivity health check.
|
||||
- `nx9-wg system info`: System platform, architecture, and runtime paths.
|
||||
- `nx9-wg system settings list`: List all configuration key-value settings.
|
||||
- `nx9-wg system settings list`: List all key-value settings.
|
||||
- `nx9-wg system settings get <KEY>`: Query setting value.
|
||||
- `nx9-wg system settings set <KEY> <VALUE> [--secret]`: Save setting.
|
||||
- `nx9-wg system settings delete <KEY>`: Delete setting.
|
||||
|
||||
### 5. `admin`
|
||||
- `nx9-wg admin status`: View administrator profile and last login metrics.
|
||||
- `nx9-wg admin create`: Provision administrator if not already initialized.
|
||||
- `nx9-wg admin password --new-password <PW> | --stdin | --password-file <PATH> | --generate`: Update password and invalidate all sessions.
|
||||
- `nx9-wg admin sessions list`: List active sessions.
|
||||
- `nx9-wg admin sessions revoke <SESSION_ID>`: Invalidate specific session.
|
||||
- `nx9-wg admin sessions revoke-all`: Invalidate all active administrator sessions.
|
||||
- `nx9-wg admin tokens create --name <NAME> [--days <DAYS>] [--write-token-file <PATH>]`: Generate a long-lived API token. The recommended secure workflow writes the one-time plaintext token to a file with restrictive permissions; token hashes are redacted from normal CLI output.
|
||||
- `nx9-wg admin tokens list`: List all API token metadata.
|
||||
- `nx9-wg admin tokens revoke <TOKEN_ID>`: Revoke an API token.
|
||||
- `nx9-wg admin info`: Query administrator account metadata.
|
||||
- `nx9-wg admin password`: Change administrator password.
|
||||
- `nx9-wg admin token create <NAME> [--expires-in-days N] [--write-token-file PATH]`: Generate API token.
|
||||
- `nx9-wg admin token list`: List active API tokens.
|
||||
- `nx9-wg admin token revoke <TOKEN_ID>`: Revoke an API token.
|
||||
- `nx9-wg admin session list`: List active browser sessions.
|
||||
- `nx9-wg admin session revoke-all`: Invalidate all active sessions.
|
||||
|
||||
### 6. `interface`
|
||||
- `nx9-wg interface list`: List all WireGuard interfaces.
|
||||
- `nx9-wg interface show <NAME_OR_ID>`: Inspect interface details.
|
||||
- `nx9-wg interface create <NAME> --address-v4 <CIDR> [--port <PORT>] [--address-v6 <CIDR>] [--mtu <MTU>] [--dns <DNS>]`: Create an interface.
|
||||
- `nx9-wg interface update <NAME_OR_ID> [--port <PORT>] [--address-v4 <CIDR>] [--enabled <BOOL>]`: Update interface properties.
|
||||
- `nx9-wg interface enable <NAME_OR_ID>` / `disable <NAME_OR_ID>`: Toggle administrative state.
|
||||
- `nx9-wg interface delete <NAME_OR_ID>`: Delete interface and associated peers.
|
||||
- `nx9-wg interface status <NAME>`: Query live interface telemetry.
|
||||
- `nx9-wg interface reconcile <NAME>`: Reconcile interface state with the Linux kernel.
|
||||
- `nx9-wg interface create <NAME> --address-v4 <CIDR> [--port PORT] [--mtu MTU]`: Create interface.
|
||||
- `nx9-wg interface show <NAME_OR_ID>`: Show interface configuration.
|
||||
- `nx9-wg interface enable <NAME_OR_ID>`: Enable interface (`IFF_UP`).
|
||||
- `nx9-wg interface disable <NAME_OR_ID>`: Disable interface (`IFF_DOWN`).
|
||||
- `nx9-wg interface delete <NAME_OR_ID>`: Delete interface.
|
||||
|
||||
### 7. `peer`
|
||||
- `nx9-wg peer list [--interface <NAME_OR_ID>]`: List enrolled peers.
|
||||
- `nx9-wg peer show <PEER_ID>`: Inspect peer configuration and metadata.
|
||||
- `nx9-wg peer create --interface <NAME_OR_ID> --name <NAME> [--address-v4 <CIDR>] [--allowed-ips <CIDRS>] [--endpoint <IP:PORT>]`: Enroll peer.
|
||||
- `nx9-wg peer update <PEER_ID> [--name <NAME>] [--allowed-ips <CIDRS>] [--enabled <BOOL>]`: Update peer parameters.
|
||||
- `nx9-wg peer enable <PEER_ID>` / `disable <PEER_ID>` / `revoke <PEER_ID>`: Peer lifecycle transitions.
|
||||
- `nx9-wg peer delete <PEER_ID>`: Remove peer.
|
||||
- `nx9-wg peer status <PEER_ID>`: Live handshake, endpoint, and bandwidth telemetry.
|
||||
- `nx9-wg peer config <PEER_ID> [--output <PATH>]`: Generate standard client `.conf` file.
|
||||
- `nx9-wg peer qr <PEER_ID> [--qr-format <terminal|svg|png>]`: Generate enrollment QR code.
|
||||
- `nx9-wg peer list [--interface NAME]`: List enrolled peers.
|
||||
- `nx9-wg peer create --interface <IFACE> --name <NAME> [--profile PROFILE] [--mtu MTU]`: Enroll peer.
|
||||
- `nx9-wg peer show <PEER_ID>`: Show peer configuration.
|
||||
- `nx9-wg peer enable <PEER_ID>` / `disable <PEER_ID>`: Toggle peer state.
|
||||
- `nx9-wg peer delete <PEER_ID>`: Delete peer.
|
||||
- `nx9-wg peer config <PEER_ID> [--device DEV] [--connection CONN]`: Output `.conf` client file.
|
||||
- `nx9-wg peer qr <PEER_ID>`: Render ASCII QR code in terminal for mobile scanning.
|
||||
|
||||
### 8. `network`
|
||||
- `nx9-wg network list`: List defined subnet networks.
|
||||
- `nx9-wg network show <ID>`: Inspect network details.
|
||||
- `nx9-wg network create <NAME> <CIDR> [--description <TEXT>]`: Create subnet network.
|
||||
- `nx9-wg network update <ID> [--name <NAME>] [--cidr <CIDR>] [--enabled <BOOL>]`: Update network.
|
||||
- `nx9-wg network delete <ID>`: Delete subnet network.
|
||||
- `nx9-wg network list`: List subnet networks.
|
||||
- `nx9-wg network create <NAME> --cidr <CIDR>`: Create network.
|
||||
- `nx9-wg network delete <NAME_OR_ID>`: Delete network.
|
||||
|
||||
### 9. `route`
|
||||
- `nx9-wg route list`: List configured kernel routing rules.
|
||||
- `nx9-wg route show <ID>`: Inspect route rule.
|
||||
- `nx9-wg route add --destination <CIDR> [--gateway <IP>] [--interface-name <IFACE>] [--metric <METRIC>]`: Add route.
|
||||
- `nx9-wg route update <ID> [--destination <CIDR>] [--gateway <IP>] [--metric <METRIC>]`: Update route.
|
||||
- `nx9-wg route delete <ID>`: Delete route.
|
||||
- `nx9-wg route status`: Status of kernel routing table management.
|
||||
- `nx9-wg route sync`: Synchronize desired routes to Linux kernel routing table.
|
||||
- `nx9-wg route list`: List routing table entries.
|
||||
- `nx9-wg route add --destination <CIDR> [--gateway IP] [--interface-name IFACE] [--metric M]`: Add route.
|
||||
- `nx9-wg route delete <ROUTE_ID>`: Delete route.
|
||||
|
||||
### 10. `firewall`
|
||||
- `nx9-wg firewall list`: List nftables firewall rules.
|
||||
- `nx9-wg firewall show <ID>`: Inspect firewall rule.
|
||||
- `nx9-wg firewall add --name <NAME> [--direction <in|out|forward>] [--source <CIDR>] [--destination <CIDR>] [--protocol <tcp|udp|icmp|any>] [--port <PORT>] [--action <accept|drop|reject>] [--priority <INT>]`: Add rule.
|
||||
- `nx9-wg firewall update <ID> [--action <ACTION>] [--priority <INT>] [--enabled <BOOL>]`: Update rule.
|
||||
- `nx9-wg firewall delete <ID>` / `enable <ID>` / `disable <ID>`: Rule management.
|
||||
- `nx9-wg firewall status`: Inspect active nftables ruleset and table.
|
||||
- `nx9-wg firewall sync`: Synchronize firewall ruleset to nftables.
|
||||
- `nx9-wg firewall add --name <NAME> [--protocol PROTO] [--port PORT] [--action ACTION] [--priority P]`: Add rule.
|
||||
- `nx9-wg firewall enable <RULE_ID>` / `disable <RULE_ID>`: Toggle rule.
|
||||
- `nx9-wg firewall delete <RULE_ID>`: Delete rule.
|
||||
|
||||
### 11. `nat`
|
||||
- `nx9-wg nat status`: Inspect NAT masquerade status and managed subnets.
|
||||
- `nx9-wg nat enable` / `disable`: Toggle NAT masquerade setting.
|
||||
- `nx9-wg nat list`: List subnets configured for NAT masquerade.
|
||||
- `nx9-wg nat sync`: Synchronize NAT rules to nftables postrouting chain.
|
||||
- `nx9-wg nat status`: Query NAT masquerade state.
|
||||
- `nx9-wg nat enable` / `disable`: Toggle outbound NAT masquerading.
|
||||
|
||||
### 12. `forwarding`
|
||||
- `nx9-wg forwarding status`: Inspect IPv4 and IPv6 kernel packet forwarding state.
|
||||
- `nx9-wg forwarding enable` / `disable`: Enable or disable kernel packet forwarding.
|
||||
- `nx9-wg forwarding sync`: Synchronize sysctl forwarding parameters.
|
||||
- `nx9-wg forwarding status`: Query kernel `/proc/sys/net/ipv4/ip_forward` status.
|
||||
- `nx9-wg forwarding enable` / `disable`: Toggle kernel IP forwarding.
|
||||
|
||||
### 13. `reconcile`
|
||||
- `nx9-wg reconcile status`: Summary of detected drift across all subsystems.
|
||||
- `nx9-wg reconcile plan [--interface <NAME>]`: Dry-run drift analysis without state mutation.
|
||||
- `nx9-wg reconcile apply [--interface <NAME>]`: Reconcile SQLite desired state to Linux kernel.
|
||||
- `nx9-wg reconcile verify`: Assert zero drift exists between SQLite and kernel (returns exit code 1 if drift exists).
|
||||
- `nx9-wg reconcile plan`: Calculate read-only drift between SQLite and kernel.
|
||||
- `nx9-wg reconcile apply`: Apply mutations across all execution planes.
|
||||
- `nx9-wg reconcile verify`: Post-apply verification check.
|
||||
|
||||
### 14. `backup`
|
||||
- `nx9-wg backup create [--description <TEXT>]`: Generate consistent SQLite backup snapshot with SHA-256 manifest.
|
||||
- `nx9-wg backup list`: List all backup snapshots.
|
||||
- `nx9-wg backup show <ID>`: Inspect backup metadata and file size.
|
||||
- `nx9-wg backup verify --path <PATH>`: Verify integrity and checksum of backup archive.
|
||||
- `nx9-wg backup restore --path <PATH> --yes`: Safely restore database with pre-restore safety snapshot.
|
||||
- `nx9-wg backup delete <ID>`: Delete backup record and archive.
|
||||
- `nx9-wg backup list`: List backup snapshots.
|
||||
- `nx9-wg backup create [--description DESC]`: Generate atomic SQLite online backup (`VACUUM INTO`).
|
||||
- `nx9-wg backup verify <PATH>`: Verify SQLite 3 header and SHA-256 checksum.
|
||||
- `nx9-wg backup restore <PATH_OR_ID>`: Restore database with automatic safety snapshot.
|
||||
|
||||
### 15. `audit`
|
||||
- `nx9-wg audit list [--event-type <TYPE>] [--actor <ACTOR>] [--resource-type <RESOURCE>] [--limit <N>] [--offset <N>]`: Query security audit trail.
|
||||
- `nx9-wg audit show <ID>`: Inspect complete audit event details.
|
||||
- `nx9-wg audit list [--limit N] [--event-type TYPE]`: List append-only audit trail records.
|
||||
|
||||
### 16. `live`
|
||||
- `nx9-wg live interface list` / `show <NAME>`: Query active WireGuard interfaces from kernel.
|
||||
- `nx9-wg live peer list <IFACE>` / `show <KEY_OR_ID>`: Query active peers from kernel.
|
||||
- `nx9-wg live routes`: Query live kernel routing status.
|
||||
- `nx9-wg live firewall`: Query live nftables ruleset.
|
||||
- `nx9-wg live forwarding`: Query live kernel forwarding sysctls.
|
||||
- `nx9-wg live nat`: Query live NAT state.
|
||||
- `nx9-wg live interfaces`: Query active Linux kernel WireGuard interfaces.
|
||||
- `nx9-wg live peers <IFACE>`: Query live peers, transfer bytes, and handshakes.
|
||||
- `nx9-wg live routes`: Query live kernel routing table.
|
||||
- `nx9-wg live nftables`: Query active `table inet nx9_wg` ruleset.
|
||||
|
||||
### 17. `diagnostics`
|
||||
- `nx9-wg diagnostics inspect all`: Inspect health across all 9 subsystems.
|
||||
- `nx9-wg diagnostics inspect <SUBSYSTEM>`: Inspect specific subsystem (`system`, `network`, `wireguard`, `peer`, `routing`, `forwarding`, `firewall`, `nat`, `reconciliation`).
|
||||
@@ -0,0 +1,82 @@
|
||||
# NX9 WireGuard — Architectural & Design Principles
|
||||
|
||||
> **"Sovereign, self-hosted, Linux-native network infrastructure built from first principles."**
|
||||
|
||||
---
|
||||
|
||||
## 1. The NX9 Philosophy
|
||||
|
||||
`nx9-wg` was conceived as a clean, high-performance, single-binary WireGuard appliance and network management engine for sovereign infrastructure. It is built upon the following foundational principles:
|
||||
|
||||
### A. Self-Hosted First & Full Ownership
|
||||
Network infrastructure is a critical sovereignty boundary. Administrators must have complete, unencumbered ownership of their cryptographic keys, network routing policies, and configuration data. `nx9-wg` operates entirely locally without phone-home telemetry, cloud dependencies, or external licensing servers.
|
||||
|
||||
### B. Linux-Native Architecture
|
||||
Rather than treating the Linux kernel as an opaque black box accessed via shell utilities, `nx9-wg` communicates directly with kernel networking subsystems using native Netlink protocols (RTNETLINK and WireGuard Generic Netlink) and direct `/proc` interfaces.
|
||||
|
||||
### C. FOSS & No Vendor Lock-In
|
||||
`nx9-wg` is free and open-source software dual-licensed under `MIT OR Apache-2.0`. All database schemas, configuration formats, cryptographic profiles, and backup archives use open, standard specifications (SQLite, TOML, JSON, Base64).
|
||||
|
||||
### D. Zero Scripting Runtime Dependencies
|
||||
The entire application—from the HTTP/WebSocket API server and reactive SPA frontend to cryptographic key generation, QR rendering, database migrations, and kernel Netlink communication—is compiled into a single native Rust binary. There is zero runtime dependency on Node.js, npm, Electron, Python, or external shell scripts.
|
||||
|
||||
### E. CLI-First & Headless Operational Simplicity
|
||||
Every capability exposed by the Web UI or REST API is first available as a first-class native CLI command supporting human-readable tables as well as machine-readable JSON, YAML, and CSV formats.
|
||||
|
||||
---
|
||||
|
||||
## 2. Why Not an Imperative Shell Wrapper?
|
||||
|
||||
Many existing WireGuard management tools act merely as thin Web UI wrappers around command-line utilities like `wg`, `wg-quick`, `iptables`, and `ip`. This model introduces severe architectural limitations:
|
||||
|
||||
1. **Fragile Process Spawning**: Shelling out to external executables (`std::process::Command`) incurs substantial overhead, introduces quoting/injection risks, and parses fragile string outputs that break across operating system versions.
|
||||
2. **Lack of Authoritative State**: Relying on `/etc/wireguard/wg0.conf` text files makes atomic transactional updates, relational constraints, foreign keys, and audit logging difficult and error-prone.
|
||||
3. **Configuration Drift**: Imperative changes applied directly to the kernel or configuration files easily drift out of sync with what the web management interface displays.
|
||||
4. **Host Network Destruction**: Script-based firewall and routing flush commands (e.g., `iptables -F` or modifying default routing tables) often disrupt container engines (Docker, Podman), hypervisors (KVM, libvirt), or host networking.
|
||||
|
||||
---
|
||||
|
||||
## 3. Core Architectural Invariants
|
||||
|
||||
### 1. SQLite Desired-State Authority
|
||||
The SQLite database is the single authoritative source of truth for all intended configuration state (interfaces, peers, networks, routes, firewall rules, and NAT policies). The kernel execution plane is a cache that is brought into alignment through continuous, deterministic reconciliation.
|
||||
|
||||
### 2. Zero Subprocess Execution Guarantee
|
||||
Production Rust code in `nx9-wg` is strictly forbidden from invoking `std::process::Command` or `tokio::process`. All kernel mutations occur via in-process Netlink sockets or `libnftables` Netfilter bindings.
|
||||
|
||||
### 3. Strict Resource Ownership & Scoping
|
||||
- **Firewall Rules**: Confined strictly to `table inet nx9_wg`. External tables created by Docker, Kubernetes, or host firewalls are never modified or flushed.
|
||||
- **Routing**: `nx9-wg` manages only routes explicitly defined in its database or attached to its managed interfaces. Default gateway routes and unmanaged host routes are never altered.
|
||||
|
||||
### 4. Single Administrator Security Model
|
||||
`nx9-wg` avoids complex RBAC frameworks in favor of a strictly enforced single-administrator model locked by database constraints (`CHECK (id = 1)`). This eliminates privilege escalation, role confusion, and broken object-level authorization vulnerabilities.
|
||||
|
||||
### 5. Multi-Cycle Idempotent Reconciliation
|
||||
State reconciliation follows a deterministic, read-only plan phase followed by a serialized apply phase and post-apply verification. Repeated executions against an already converged system produce zero mutations (NOOP).
|
||||
|
||||
---
|
||||
|
||||
## 4. Architectural Summary
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ Single Administrator (Web UI / CLI) │
|
||||
└───────────────────────────┬────────────────────────────┘
|
||||
│
|
||||
┌───────────────────────────▼────────────────────────────┐
|
||||
│ Axum REST API & WebSockets │
|
||||
└───────────────────────────┬────────────────────────────┘
|
||||
│
|
||||
┌───────────────────────────▼────────────────────────────┐
|
||||
│ Authoritative SQLite Desired State (WAL) │
|
||||
└───────────────────────────┬────────────────────────────┘
|
||||
│ (Periodic / Triggered)
|
||||
┌───────────────────────────▼────────────────────────────┐
|
||||
│ Reconciliation Engine │
|
||||
└───────┬───────────────────┼───────────────────┬────────┘
|
||||
│ (RTNETLINK/Genl) │ (libnftables) │ (Procfs)
|
||||
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
|
||||
│ WireGuard Genl│ │ inet nx9_wg │ │ IP Forwarding │
|
||||
│ Kernel Socket │ │ Table Filter │ │ /proc/sys │
|
||||
└───────────────┘ └───────────────┘ └───────────────┘
|
||||
```
|
||||
+64
-34
@@ -1,52 +1,82 @@
|
||||
# Development and Contributing Guide
|
||||
# Developer Guide & Repository Reference
|
||||
|
||||
## Environment Setup
|
||||
|
||||
- **Rust Toolchain**: `rustc` and `cargo` 1.85+ (Edition 2024).
|
||||
- **SQLite3 development headers** (for `sqlx-sqlite`).
|
||||
This guide provides instructions for building, testing, linting, and contributing to the `nx9-wg` codebase.
|
||||
|
||||
---
|
||||
|
||||
## Workspace Structure
|
||||
## 1. Workspace Layout
|
||||
|
||||
```
|
||||
.
|
||||
├── Cargo.toml
|
||||
├── Cargo.lock
|
||||
├── config.example.toml
|
||||
├── nx9-wg.service
|
||||
├── Dockerfile
|
||||
├── src/
|
||||
│ └── main.rs
|
||||
├── crates/
|
||||
│ ├── nx9-core/ # Domain models, crypto, config, validation
|
||||
│ ├── nx9-db/ # SQLite schema, migrations, repositories
|
||||
│ ├── nx9-wireguard/ # WireGuard controller, .conf builder, QR engine
|
||||
│ ├── nx9-network/ # Forwarding, routing, nftables
|
||||
│ ├── nx9-api/ # Axum API, WebSocket, Reconciler, Backup
|
||||
│ └── nx9-ui/ # Dioxus UI shell
|
||||
└── docs/ # Documentation suite
|
||||
```
|
||||
The repository is organized as a Cargo workspace containing 6 crates and the root application binary:
|
||||
|
||||
- **`crates/nx9-wg-core`**: Common domain entities, RFC validators, cryptography, and configuration.
|
||||
- **`crates/nx9-wg-db`**: SQLite database persistence layer, migration SQL scripts, and repository implementations.
|
||||
- **`crates/nx9-wireguard`**: WireGuard Generic Netlink execution, RTNETLINK link management, config builder, and QR engine.
|
||||
- **`crates/nx9-wg-network`**: RTNETLINK route management, `libnftables.so.1` integration, and procfs forwarding.
|
||||
- **`crates/nx9-wg-api`**: Axum REST API router, WebSocket broadcaster, authentication middleware, and reconciliation engine.
|
||||
- **`crates/nx9-wg-ui`**: Design tokens, CSS stylesheet compiler, view models, and SPA asset integration.
|
||||
- **`src/main.rs`**: Root CLI command parser and daemon entry point.
|
||||
|
||||
---
|
||||
|
||||
## Running Quality Gates
|
||||
## 2. Prerequisites & Build Commands
|
||||
|
||||
Before submitting changes, all mandatory quality gates must pass:
|
||||
### Prerequisites
|
||||
- **Rust Toolchain**: 1.85+ (Edition 2024).
|
||||
- **C Compiler**: `gcc` or `clang` (for SQLite C amalgamation).
|
||||
- **Linux Libraries**: `libnftables-dev` (Debian/Ubuntu) or `nftables-devel` / `libnftables` (Fedora/Arch).
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
# 1. Format check
|
||||
# Debug build
|
||||
cargo build --workspace
|
||||
|
||||
# Release build
|
||||
cargo build --release
|
||||
|
||||
# Format check
|
||||
cargo fmt --all -- --check
|
||||
|
||||
# 2. Workspace check
|
||||
cargo check --workspace
|
||||
# Clippy linter
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
```
|
||||
|
||||
# 3. Unit and integration tests
|
||||
---
|
||||
|
||||
## 3. Test Execution & SAFE Mode (`LIVE=0`) vs Privileged Mode (`LIVE=1`)
|
||||
|
||||
To prevent accidental modifications to developer workstations, all integration and live kernel test scripts default to SAFE mode (`LIVE=0`):
|
||||
|
||||
```bash
|
||||
# 1. Run full workspace unit & integration tests
|
||||
cargo test --workspace
|
||||
|
||||
# 4. Strict clippy with warnings denied
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
# 2. Run Comprehensive CLI Verification Suite (210 checks)
|
||||
LIVE=0 bash scripts/test-cli-comprehensive.sh
|
||||
|
||||
# 5. Marker scan
|
||||
git grep -n -E 'TODO|FIXME|XXX|HACK|unimplemented!|todo!|panic!' src/ crates/
|
||||
# 3. Run Native Linux Integration Test Suite (20 checks)
|
||||
LIVE=0 bash scripts/test-native-integration.sh
|
||||
|
||||
# 4. Run Dedicated Live Kernel Test Suite (24 checks)
|
||||
LIVE=0 bash scripts/test-live-kernel.sh
|
||||
```
|
||||
|
||||
### Privileged Real-Kernel Testing (`LIVE=1`)
|
||||
> [!CAUTION]
|
||||
> `LIVE=1` tests must ONLY be executed on a dedicated disposable Linux virtual machine or container with `CAP_NET_ADMIN`. Never execute `LIVE=1` on a production host.
|
||||
|
||||
```bash
|
||||
# On a dedicated disposable VM as root:
|
||||
sudo LIVE=1 bash scripts/test-live-kernel.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Release Packaging
|
||||
|
||||
To build the self-contained release distribution archives:
|
||||
|
||||
```bash
|
||||
bash scripts/package-release.sh
|
||||
```
|
||||
|
||||
Outputs `.tar.gz`, `.tar.xz`, and `.sha256` files in `target/dist/`.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Firewall and NAT Domain Model Reference
|
||||
|
||||
This document describes the domain representations, rule structures, port specifications, and safety invariants for packet filtering and NAT in `nx9-wg`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Domain Entities
|
||||
|
||||
### A. Firewall Rule (`FirewallRule`)
|
||||
Represents an individual packet filtering rule in the database:
|
||||
|
||||
| Field | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | `Uuid` | Unique identifier (Primary Key) |
|
||||
| `name` | `String` | Human-readable identifier (e.g., `allow-dns-udp`) |
|
||||
| `direction` | `FirewallDirection` | `In`, `Out`, or `Forward` |
|
||||
| `protocol` | `FirewallProtocol` | `Tcp`, `Udp`, `TcpUdp`, `Icmp`, or `Any` |
|
||||
| `action` | `FirewallAction` | `Accept`, `Drop`, or `Reject` |
|
||||
| `source` | `Option<String>` | Source CIDR or IP (e.g., `10.100.0.0/24`) |
|
||||
| `destination` | `Option<String>` | Destination CIDR or IP |
|
||||
| `source_port` | `Option<u16>` | Specific source port |
|
||||
| `destination_port`| `Option<u16>` | Specific destination port |
|
||||
| `port_range` | `Option<String>` | Single port, list, or range (`53`, `80,443`, `8000-8100`) |
|
||||
| `interface_id` | `Option<Uuid>` | Optional interface association |
|
||||
| `peer_id` | `Option<Uuid>` | Optional cryptographic peer association |
|
||||
| `priority` | `i32` | Rule evaluation priority (lower numbers evaluate first) |
|
||||
| `enabled` | `bool` | Active state flag |
|
||||
|
||||
---
|
||||
|
||||
## 2. Port Specification Syntax
|
||||
|
||||
The `port_range` field supports three RFC-compliant formats:
|
||||
|
||||
1. **Single Port**: `80` $\rightarrow$ Evaluates as `dport 80`
|
||||
2. **Multi-Port Comma List**: `80,443,8080` $\rightarrow$ Evaluates as `dport { 80, 443, 8080 }`
|
||||
3. **Port Range**: `8000-8100` $\rightarrow$ Evaluates as `dport 8000-8100`
|
||||
|
||||
---
|
||||
|
||||
## 3. Protocol Grouping
|
||||
|
||||
- **`Tcp`**: Filters IPv4/IPv6 TCP packets.
|
||||
- **`Udp`**: Filters IPv4/IPv6 UDP packets.
|
||||
- **`TcpUdp`**: Translates to `{ tcp, udp }` protocol match in a single atomic rule.
|
||||
- **`Icmp`**: Translates to `icmp` (IPv4) or `icmpv6` (IPv6).
|
||||
- **`Any`**: Omits protocol match, applying action to all transport protocols.
|
||||
|
||||
---
|
||||
|
||||
## 4. NAT Masquerade Domain Configuration
|
||||
|
||||
NAT masquerading is governed by key-value appliance settings in SQLite:
|
||||
|
||||
- **`enable_nat`**: Boolean string (`"true"` / `"false"`). When enabled, all active managed WireGuard subnets are masqueraded outbound to the host WAN interface.
|
||||
- **Dynamic Subnet Calculation**: The reconciliation engine queries all enabled interfaces (`Interface.address_v4`) and generates dedicated masquerade rules for each unique subnet.
|
||||
|
||||
---
|
||||
|
||||
## 5. Domain Validation & Invariants
|
||||
|
||||
1. **Priority Uniqueness & Ordering**: Rules are sorted by `priority ASC, created_at ASC` ensuring determinism.
|
||||
2. **CIDR Validation**: Source and destination values must parse as valid IPv4 or IPv6 CIDRs.
|
||||
3. **Port Bounds**: Port numbers must fall within standard bounds (`1..=65535`). In ranges `A-B`, `A <= B` is strictly enforced.
|
||||
+176
-32
@@ -1,70 +1,214 @@
|
||||
# Installation and Deployment Guide
|
||||
# nx9-wg Production Installation & Deployment Guide
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Linux kernel 5.6+ (with native in-tree WireGuard module)
|
||||
- `nftables` packet filtering engine
|
||||
- Linux capabilities: `CAP_NET_ADMIN` and `CAP_NET_BIND_SERVICE`
|
||||
This guide provides the complete, authoritative reference for installing, configuring, securing, maintaining, upgrading, and uninstallation of the `nx9-wg` WireGuard Appliance Management Engine on Linux.
|
||||
|
||||
---
|
||||
|
||||
## 1. Native Binary Installation
|
||||
## Prerequisites & Runtime Environment
|
||||
|
||||
| Requirement | Specification | Details |
|
||||
| :--- | :--- | :--- |
|
||||
| **Operating System** | Linux (Kernel 5.6+) | Native in-tree WireGuard module support (`wireguard.ko`). |
|
||||
| **Architecture** | `x86_64` or `aarch64` | Native 64-bit Linux executable. |
|
||||
| **Packet Filtering** | `nftables` / `libnftables.so.1` | Native Netfilter execution plane for firewall and NAT masquerade. |
|
||||
| **Linux Capabilities** | `CAP_NET_ADMIN`, `CAP_NET_BIND_SERVICE` | Required for RTNETLINK, Generic Netlink, and low-port UDP binding. |
|
||||
| **Database** | SQLite 3 (Embedded) | Statically bundled in binary; zero external database server required. |
|
||||
| **Process Model** | Single Native Executable | Zero external subprocess invocations (no `wg`, `ip`, `nft`, `bash`, Python, or Node.js). |
|
||||
|
||||
---
|
||||
|
||||
## 1. Quick Installation via Release Archive
|
||||
|
||||
Download and extract the official release archive:
|
||||
|
||||
### Building from Source
|
||||
```bash
|
||||
git clone ssh://git@git.nx9.in:6645/thakares/nx9-wg.git
|
||||
cd nx9-wg
|
||||
cargo build --release --bin nx9-wg
|
||||
# 1. Download release archive (replace with current version/arch)
|
||||
tar -xzf nx9-wg-v0.8.0-linux-x86_64.tar.gz
|
||||
cd nx9-wg-v0.8.0-linux-x86_64
|
||||
|
||||
# Install binary
|
||||
# 2. Run the automated installer as root
|
||||
sudo bash install.sh
|
||||
```
|
||||
|
||||
The installer automatically:
|
||||
- Installs `/usr/local/bin/nx9-wg` (mode `0755`)
|
||||
- Creates `/etc/nx9-wg` (mode `0750`) and installs `/etc/nx9-wg/config.toml` (mode `0640`) if absent
|
||||
- Creates `/var/lib/nx9-wg` (mode `0700`) and `/var/lib/nx9-wg/backups` (mode `0700`)
|
||||
- Bootstraps the initial administrator with a secure random password (`/var/lib/nx9-wg/admin-initial-password`)
|
||||
- Installs `/etc/systemd/system/nx9-wg.service` (mode `0644`)
|
||||
- Enables and starts the `nx9-wg` service
|
||||
|
||||
---
|
||||
|
||||
## 2. Manual Step-by-Step Installation
|
||||
|
||||
If you prefer to perform each step manually:
|
||||
|
||||
### Step 2.1 — Install Binary
|
||||
```bash
|
||||
sudo install -m 0755 target/release/nx9-wg /usr/local/bin/nx9-wg
|
||||
```
|
||||
|
||||
### Initializing Directories and Configuration
|
||||
### Step 2.2 — Create Filesystem Layout & Set Strict Permissions
|
||||
```bash
|
||||
sudo mkdir -p /var/lib/nx9-wg /etc/nx9-wg /var/lib/nx9-wg/backups
|
||||
sudo cp config.example.toml /etc/nx9-wg/config.toml
|
||||
sudo install -d -m 0750 /etc/nx9-wg
|
||||
sudo install -d -m 0700 /var/lib/nx9-wg
|
||||
sudo install -d -m 0700 /var/lib/nx9-wg/backups
|
||||
sudo install -d -m 0750 /var/log/nx9-wg
|
||||
```
|
||||
|
||||
### Bootstrapping the Administrator Account
|
||||
### Step 2.3 — Install Configuration File
|
||||
```bash
|
||||
sudo nx9-wg --config /etc/nx9-wg/config.toml --data-dir /var/lib/nx9-wg init --generate-password --write-password-file /var/lib/nx9-wg/admin-password
|
||||
if [ ! -f /etc/nx9-wg/config.toml ]; then
|
||||
sudo install -m 0640 config.example.toml /etc/nx9-wg/config.toml
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
### Step 2.4 — Bootstrap Initial Administrator Account
|
||||
Generate a cryptographically secure 24-character random password written to a restricted file:
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg \
|
||||
--config /etc/nx9-wg/config.toml \
|
||||
--data-dir /var/lib/nx9-wg \
|
||||
init --generate-password --write-password-file /var/lib/nx9-wg/admin-password
|
||||
|
||||
## 2. Systemd Service Deployment
|
||||
sudo chmod 0600 /var/lib/nx9-wg/admin-password
|
||||
```
|
||||
|
||||
### Step 2.5 — Deploy & Start systemd Service
|
||||
```bash
|
||||
# Copy systemd unit file
|
||||
sudo cp nx9-wg.service /etc/systemd/system/nx9-wg.service
|
||||
|
||||
# Reload systemd and enable service
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now nx9-wg
|
||||
|
||||
# Check service status and logs
|
||||
sudo systemctl status nx9-wg
|
||||
sudo journalctl -u nx9-wg -f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Upgrading nx9-wg
|
||||
## 3. Verification & First Operational Workflow
|
||||
|
||||
### Step 3.1 — Check Service Status
|
||||
```bash
|
||||
sudo systemctl status nx9-wg
|
||||
```
|
||||
|
||||
### Step 3.2 — Check Operational Health via CLI
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg system health
|
||||
sudo /usr/local/bin/nx9-wg diagnostics inspect all
|
||||
```
|
||||
|
||||
### Step 3.3 — Log in via Web User Interface
|
||||
Open your browser at `http://<server-ip>:8080/` and log in with:
|
||||
- **Username**: `admin`
|
||||
- **Password**: Found in `/var/lib/nx9-wg/admin-password`
|
||||
|
||||
### Step 3.4 — Create First WireGuard Interface (wg0)
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg interface create \
|
||||
--address-v4 10.100.0.1/24 \
|
||||
--port 51820 \
|
||||
--mtu 1420 \
|
||||
wg0
|
||||
```
|
||||
|
||||
### Step 3.5 — Enroll Client Peer
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg peer create \
|
||||
--interface wg0 \
|
||||
--name alice-mobile \
|
||||
--profile full_tunnel \
|
||||
--mtu 1280
|
||||
```
|
||||
|
||||
### Step 3.6 — Apply Reconciliation
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg reconcile apply
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Production Backup & Recovery
|
||||
|
||||
### Mandatory Pre-Upgrade Backup
|
||||
Always create an authoritative database backup before applying system updates or binary upgrades:
|
||||
```bash
|
||||
sudo /usr/local/bin/nx9-wg backup create --description "Pre-upgrade snapshot"
|
||||
sudo /usr/local/bin/nx9-wg backup list
|
||||
```
|
||||
|
||||
### Restoring from Backup
|
||||
```bash
|
||||
# 1. Stop active service
|
||||
sudo systemctl stop nx9-wg
|
||||
|
||||
# 2. Restore database from backup snapshot
|
||||
sudo /usr/local/bin/nx9-wg backup restore <BACKUP_ID>
|
||||
|
||||
# 3. Restart service & reconcile state
|
||||
sudo systemctl start nx9-wg
|
||||
sudo /usr/local/bin/nx9-wg reconcile apply
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Upgrading nx9-wg
|
||||
|
||||
The `nx9-wg` persistence model utilizes SQLite with automatic schema migrations executed upon startup.
|
||||
|
||||
```bash
|
||||
# 1. Stop service
|
||||
sudo systemctl stop nx9-wg
|
||||
|
||||
# 2. Create backup
|
||||
sudo /usr/local/bin/nx9-wg backup create --description "Pre-upgrade backup"
|
||||
|
||||
# 3. Install new binary
|
||||
sudo install -m 0755 nx9-wg-new /usr/local/bin/nx9-wg
|
||||
|
||||
# 4. Restart service (automatic migration)
|
||||
sudo systemctl start nx9-wg
|
||||
|
||||
# 5. Verify convergence
|
||||
sudo /usr/local/bin/nx9-wg reconcile plan
|
||||
sudo /usr/local/bin/nx9-wg system health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Rollback Procedure
|
||||
|
||||
If a new binary fails or encounters incompatibility:
|
||||
|
||||
1. Stop the active service:
|
||||
```bash
|
||||
sudo systemctl stop nx9-wg
|
||||
```
|
||||
2. Create a safety backup:
|
||||
2. Re-install the previous working binary:
|
||||
```bash
|
||||
sudo nx9-wg --config /etc/nx9-wg/config.toml --data-dir /var/lib/nx9-wg backup create --description "Pre-upgrade backup"
|
||||
sudo install -m 0755 nx9-wg-previous /usr/local/bin/nx9-wg
|
||||
```
|
||||
3. Install new binary:
|
||||
3. Restore the pre-upgrade database backup if schema changes occurred:
|
||||
```bash
|
||||
sudo install -m 0755 target/release/nx9-wg /usr/local/bin/nx9-wg
|
||||
sudo /usr/local/bin/nx9-wg backup restore <PRE_UPGRADE_BACKUP_ID>
|
||||
```
|
||||
4. Restart service (database schema migrations run automatically at startup):
|
||||
4. Start service and verify:
|
||||
```bash
|
||||
sudo systemctl start nx9-wg
|
||||
sudo /usr/local/bin/nx9-wg system health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Safe Uninstallation
|
||||
|
||||
### Standard Uninstallation (Preserves Database & Configuration)
|
||||
```bash
|
||||
sudo bash uninstall.sh
|
||||
```
|
||||
*Stops and disables the service, removes `/usr/local/bin/nx9-wg` and the systemd unit file, while preserving `/etc/nx9-wg` and `/var/lib/nx9-wg`.*
|
||||
|
||||
### Total Purge (Destructive)
|
||||
```bash
|
||||
sudo bash uninstall.sh --purge
|
||||
```
|
||||
*Requires explicit interactive confirmation before permanently deleting all database files, backups, logs, and configuration.*
|
||||
+28
-15
@@ -1,34 +1,47 @@
|
||||
# Linux Platform and Kernel Requirements
|
||||
|
||||
`nx9-wg` is built for modern Linux systems and relies directly on kernel networking features.
|
||||
`nx9-wg` is designed for native Linux execution and interacts directly with Linux kernel subsystems via Netlink sockets and direct `/proc` filesystem interfaces.
|
||||
|
||||
---
|
||||
|
||||
## 1. Kernel Requirements
|
||||
|
||||
- **Linux Kernel Version**: 5.6 or newer (WireGuard module is included in mainline kernel 5.6+).
|
||||
- **Kernel Module**: `wireguard.ko` (`modprobe wireguard`).
|
||||
- **Sysctl IP Forwarding**:
|
||||
- `/proc/sys/net/ipv4/ip_forward` (must be `1` for VPN client internet routing).
|
||||
- `/proc/sys/net/ipv6/conf/all/forwarding` (optional, for IPv6 dual-stack).
|
||||
- **Linux Kernel Version**: 5.6 or newer (in-tree WireGuard module support).
|
||||
- **WireGuard Subsystem**: `wireguard.ko` in-tree module (`modprobe wireguard`).
|
||||
- **Generic Netlink (Genl)**: Family `wireguard` for cryptographic interface and peer configuration.
|
||||
- **RTNETLINK**: For network interface lifecycle (RTM_NEWLINK/DELLINK), address assignments (RTM_NEWADDR), and routing table management (RTM_NEWROUTE/DELROUTE).
|
||||
- **Sysctl IP Forwarding**: Direct procfs mutation:
|
||||
- `/proc/sys/net/ipv4/ip_forward` (enabled for IPv4 packet routing)
|
||||
- `/proc/sys/net/ipv6/conf/all/forwarding` (enabled for IPv6 dual-stack routing)
|
||||
|
||||
---
|
||||
|
||||
## 2. Firewall and Packet Filtering
|
||||
## 2. Dynamic Library & Runtime Dependencies
|
||||
|
||||
- **`nftables`**: `nx9-wg` requires `nftables` in the kernel.
|
||||
- **Isolated Table**: All rules are scoped inside `table inet nx9_wg`. `nx9-wg` does not alter or flush tables created by Docker, Kubernetes, or other firewall utilities.
|
||||
When compiled for Linux, `nx9-wg` links dynamically against standard system libraries:
|
||||
|
||||
| Library | Runtime Function | Installation Package (Debian/Ubuntu) | Installation Package (RHEL/Fedora/Arch) |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `libnftables.so.1` | Native nftables ruleset execution | `libnftables1` / `nftables` | `libnftables` / `nftables` |
|
||||
| `libmnl.so.0` | Minimal Netlink library | `libmnl0` | `libmnl` |
|
||||
| `libnftnl.so.11` | Netfilter Netlink object library | `libnftnl11` | `libnftnl` |
|
||||
| `libc.so.6` | Standard C library (glibc / musl) | Base system | Base system |
|
||||
|
||||
> [!NOTE]
|
||||
> SQLite is statically embedded into the `nx9-wg` binary via `libsqlite3-sys`. No external SQLite installation or database daemon is required.
|
||||
|
||||
---
|
||||
|
||||
## 3. Capability Requirements
|
||||
## 3. Security Capabilities & Privilege Boundaries
|
||||
|
||||
When running without full root privileges, the process requires:
|
||||
- `CAP_NET_ADMIN`: For configuring network links, routes, and packet filter tables.
|
||||
- `CAP_NET_BIND_SERVICE`: If binding to low UDP ports (< 1024).
|
||||
When executed under systemd or non-root service accounts:
|
||||
- `CAP_NET_ADMIN`: Strictly required for RTNETLINK interface lifecycle, IP route mutations, WireGuard Genl socket communication, and nftables Netfilter execution.
|
||||
- `CAP_NET_BIND_SERVICE`: Required if binding the REST API or WireGuard UDP socket to privileged ports (< 1024).
|
||||
|
||||
---
|
||||
|
||||
## 4. Unsupported Environments
|
||||
## 4. Execution Mode Classification
|
||||
|
||||
- macOS and Windows do not support the Linux in-tree WireGuard kernel module. For local testing on non-Linux platforms, `nx9-wg` automatically engages the built-in `SimulatedWireGuardEngine` and `SimulatedNetworkEngine`.
|
||||
- **Linux Native Mode**: Automatically engaged on Linux systems with `CAP_NET_ADMIN` and kernel WireGuard/Netfilter modules.
|
||||
- **Non-Linux / Simulated Mode**: Automatically engaged on macOS and Windows hosts for development and UI preview.
|
||||
- **Restricted Mode**: Engaged when running on Linux without `CAP_NET_ADMIN`; control-plane REST API, SQLite queries, and diagnostics operate normally, while kernel mutation calls return descriptive permission errors without crashing.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Native Linux Network Engine (`NativeLinuxNetworkEngine`)
|
||||
|
||||
The `NativeLinuxNetworkEngine` provides Linux network interface inspection, IPv4/IPv6 address assignment, kernel routing table synchronization, and IP packet forwarding controls.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture & Netlink Communication
|
||||
|
||||
All network operations are executed in-process using RTNETLINK (`NETLINK_ROUTE` family) and direct `/proc/sys` procfs file writes:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ NativeLinuxNetworkEngine │
|
||||
└───────────────┬────────────────────────┬───────────────┘
|
||||
│ │
|
||||
Link, Address & Route Management │ Kernel IP Forwarding Controls
|
||||
via RTNETLINK (NETLINK_ROUTE) │ via direct /proc/sys writes
|
||||
│ │
|
||||
┌───────────────▼────────────────────────▼───────────────┐
|
||||
│ Linux Kernel Networking │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Capabilities & Operations
|
||||
|
||||
### A. Interface & Address Management
|
||||
- **`list_interfaces()`**: Enumerates all host network interfaces, resolving interface index (`ifindex`), MAC address, operational flags (`IFF_UP`, `IFF_RUNNING`, `IFF_POINTOPOINT`), and interface type.
|
||||
- **`set_interface_state(name, up)`**: Modifies interface operational state flags (`IFF_UP`).
|
||||
- **`add_address(name, cidr)` / `delete_address(name, cidr)`**: Sends `RTM_NEWADDR` / `RTM_DELADDR` Netlink messages to attach IPv4 or IPv6 subnets to interfaces.
|
||||
|
||||
### B. Kernel Routing Table Synchronization
|
||||
- **`list_routes()`**: Queries active kernel routes (`RTM_GETROUTE`), decoding destination prefixes, gateway addresses, interface names, route metrics, and route protocols.
|
||||
- **`add_route(route)`**: Installs a routing entry via `RTM_NEWROUTE` with scope `RT_SCOPE_UNIVERSE` or `RT_SCOPE_LINK`, target interface index (`RTA_OIF`), and route metric (`RTA_PRIORITY`).
|
||||
- **`delete_route(route)`**: Removes a managed route via `RTM_DELROUTE`.
|
||||
- **`has_route_drift(desired_routes)`**: Compares SQLite desired routes against active kernel routes using exact subnet, gateway, interface, and metric equality.
|
||||
|
||||
### C. Direct Procfs IP Forwarding
|
||||
Rather than executing `sysctl -w net.ipv4.ip_forward=1`, the engine directly inspects and updates procfs files:
|
||||
- **IPv4**: `/proc/sys/net/ipv4/ip_forward`
|
||||
- **IPv6**: `/proc/sys/net/ipv6/conf/all/forwarding`
|
||||
|
||||
---
|
||||
|
||||
## 3. Strict Resource Ownership Invariants
|
||||
|
||||
To guarantee safety on multi-tenant hosts running Docker, Kubernetes, Podman, or libvirt, `nx9-wg` enforces strict non-interference rules:
|
||||
|
||||
1. **No Routing Table Flushes**: `nx9-wg` NEVER executes `ip route flush` or flushes kernel routing tables.
|
||||
2. **Default Route Protection**: The default gateway (`0.0.0.0/0` via WAN gateway) is NEVER modified, deleted, or overridden.
|
||||
3. **Unmanaged Route Protection**: Routes belonging to external interfaces (e.g., `eth0`, `docker0`, `cni0`, `virbr0`) are completely ignored during route reconciliation.
|
||||
4. **Scope-Confined Deletion**: Only routes explicitly created by `nx9-wg` or assigned to `nx9-wg` interfaces are candidates for removal during drift reconciliation.
|
||||
|
||||
---
|
||||
|
||||
## 4. Route Equality & Reconciliation Logic
|
||||
|
||||
Two routes are evaluated as equal if and only if all of the following match:
|
||||
- **Destination CIDR**: Prefix and netmask (e.g., `192.168.50.0/24`).
|
||||
- **Gateway**: Optional next-hop IP address.
|
||||
- **Interface**: Egress device name (e.g., `wg0`).
|
||||
- **Metric**: Route priority integer.
|
||||
|
||||
```rust
|
||||
// Deterministic route equality check
|
||||
if desired_route.destination == live_route.destination
|
||||
&& desired_route.gateway == live_route.gateway
|
||||
&& desired_route.interface_name == live_route.interface_name
|
||||
&& desired_route.metric == live_route.metric
|
||||
{
|
||||
// Route is converged (In Sync)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Non-Linux Platform Fallback
|
||||
|
||||
On macOS and Windows workstations, `nx9-wg` automatically engages `SimulatedNetworkEngine` to enable local application development without requiring Linux-specific Netlink sockets.
|
||||
@@ -0,0 +1,88 @@
|
||||
# Native Linux WireGuard Engine (`NativeLinuxWireGuardEngine`)
|
||||
|
||||
The `NativeLinuxWireGuardEngine` provides direct, in-process communication with the Linux kernel WireGuard subsystem via Linux Netlink sockets.
|
||||
|
||||
---
|
||||
|
||||
## 1. Protocol Architecture: RTNETLINK & Generic Netlink
|
||||
|
||||
Unlike traditional WireGuard management tools that spawn external CLI processes (`wg`, `wg-quick`), `nx9-wg` uses native kernel sockets:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ NativeLinuxWireGuardEngine │
|
||||
└───────────────┬────────────────────────┬───────────────┘
|
||||
│ │
|
||||
Link Lifecycle (Create / Up / Down) │ Cryptographic Config & Telemetry
|
||||
via RTNETLINK (AF_NETLINK, NETLINK_ROUTE)│ via Generic Netlink (family "wireguard")
|
||||
│ │
|
||||
┌───────────────▼────────────────────────▼───────────────┐
|
||||
│ Linux Kernel (wireguard.ko) │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### A. RTNETLINK Link Lifecycle
|
||||
- **Interface Creation**: Sends `RTM_NEWLINK` with link type `wireguard`.
|
||||
- **Interface Deletion**: Sends `RTM_DELLINK` by interface index or name.
|
||||
- **Interface State**: Toggles `IFF_UP` and `IFF_DOWN` flags without invoking `ip link set up/down`.
|
||||
- **MTU Assignment**: Configures interface MTU directly in the `RTM_NEWLINK` netlink attributes.
|
||||
|
||||
### B. WireGuard Generic Netlink Protocol
|
||||
- Resolves the dynamic Generic Netlink family ID for `"wireguard"`.
|
||||
- **`WG_CMD_SET_DEVICE`**: Atomically configures the interface private key, UDP listen port, and peer list.
|
||||
- **`WG_CMD_GET_DEVICE`**: Queries live kernel device state, active listen port, public key, peer public keys, endpoints, allowed IPs, last handshake timestamps, and transfer byte counters.
|
||||
- **`WGDEVICE_F_REPLACE_PEERS`**: When syncing peers, setting this flag instructs the kernel to atomically replace all existing peers with the supplied desired set, removing stale peers in a single transaction.
|
||||
|
||||
---
|
||||
|
||||
## 2. Peer Cryptographic Synchronization
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Engine as NativeLinuxWireGuardEngine
|
||||
participant Genl as Generic Netlink Socket
|
||||
participant Kernel as Linux Kernel (wireguard.ko)
|
||||
|
||||
Engine->>Genl: Send WG_CMD_SET_DEVICE (Interface wg0, ReplacePeers=true)
|
||||
Note over Engine,Genl: Encodes ListenPort, PrivateKey, Peer Array
|
||||
Genl->>Kernel: Transmit Netlink Message
|
||||
Kernel->>Kernel: Validate Keys, Bind UDP Port, Apply Peers
|
||||
Kernel-->>Genl: NLMSG_ERROR (error=0 / Success)
|
||||
Genl-->>Engine: Ok(())
|
||||
|
||||
Engine->>Genl: Send WG_CMD_GET_DEVICE (Interface wg0)
|
||||
Genl->>Kernel: Query Live State
|
||||
Kernel-->>Genl: Return Device Attributes & Peer Telemetry
|
||||
Genl-->>Engine: Live Telemetry (Handshakes, Bytes Tx/Rx)
|
||||
```
|
||||
|
||||
### Cryptographic Attribute Encoding:
|
||||
- **Keys**: 32-byte binary Curve25519 keys (`WGPEER_A_PUBLIC_KEY`, `WGPEER_A_PRESHARED_KEY`).
|
||||
- **Allowed IPs**: Nested attributes (`WGALLOWEDIP_A_FAMILY`, `WGALLOWEDIP_A_IPADDR`, `WGALLOWEDIP_A_CIDR_MASK`).
|
||||
- **Endpoint**: `sockaddr_in` (IPv4) or `sockaddr_in6` (IPv6) socket address structures.
|
||||
- **Persistent Keepalive**: Interval in seconds (`WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Telemetry & Handshake Monitoring
|
||||
|
||||
The engine queries live kernel transfer statistics without writing temporary files:
|
||||
- **`last_handshake_at`**: Calculated from `WGPEER_A_LAST_HANDSHAKE_TIME` (seconds and nanoseconds since UNIX epoch).
|
||||
- **`rx_bytes` / `tx_bytes`**: 64-bit byte counters (`WGPEER_A_RX_BYTES`, `WGPEER_A_TX_BYTES`).
|
||||
- **`endpoint`**: Actual remote socket address learned dynamically by the kernel through authenticated roaming.
|
||||
|
||||
---
|
||||
|
||||
## 4. Security & Memory Safety Invariants
|
||||
|
||||
1. **Zero Subprocesses**: No calls to `wg`, `wg-quick`, or `ip`.
|
||||
2. **Secret Redaction**: Private keys and preshared keys implement custom `std::fmt::Debug` formatters emitting `[REDACTED]`.
|
||||
3. **Memory Scrubbing**: Sensitive cryptographic buffers are wrapped in types that zeroize memory upon drop.
|
||||
4. **Linux Capability Boundary**: Requires `CAP_NET_ADMIN` to open Netlink route and generic sockets.
|
||||
|
||||
---
|
||||
|
||||
## 5. Non-Linux Platform Fallback
|
||||
|
||||
On non-Linux platforms (macOS, Windows), `nx9-wg` automatically switches to `SimulatedWireGuardEngine`. This allows frontend UI and CLI development on local workstations while preserving the exact same `WireGuardEngine` trait interface.
|
||||
@@ -0,0 +1,91 @@
|
||||
# Native Linux nftables Engine (`NativeLinuxNftablesEngine`)
|
||||
|
||||
The `NativeLinuxNftablesEngine` manages Linux firewall filtering and Network Address Translation (NAT) via direct in-process interaction with `libnftables.so.1` and the Linux Netfilter Netlink subsystem.
|
||||
|
||||
---
|
||||
|
||||
## 1. Protocol Architecture & In-Process Netfilter Binding
|
||||
|
||||
`nx9-wg` uses `libnftables` in-process C-ABI FFI via `NftContext` to execute atomic transaction batches without spawning the `nft` or `iptables` CLI utilities:
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ NativeLinuxNftablesEngine │
|
||||
└───────────────────────────┬────────────────────────────┘
|
||||
│
|
||||
In-Process FFI Transactions
|
||||
via libnftables (NftContext)
|
||||
│
|
||||
┌───────────────────────────▼────────────────────────────┐
|
||||
│ Netfilter Subsystem (table inet nx9_wg) │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Table Scoping & Multi-Tenant Host Isolation
|
||||
|
||||
To prevent breaking container networks, hypervisors, or external security tools, `nx9-wg` enforces strict table isolation:
|
||||
|
||||
### A. Dedicated Table Namespace: `table inet nx9_wg`
|
||||
All chains, sets, rules, and NAT masquerade policies are strictly contained inside `table inet nx9_wg`.
|
||||
|
||||
### B. Zero Table Interference
|
||||
- **No Global Flushes**: `nx9-wg` NEVER executes `flush ruleset` or alters tables belonging to Docker (`table ip docker`), Kubernetes (`table inet cni`), libvirt (`table ip libvirt`), fail2ban, or UFW/Firewalld.
|
||||
- **Ownership Verification**: Before modifying or inspecting rules, `nx9-wg` validates table family (`inet`) and name (`nx9_wg`). Any foreign table is rejected and untouched.
|
||||
|
||||
---
|
||||
|
||||
## 3. Ruleset Architecture & Chains
|
||||
|
||||
The generated `inet nx9_wg` table contains three dedicated chains:
|
||||
|
||||
```
|
||||
table inet nx9_wg {
|
||||
chain input {
|
||||
type filter hook input priority filter; policy accept;
|
||||
# Custom peer filter rules (e.g. UDP/TCP port restrictions)
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy accept;
|
||||
# Inter-client routing and subnet forward policies
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat; policy accept;
|
||||
# Outbound NAT masquerade scoped strictly to managed WireGuard subnets
|
||||
ip saddr { 10.100.0.0/24 } oifname != "wg0" masquerade
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Scoped NAT Masquerade Invariant
|
||||
|
||||
Outbound NAT masquerading is dynamically scoped exclusively to managed WireGuard client subnets:
|
||||
1. **Subnet Deduplication**: Overlapping subnets are merged to prevent redundant rules.
|
||||
2. **Interface Exclusion**: Traffic routing back into the WireGuard interface (`oifname != "wg0"`) is not masqueraded to preserve true source IPs for site-to-site tunnels.
|
||||
3. **No Catch-All Masquerade**: `nx9-wg` never creates a catch-all `masquerade` rule that affects non-WireGuard traffic on the host.
|
||||
|
||||
---
|
||||
|
||||
## 5. Atomic Rule Compilation & Verification
|
||||
|
||||
The ruleset builder (`NftablesRulesetBuilder`) compiles desired database state into a single atomic Netfilter transaction buffer:
|
||||
1. **Deterministic Rule Ordering**: Rules are sorted by priority index (ascending) to guarantee consistent packet evaluation.
|
||||
2. **Protocol Grouping**: Supports `tcp`, `udp`, `tcp_udp`, `icmp`, and `any`.
|
||||
3. **Port & Port-Range Parsing**: Supports single ports (`53`), comma-separated lists (`80,443`), and contiguous ranges (`8000-8100`).
|
||||
4. **Validation via `nft_ctx_buffer_output`**: The compiled batch is verified by `libnftables` before committing to the kernel.
|
||||
|
||||
---
|
||||
|
||||
## 6. Runtime Dependency Qualification
|
||||
|
||||
On Linux systems, `nx9-wg` dynamically links against:
|
||||
- `libnftables.so.1` (provided by `libnftables1` / `nftables` package)
|
||||
- `libmnl.so.0`
|
||||
- `libnftnl.so.11`
|
||||
|
||||
No runtime dependency on the `nft` CLI binary or shell scripts exists.
|
||||
@@ -0,0 +1,107 @@
|
||||
# Reconciliation Engine & State Convergence Architecture
|
||||
|
||||
The `ReconciliationEngine` is the core architectural subsystem of `nx9-wg`. It implements a continuous, deterministic control loop ensuring the live Linux kernel state matches the authoritative desired state stored in SQLite.
|
||||
|
||||
---
|
||||
|
||||
## 1. The Closed-Loop Reconciliation Cycle
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph SOT["1. Authoritative Source of Truth"]
|
||||
DB[("SQLite Database\n(Desired State)")]
|
||||
end
|
||||
|
||||
subgraph Drift["2. Drift Detection & Planning"]
|
||||
Live["Query Live Kernel State\n(WireGuard Genl, RTNL, Netfilter, procfs)"]
|
||||
Plan["Reconciliation Engine: plan()\n(Read-Only Deterministic Diff)"]
|
||||
end
|
||||
|
||||
subgraph Mutation["3. Serialized Apply & Convergence"]
|
||||
Lock["Acquire Async Reconcile Mutex Lock"]
|
||||
Apply["Execute Native Mutations\n(WireGuard SET_DEVICE, RTNL routes, nftables)"]
|
||||
Verify["Post-Apply Verification Diff"]
|
||||
end
|
||||
|
||||
subgraph Outcome["4. Convergence Lifecycle State"]
|
||||
Converged["Converged (In Sync)\nhas_drift = false"]
|
||||
PartialFail["Partial Failure / Drift Remains\n(Descriptive Error & Safe State)"]
|
||||
end
|
||||
|
||||
DB --> Plan
|
||||
Live --> Plan
|
||||
Plan -->|Drift Detected| Lock
|
||||
Lock --> Apply
|
||||
Apply --> Verify
|
||||
Verify -->|Zero Differences| Converged
|
||||
Verify -->|Errors Encountered| PartialFail
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Six Convergence Lifecycle States
|
||||
|
||||
Every reconciliation execution produces a structured `ReconciliationReport` modeling one of six Phase 6 states:
|
||||
|
||||
| Lifecycle State | Description | Action Required |
|
||||
| :--- | :--- | :--- |
|
||||
| **`Plan`** | Read-only calculation of drift between SQLite and kernel. | None (Dry run) |
|
||||
| **`Applying`** | Native mutations actively dispatching across execution planes. | In progress |
|
||||
| **`Verifying`** | Post-apply live query verifying kernel reflects desired state. | In progress |
|
||||
| **`Converged`** | All desired resources verified present in kernel with zero drift. | None (Healthy) |
|
||||
| **`PartialFailure`** | One or more execution planes failed during apply (e.g. EPERM). | Inspect diagnostic remediation hints |
|
||||
| **`DriftRemains`** | Apply completed without crash, but verification detected remaining drift. | Re-evaluate desired configuration |
|
||||
|
||||
---
|
||||
|
||||
## 3. Subsystem Drift Detection Matrix
|
||||
|
||||
The `plan()` method calculates exact drift across 5 independent subsystems:
|
||||
|
||||
```rust
|
||||
pub struct ReconciliationPlan {
|
||||
pub has_drift: bool,
|
||||
pub interface_changes: usize,
|
||||
pub peer_changes: usize,
|
||||
pub route_changes: usize,
|
||||
pub firewall_changes: usize,
|
||||
pub forwarding_change: bool,
|
||||
pub actions: Vec<PlannedAction>,
|
||||
}
|
||||
```
|
||||
|
||||
### A. WireGuard Interfaces
|
||||
- Checks if desired interfaces (`Interface`) exist in kernel links via RTNETLINK.
|
||||
- Detects missing interfaces, wrong MTU, or down status.
|
||||
|
||||
### B. Cryptographic Peers
|
||||
- Queries live WireGuard device via `WG_CMD_GET_DEVICE`.
|
||||
- Detects missing peers, changed public keys, altered allowed IPs, or mismatched persistent keepalive intervals.
|
||||
|
||||
### C. Kernel Routes
|
||||
- Queries active kernel routes via `RTM_GETROUTE`.
|
||||
- Evaluates exact equality on destination CIDR, gateway IP, interface name, and route metric.
|
||||
|
||||
### D. nftables Firewall & NAT
|
||||
- Compares desired rules in SQLite against live rules in `table inet nx9_wg`.
|
||||
- Detects missing rules, priority shifts, or altered NAT masquerade subnet policies.
|
||||
|
||||
### E. IP Forwarding
|
||||
- Inspects `/proc/sys/net/ipv4/ip_forward` and `/proc/sys/net/ipv6/conf/all/forwarding`.
|
||||
- Flags drift if forwarding is disabled when VPN routing is configured.
|
||||
|
||||
---
|
||||
|
||||
## 4. Mutex Serialization & Concurrency Safety
|
||||
|
||||
Reconciliation mutations are protected by an asynchronous Mutex:
|
||||
- **Zero Race Conditions**: CLI commands (`nx9-wg reconcile apply`), Web UI actions (`POST /api/v1/reconcile/apply`), and background periodic cron jobs cannot execute concurrent kernel mutations.
|
||||
- **Read-Only Plan Concurrency**: Multiple callers can query `reconcile plan` simultaneously without blocking, as `plan()` performs read-only queries.
|
||||
|
||||
---
|
||||
|
||||
## 5. Restart Recovery & Multi-Cycle Idempotency
|
||||
|
||||
1. **Clean Cold-Start Recovery**: When `nx9-wg` starts or restarts, the background daemon queries the kernel, detects unapplied state from SQLite, and applies all interfaces, peers, routes, and firewall rules in one unified cycle.
|
||||
2. **Idempotent Convergence**: Running `reconcile apply` multiple times in succession produces zero mutations (NOOP) once convergence is achieved.
|
||||
3. **Telemetry Protection**: Live kernel telemetry (transfer bytes, handshake timestamps) is ingested into memory/events and NEVER overwrites authoritative desired configuration in SQLite.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Release Engineering & Packaging Reference
|
||||
|
||||
This document describes the release packaging, artifact verification, filesystem layout, systemd service hardening, and distribution model for `nx9-wg`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Release Packaging Pipeline
|
||||
|
||||
Release archives are generated using [`scripts/package-release.sh`](file:///home/sunil/Programs/nx9-wg/scripts/package-release.sh):
|
||||
|
||||
```bash
|
||||
bash scripts/package-release.sh
|
||||
```
|
||||
|
||||
### Packaging Outputs in `target/dist/`:
|
||||
- `nx9-wg-v0.8.0-linux-x86_64.tar.gz` (Standard gzip archive)
|
||||
- `nx9-wg-v0.8.0-linux-x86_64.tar.xz` (High-compression XZ archive)
|
||||
- `nx9-wg-v0.8.0-linux-x86_64.sha256` (Cryptographic SHA-256 checksums)
|
||||
|
||||
---
|
||||
|
||||
## 2. Release Archive Contents
|
||||
|
||||
Every release archive contains everything required for a standalone, offline production deployment:
|
||||
|
||||
```
|
||||
nx9-wg-v0.8.0-linux-x86_64/
|
||||
├── nx9-wg (Native executable binary, mode 0755)
|
||||
├── nx9-wg.service (Hardened systemd unit file, mode 0644)
|
||||
├── config.example.toml (Production configuration template, mode 0644)
|
||||
├── install.sh (Automated production installer, mode 0755)
|
||||
├── uninstall.sh (Safe uninstallation script, mode 0755)
|
||||
├── README.md (Primary project guide)
|
||||
├── LICENSE-MIT (MIT License text)
|
||||
├── LICENSE-APACHE (Apache 2.0 License text)
|
||||
└── docs/ (Complete offline documentation suite)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Standalone Verification Invariant
|
||||
|
||||
Release packages must function completely independently of the source repository. When extracted into an isolated clean directory (`/tmp/nx9-release-verify...`):
|
||||
- `nx9-wg version` outputs valid version, architecture, and platform strings.
|
||||
- `nx9-wg --help` lists all available subcommands.
|
||||
- `nx9-wg init` bootstraps the isolated SQLite database with WAL journals.
|
||||
- `nx9-wg system health` verifies database integrity.
|
||||
|
||||
---
|
||||
|
||||
## 4. Production Filesystem Layout
|
||||
|
||||
```
|
||||
/usr/local/bin/nx9-wg (0755 root:root - Binary)
|
||||
/etc/nx9-wg/ (0750 root:root - Configuration Directory)
|
||||
├── config.toml (0640 root:root - Main Configuration File)
|
||||
└── nx9-wg.env (0600 root:root - Optional Environment Secrets)
|
||||
/var/lib/nx9-wg/ (0700 root:root - State & Database Directory)
|
||||
├── nx9-wg.db (0600 root:root - Authoritative SQLite Database)
|
||||
├── nx9-wg.db-wal (0600 root:root - Write-Ahead Log Journal)
|
||||
├── admin-password (0600 root:root - Generated Initial Password)
|
||||
└── backups/ (0700 root:root - Database Backup Archives)
|
||||
/var/log/nx9-wg/ (0750 root:root - Operational Logs)
|
||||
/etc/systemd/system/
|
||||
└── nx9-wg.service (0644 root:root - Systemd Service Unit)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Systemd Security Sandboxing
|
||||
|
||||
The production service unit (`nx9-wg.service`) enforces modern Linux security directives:
|
||||
|
||||
- **Capabilities**: `CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE` & `AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE`.
|
||||
- **Filesystem**: `ProtectSystem=strict`, `ProtectHome=true`, `PrivateTmp=true`.
|
||||
- **System Isolation**: `ProtectControlGroups=true`, `RestrictSUIDSGID=true`, `LockPersonality=true`.
|
||||
- **Socket Domains**: `RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK`.
|
||||
- **Directory Lifecycle**: `StateDirectory=nx9-wg`, `ConfigurationDirectory=nx9-wg`, `LogsDirectory=nx9-wg`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Upgrade and Rollback Sequence
|
||||
|
||||
### Mandatory Upgrade Flow
|
||||
1. **Pre-Upgrade Backup**: `nx9-wg backup create --description "Pre-upgrade checkpoint"`
|
||||
2. **Stop Service**: `sudo systemctl stop nx9-wg`
|
||||
3. **Install Binary**: `sudo install -m 0755 nx9-wg /usr/local/bin/nx9-wg`
|
||||
4. **Start Service**: `sudo systemctl start nx9-wg` (Schema migrations run automatically upon startup)
|
||||
5. **Verify State**: `nx9-wg reconcile plan` & `nx9-wg system health`
|
||||
|
||||
### Rollback Flow
|
||||
1. **Stop Service**: `sudo systemctl stop nx9-wg`
|
||||
2. **Revert Binary**: `sudo install -m 0755 nx9-wg-old /usr/local/bin/nx9-wg`
|
||||
3. **Restore Database**: `nx9-wg backup restore <BACKUP_ID>`
|
||||
4. **Start Service**: `sudo systemctl start nx9-wg`
|
||||
+50
-22
@@ -1,43 +1,71 @@
|
||||
# Security Model and Best Practices
|
||||
# Security Model, Privilege Architecture & Best Practices
|
||||
|
||||
`nx9-wg` implements a strict, self-hosted, fail-closed security architecture.
|
||||
`nx9-wg` is designed with a strict, defense-in-depth, fail-closed security architecture tailored for self-hosted sovereign network infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## 1. Single Administrator Identity
|
||||
## 1. Single Administrator Identity Model
|
||||
|
||||
- **Fixed Database Identity**: The administrative record in SQLite is locked with `CHECK (id = 1)`.
|
||||
- **No RBAC or Multi-Tenancy**: Eliminates attack surface from privilege escalation, permission bypasses, or broken object-level authorization.
|
||||
- **Argon2id Password Hashing**: State-of-the-art memory-hard password derivation (`argon2id`). Plaintext passwords are never stored in memory longer than verification duration and never written to disk or logs.
|
||||
- **Database-Level Constraint**: The administrative record in SQLite is locked with `CHECK (id = 1)`.
|
||||
- **Zero Multi-Tenancy / RBAC Attack Surface**: Eliminates privilege escalation, role confusion, and broken object-level authorization vulnerabilities.
|
||||
- **Argon2id Password Hashing**: State-of-the-art memory-hard password derivation (`argon2id`). Passwords are never stored in plaintext, never logged, and never included in error responses.
|
||||
- **One-Time Credential Delivery**: Generated passwords and raw API tokens are displayed exactly once upon creation (or written to explicit 0600-permission files) and cannot be recovered from the database.
|
||||
|
||||
---
|
||||
|
||||
## 2. Token and Session Security
|
||||
## 2. API Token and Session Architecture
|
||||
|
||||
- **Hashed API Tokens**: API tokens use the `nx9_<base64>` format. Only the SHA-256 cryptographic digest of the token is persisted in SQLite. Compromise of the database does not reveal plaintext API tokens.
|
||||
- **Global Session Invalidation**: When the administrator changes their password, all active sessions across all devices are immediately invalidated in SQLite.
|
||||
- **HttpOnly Cookies**: Session tokens sent to browsers use `HttpOnly`, `SameSite=Strict`, and `Secure` (when TLS is active).
|
||||
- **Cryptographically Hashed Tokens**: API tokens follow the format `nx9_<uuid>_<random>`. Only the SHA-256 digest of the token (`token_hash`) is stored in SQLite. Database exfiltration will not compromise raw API tokens.
|
||||
- **Global Session Invalidation**: Changing the administrator password automatically invalidates all active browser sessions across all devices.
|
||||
- **Secure Cookie Flags**: Session cookies use `HttpOnly`, `SameSite=Strict`, and `Path=/`.
|
||||
- **Brute-Force Rate Limiting**: Exponential backoff and IP-based rate limiting (5 failed attempts per 15-minute sliding window triggers `HTTP 429 Too Many Requests`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Brute-Force Rate Limiting
|
||||
## 3. Filesystem Permissions Matrix
|
||||
|
||||
- `nx9-wg` maintains an append-only tracking log of login attempts in SQLite.
|
||||
- If more than 5 failed authentication attempts originate from the same IP address within a 15-minute sliding window, subsequent login requests are rejected with `HTTP 429 Too Many Requests`.
|
||||
| Path | Standard Owner | File Mode | Purpose / Security Scope |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `/usr/local/bin/nx9-wg` | `root:root` | `0755` | Executable binary |
|
||||
| `/etc/nx9-wg/` | `root:root` | `0750` | Configuration directory |
|
||||
| `/etc/nx9-wg/config.toml` | `root:root` | `0640` | Production configuration file |
|
||||
| `/var/lib/nx9-wg/` | `root:root` | `0700` | Working directory and SQLite database storage |
|
||||
| `/var/lib/nx9-wg/nx9-wg.db` | `root:root` | `0600` | Authoritative SQLite database with WAL journals |
|
||||
| `/var/lib/nx9-wg/backups/` | `root:root` | `0700` | Atomic SQLite database snapshots and checksum manifests |
|
||||
| `/var/lib/nx9-wg/admin-password`| `root:root` | `0600` | Initial generated password file |
|
||||
| `/var/log/nx9-wg/` | `root:root` | `0750` | Operational logs (if file logging enabled) |
|
||||
|
||||
---
|
||||
|
||||
## 4. Secret Handling and Memory Safety
|
||||
## 4. Zero Subprocess Execution Guarantee
|
||||
|
||||
- **Redacted Debug Outputs**: Types holding sensitive material (`WireGuardPrivateKey`, `WireGuardPresharedKey`, `Admin`, `ApiToken`) implement custom `std::fmt::Debug` formatters outputting `[REDACTED]`.
|
||||
- **No Plaintext Logging**: Secrets are strictly excluded from structured `tracing` event spans.
|
||||
`nx9-wg` strictly forbids external subprocess execution in production:
|
||||
- **No `std::process::Command` / `tokio::process`**: Eliminates command injection, shell escaping vulnerabilities, and PATH hijack risks.
|
||||
- **No External CLI Dependencies**: Does not shell out to `wg`, `ip`, `nft`, `iptables`, `sysctl`, or `bash`.
|
||||
- **Direct Kernel Communication**: Communicates via native Linux Netlink sockets (RTNETLINK and WireGuard Generic Netlink) and direct in-process `libnftables` Netfilter bindings.
|
||||
|
||||
---
|
||||
|
||||
## 5. Audit Logging
|
||||
## 5. nftables Scoping & Firewall Isolation
|
||||
|
||||
Every state-changing operation records an append-only audit event:
|
||||
- Authentication (`Login`, `Logout`, `LoginFailed`)
|
||||
- Credential Lifecycle (`PasswordChange`, `TotpChange`, `ApiTokenCreate`, `ApiTokenRevoke`)
|
||||
- Network & WireGuard (`InterfaceCreate`, `PeerCreate`, `PeerRotateKeys`, `RouteCreate`, `FirewallCreate`)
|
||||
- System Operations (`BackupCreate`, `BackupRestore`, `ReconciliationRun`)
|
||||
- **Table Isolation**: All rules and chains are strictly confined to `table inet nx9_wg`.
|
||||
- **Zero Interference**: `nx9-wg` never flushes or modifies external tables created by Docker, Kubernetes, systemd-networkd, or host firewalls.
|
||||
- **Deterministic Priority Rules**: Chains and rules are ordered deterministically by priority index to prevent rule shadowing or accidental packet leaks.
|
||||
|
||||
---
|
||||
|
||||
## 6. Secret Redaction & Memory Safety
|
||||
|
||||
- Custom `std::fmt::Debug` implementations enforce `[REDACTED]` for `WireGuardPrivateKey`, `WireGuardPresharedKey`, `Admin`, and `ApiToken`.
|
||||
- Web UI and REST API responses redact private keys and token hashes.
|
||||
- CLI status output strictly redacts sensitive hashes.
|
||||
|
||||
---
|
||||
|
||||
## 7. Append-Only Security Audit Logging
|
||||
|
||||
Every state mutation records an append-only audit event with timestamp, actor, IP address, event type, and context metadata:
|
||||
- Authentication events (`Login`, `Logout`, `LoginFailed`)
|
||||
- Credential modifications (`PasswordChange`, `ApiTokenCreate`, `ApiTokenRevoke`)
|
||||
- WireGuard & Network configurations (`InterfaceCreate`, `PeerCreate`, `RouteCreate`, `FirewallCreate`)
|
||||
- System operations (`BackupCreate`, `BackupRestore`, `ReconciliationRun`)
|
||||
@@ -0,0 +1,46 @@
|
||||
# Quality Assurance & Testing Strategy
|
||||
|
||||
`nx9-wg` enforces a comprehensive, multi-tiered verification strategy designed to guarantee code correctness, memory safety, failure semantics, and secret protection.
|
||||
|
||||
---
|
||||
|
||||
## 1. Test Suite Summary & Quality Gates
|
||||
|
||||
| Tier | Test Suite / Check | Scope & Execution Target | Current Status |
|
||||
| :--- | :--- | :--- | :---: |
|
||||
| **Tier 1** | Code Formatting | `cargo fmt --all -- --check` | **PASS** (Zero diffs) |
|
||||
| **Tier 2** | Type & Borrow Check | `cargo check --workspace` | **PASS** (Zero errors) |
|
||||
| **Tier 3** | Workspace Unit Tests | `cargo test --workspace` | **PASS** (**91 / 91 passed**) |
|
||||
| **Tier 4** | Clippy Linter Check | `cargo clippy --workspace --all-targets --all-features -- -D warnings` | **PASS** (Zero warnings) |
|
||||
| **Tier 5** | Release Compilation | `cargo build --release` | **PASS** (Clean build) |
|
||||
| **Tier 6** | Comprehensive CLI Suite | `LIVE=0 bash scripts/test-cli-comprehensive.sh` | **PASS** (**203 passed** / 7 skipped) |
|
||||
| **Tier 7** | Native Integration Suite | `LIVE=0 bash scripts/test-native-integration.sh` | **PASS** (**19 passed** / 1 skipped) |
|
||||
| **Tier 8** | Dedicated Live Kernel Suite | `LIVE=0 bash scripts/test-live-kernel.sh` | **PASS** (**23 passed** / 1 skipped) |
|
||||
| **Tier 9** | Subprocess Safety Audit | Automated source scan for `Command::new` | **PASS** (Zero subprocesses) |
|
||||
| **Tier 10** | Secret Leakage Audit | Automated scan for plaintext credentials | **PASS** (Zero secrets leaked) |
|
||||
| **Tier 11** | Release Package Check | Standalone archive extraction & verification | **PASS** (Independent execution) |
|
||||
|
||||
---
|
||||
|
||||
## 2. SAFE Mode (`LIVE=0`) vs Real-Kernel Mode (`LIVE=1`)
|
||||
|
||||
To guarantee safety when developing on unprivileged developer workstations:
|
||||
|
||||
### SAFE Mode (`LIVE=0` — Default)
|
||||
- Uses real in-memory SQLite stores and dry-run Netlink message builders.
|
||||
- Validates CLI parsers, JSON/YAML/CSV output formatters, route equality rules, and read-only reconciliation planning.
|
||||
- Automatically skips live kernel mutation steps that require root or `CAP_NET_ADMIN`.
|
||||
|
||||
### Real-Kernel Mode (`LIVE=1` — Dedicated Host Only)
|
||||
- Requires `root` or `CAP_NET_ADMIN` in a dedicated, disposable Linux VM.
|
||||
- Creates real kernel WireGuard interfaces (e.g. `nx9t...`), attaches IPv4/IPv6 addresses, installs routes in the kernel routing table, configures `table inet nx9_wg` in Netfilter, and validates live handshake telemetry.
|
||||
|
||||
---
|
||||
|
||||
## 3. Automated Subprocess & Secret Audits
|
||||
|
||||
Every verification run executes strict source-level security audits:
|
||||
|
||||
1. **Subprocess Audit**: Confirms zero instances of `std::process::Command`, `tokio::process::Command`, `Command::new`, or shell scripts in production Rust crates.
|
||||
2. **Secret Redaction Audit**: Confirms that password hashes, private keys, preshared keys, and token hashes are never printed in human-readable status outputs or logs.
|
||||
3. **Environment Audit**: Confirms that all recognized environment variables strictly observe the `NX9_WG_*` namespace.
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# Web User Interface (SPA) Architecture & Route Reference
|
||||
|
||||
`nx9-wg` embeds a complete, zero-dependency HTML5/CSS/JavaScript Single Page Application (SPA) directly inside the Rust binary.
|
||||
|
||||
---
|
||||
|
||||
## 1. Frontend Architecture & Design System
|
||||
|
||||
- **Zero External Toolchains**: Built entirely in standard HTML5, CSS3, and modern Vanilla ES6+ JavaScript. No Node.js, npm, Webpack, Vite, React, or external CDN dependencies.
|
||||
- **Embedded Static Assets**: HTML, CSS, and JavaScript are bundled into the binary at compile time via `include_str!()` and served from memory.
|
||||
- **Unified Design Tokens**: Custom CSS variable design system (`nx9-wg-ui/src/css.rs`) providing Dark and Light themes with persistent `localStorage` preference.
|
||||
- **Responsive Layout**: Mobile-first responsive layout with side-drawer navigation and `@media (max-width: 768px)` breakpoints.
|
||||
- **Live WebSocket Event Stream**: Connects to `ws://<host>/api/v1/ws` for reactive dashboard, peer handshake, and reconciliation updates without polling.
|
||||
- **Presentation-Only Separation**: The UI contains presentation and client routing logic only; all business validation, allocation, and state authority reside in the backend REST API and SQLite.
|
||||
|
||||
---
|
||||
|
||||
## 2. Complete Route Inventory
|
||||
|
||||
| Hash Route | Navigation Label | Purpose & Operational Features |
|
||||
| :--- | :--- | :--- |
|
||||
| `#dashboard` | **Dashboard** | System status, uptime, interface/peer counts, diagnostics health, and reconciliation status cards. |
|
||||
| `#interfaces` | **Interfaces** | List WireGuard interfaces, "+ Create Interface" modal, enable/disable toggle, and delete interface. |
|
||||
| `#peers` | **Peers** | Enrolled peer table with real-time handshakes, status filter, "+ Add Peer" modal with MTU profile resolution, client configuration export, and live SVG QR rendering. |
|
||||
| `#networks` | **Networks** | Subnet network ranges, CIDR masks, "+ Create Network" modal, and deletion. |
|
||||
| `#routes` | **Routes** | Routing table entries, gateway assignments, "+ Create Route" modal, and deletion. |
|
||||
| `#firewall` | **Firewall** | nftables packet filtering rules in `table inet nx9_wg`, "+ Create Rule" modal, priority ordering, and enable/disable toggle. |
|
||||
| `#nat` | **NAT & Masquerade** | Outbound NAT masquerade status card, active masqueraded subnet list, and instant toggle. |
|
||||
| `#forwarding` | **IP Forwarding** | Kernel sysctl `/proc/sys/net/ipv4/ip_forward` packet forwarding status and toggle. |
|
||||
| `#reconciliation` | **Reconciliation** | Real-time kernel drift overview, planned execution actions table, and interactive "Run Reconcile (Apply)" button. |
|
||||
| `#diagnostics` | **Diagnostics** | Automated health inspection across all 9 subsystems (`system`, `network`, `wireguard`, `peer`, `routing`, `forwarding`, `firewall`, `nat`, `reconciliation`) with remediation hints. |
|
||||
| `#live-state` | **Live State** | Live Linux Netlink kernel telemetry, active WireGuard interfaces, and live routing table entries. |
|
||||
| `#settings` | **Settings** | Appliance key-value parameters table and danger zone reset controls. |
|
||||
| `#backups` | **Backups** | Atomic SQLite database backup snapshots list, "+ Create Backup Snapshot" button, and direct `.db` download. |
|
||||
| `#audit` | **Audit Log** | Append-only security and administrative audit trail with actor, IP, timestamp, and metadata. |
|
||||
| `#administrator` | **Administrator** | Admin account verification, "Change Password" modal, and "+ Generate API Token" modal with one-time raw secret copy. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Interactive Modals & Client Transport Profiles
|
||||
|
||||
### A. Client Profile & MTU Resolution Modal
|
||||
When enrolling a new peer (`#peers`), the modal automatically queries `/api/v1/client-profiles/resolve` based on selected Device (Android, iOS, Linux, Windows, macOS) and Connection (Mobile Cellular 4G/5G, Wi-Fi, Wired Ethernet) to determine optimal MTU (1280 vs 1360 vs 1420) and persistent keepalive (25s).
|
||||
|
||||
### B. Client Export & QR Code Modal
|
||||
Displays both:
|
||||
1. **Interactive Vector QR Code**: Inline SVG rendering for scanning directly with the official WireGuard mobile app.
|
||||
2. **Downloadable `.conf` File**: Standard WireGuard client configuration file formatted for instant download or clipboard copy.
|
||||
|
||||
### C. One-Time API Token Delivery Modal
|
||||
Generates a new API token, calculates its SHA-256 digest for SQLite storage, and presents the raw token string once in an interactive modal with a copy button.
|
||||
|
||||
---
|
||||
|
||||
## 4. Error Handling & Session Recovery
|
||||
|
||||
- **HTTP 401 Interception**: When a session expires or credentials are revoked, the client `api()` helper automatically transitions to the login view (`renderLoginPage()`).
|
||||
- **Input Validation**: Modals enforce client-side form validation before submitting requests to the backend.
|
||||
- **Graceful Error Alerts**: Backend API error messages are formatted clearly in alert dialogs.
|
||||
Reference in new issue
Block a user