A terminal that leaves no trace
Nyx is a fully decentralized, anonymous peer-to-peer communication engine written in Rust. Every instance is a sovereign node in a globally distributed mesh — there are no servers, no databases, no administrator accounts, and no signup flow. The network is its users.
The architecture layers three independent systems: the Kademlia DHT for global peer discovery, GossipSub for mesh-level message routing, and a request-response whisper channel for direct one-to-one key delivery. Application-layer AES-256-GCM encryption ensures that even if mesh routing is observed, the contents are opaque to every node that doesn't hold the correct room key in RAM.
QUIC over UDP
Zero-RTT reconnection, multiplexed streams, and built-in TLS 1.3 at the network layer.
Dual-engine routing
mDNS for instant LAN discovery. Kademlia DHT for global O(log N) resolution with O(1) LRU cache on top.
Signature-enforced gossip
GossipSub with strict validation. Every message is signed by the sender's Ed25519 keypair — spoofing is structurally impossible.
Zero-trust rooms
256-bit AES keys live only in RAM. The mesh routes ciphertext — nodes without the key receive incomprehensible binary noise.
RAM remanence protection
Keys are wrapped in ZeroizeOnDrop structs. Volatile memset to 0x00 fires the microsecond a room is exited.
NAT traversal
dcutr punches through symmetric NAT without manual port forwarding via a libp2p relay circuit upgrade.
System architecture
Nyx composes nine libp2p protocol behaviours into a single unified swarm. Each behaviour handles a distinct concern and communicates through the swarm event bus only.
Message flow: plaintext to wire
Every publish is a fresh nonce + ciphertext blob. The mesh sees only opaque binary.
Zero-trust room model
Nyx separates transport security from application-layer secrecy. QUIC provides TLS 1.3 between adjacent peers — but that only protects the hop, not the route. AES-256-GCM secures the room end-to-end regardless of how many relay hops the packet takes.
Room key lifecycle
/nyx/invite/1.0.0 — the AES key never touches the gossip mesh.Why application-layer encryption?
QUIC/TLS secures the link between two adjacent nodes. It does not protect message contents from other authenticated members of the same GossipSub topic. AES-256-GCM ensures that subscription grants no meaningful information — only nodes holding the symmetric key recover plaintext.
Encryption implementation
// Per-message encryption — src/main.rs
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(¤t_room_key.0));
let nonce = Aes256Gcm::generate_nonce(&mut OsRng); // 96-bit fresh nonce
let mut payload = nonce.to_vec(); // prepend nonce
payload.extend_from_slice(&cipher.encrypt(&nonce, cmd.as_bytes())?);
swarm.behaviour_mut().gossipsub.publish(topic, payload); // ciphertext on the wire
Active DoS shielding
Exposing a raw UDP listener to the internet risks amplification and exhaustion attacks. Nyx implements two independent, layered defences directly in the swarm event loop.
Token bucket rate limiter
Each unique source IP is tracked in a HashMap<IpAddr, TokenBucket>. Buckets refill at 0.5 tokens/second up to a capacity of 5 tokens. A new connection consumes one token; when empty the connection is silently throttled.
fn check_and_consume(&mut self) -> bool {
let elapsed = now.duration_since(self.last_refill).as_secs_f64();
self.tokens = (self.tokens + elapsed * self.refill_rate).min(self.capacity);
if self.tokens >= 1.0 { self.tokens -= 1.0; true } else { false }
}
Hard connection bounds
| Limit | Value | Purpose |
|---|---|---|
| max_pending_incoming | 10 | Half-open handshake queue |
| max_pending_outgoing | 5 | Outbound dial queue |
| max_established_incoming | 30 | Inbound peer slots |
| max_established_outgoing | 30 | Outbound peer slots |
| max_established_total | 60 | Total simultaneous peers |
| max_established_per_peer | 2 | Multi-stream dedup guard |
Installation
Requires the latest stable Rust toolchain. No other system dependencies on macOS or Windows.
# Install Rust (if not present)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
# Clone and install globally
git clone https://github.com/tyrobro/nyx.git
cd nyx
cargo install --path . --force
# Launch
nyx
On Ubuntu/Debian you may need the C build toolchain:
sudo apt install build-essential pkg-config
Usage guide
Launch with nyx. The node immediately binds a random QUIC port, bootstraps into the global Kademlia DHT, and subscribes to nyx-global. Your Peer ID is printed on boot; share it out-of-band to establish a private room.
| Command | Description |
|---|---|
| /create <room_name> | Generates a 256-bit AES key in RAM, unsubscribes from the current topic, and moves you into a new cryptographically sealed room. |
| /invite <PeerID> | Dials the target peer and dispatches the current room's AES key as a base64 CBOR payload over /nyx/invite/1.0.0. The key never touches the gossip mesh. |
| /dm <PeerID> | Creates a one-time ephemeral room with a random ID and key, then atomically invites the target. Equivalent to /create + /invite in a single command. |
| /accept | Processes a pending invite: decodes the base64 key, loads it into a ZeroizeOnDrop struct, and drops you into the sender's encrypted room. |
| /connect <PeerID> | Manually resolves a Peer ID via LRU cache or Kademlia DHT and negotiates a QUIC tunnel. |
| /exit | Triggers ZeroizeOnDrop on all active room keys, tears down all QUIC/relay sockets, and terminates the process. |
Technology stack
Roadmap
NAT traversal refinement
Relay circuit negotiation and dcutr hole-punch success rates across different NAT topologies including carrier-grade NAT.
Multi-relay failover
Maintain a ranked list of known relays and automatically re-circuit when the active relay goes offline.
Encrypted file transfer
Chunked, AES-encrypted binary streaming over the established Yamux multiplexer without leaving the encrypted session context.
Forward secrecy
Rotate room keys on a configurable interval using a ratchet construction, limiting the blast radius of a key compromise.
Persistent identity
Optional Ed25519 identity persistence with passphrase encryption so a Peer ID survives process restarts.