Skip to content

Security Model

meshguard's security model is built on three pillars: cryptographic identity, decentralized trust, and attack surface minimization.

Threat Model

What meshguard protects against

ThreatMitigation
EavesdroppingAll traffic encrypted with ChaCha20-Poly1305 (WireGuard Noise_IK)
Man-in-the-middleEd25519 signatures in handshake, mutual authentication
Replay attacks2048-bit sliding window + TAI64N timestamps in handshake
Key compromiseTransport keys rotate every 120s; identity keys never transmitted
Unauthorized peersauthorized_keys/ directory gates membership
NAT traversal attacksHole punch uses 16-byte random tokens, not predictable patterns

What meshguard does NOT protect against

ThreatWhyMitigation
Compromised hostIf attacker has root on a trusted node, all mesh traffic is readableHost hardening, least privilege
Social engineeringIf you add a malicious peer's key, they're in the meshVerify fingerprints out-of-band
Traffic analysisPacket sizes and timing are visibleUse constant-time padding (future work)
DoSUDP flood to public portsRate limiting at firewall level

Key Hygiene

Identity Keys

  • Never share identity.key — this is your node's long-term identity
  • Use --force carefullymeshguard keygen --force overwrites your identity
  • Backups — store identity.key offline, not in git

WireGuard Transport Keys

  • Ephemeral — X25519 keys are generated at startup, never persisted
  • Auto-rotate — rekey every 120s (REKEY_AFTER_TIME)
  • Hard timeout — reject after 180s (REJECT_AFTER_TIME)

Organization Keys

  • Org admins hold signing keys — treat like root CA keys
  • Node certificates — 186 bytes, stored at ~/.config/meshguard/node.cert
  • Revocation — use org-revoke immediately if a node is compromised

Attack Surface

Exposed Ports

PortProtocolPurpose
51821/udpSWIM + WGGossip, handshake, transport (multiplexed)
51830/udpWGWireGuard transport (if --kernel mode)

Network Exposure

  • Public IP nodes — accept connections from any IP (but only authorized keys)
  • NATed nodes — only reachable via hole punch or relay
  • Recommendation — run behind a firewall, whitelist seed peer IPs

Memory Safety

  • Written in Zig — no null pointer derefs, bounds-checked slices
  • No dynamic memory in hot path — fixed-size pools, no allocator in packet processing
  • Secrets zeroizedcrypto.timing_safe.eql for comparisons, explicit zeroing on peer removal

Trust Model

Individual Trust

  • Each node manages its own authorized_keys/ directory
  • No central authority validates membership
  • Trust is bidirectional — both peers must have each other's keys

Organization Trust

  • Org certificate signs node public key + name + expiry
  • Lamport timestamps resolve alias conflicts (earliest claim wins)
  • Revocation propagates via SWIM gossip

Security Recommendations

  1. Firewall the gossip port — only allow from trusted IP ranges
  2. Use org trust for fleets — easier key rotation than N individual keys
  3. Monitor for unknown keys — log new peer joins
  4. Rotate org keys annually — generate new org keypair, re-sign node certs
  5. Run as non-root if possible — userspace mode only needs CAP_NET_ADMIN

Comparison with Other VPNs

FeaturemeshguardTailscaleWireGuard (manual)
Central authorityNoneControl planeNone
Key distributionManual / org-signedAutomaticManual
RevocationDelete file / gossipDashboardManual
NAT traversalSTUN + hole punch + relayDERP serversManual port forward
Attack surfaceSingle UDP portMultiple servicesSingle UDP port

Released under the MIT License.