Skip to content

MiniGuard is a minimal Layer-3 VPN that uses a TUN interface and a UDP tunnel secured with X25519 key exchange and ChaCha20-Poly1305 encryption.

Notifications You must be signed in to change notification settings

chahat-101/MiniGuard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

MiniGuard

A minimal Layer-3 VPN implementation for Windows using Wintun and UDP tunneling, secured with X25519 key exchange and ChaCha20-Poly1305 encryption.

Overview

MiniGuard demonstrates core VPN concepts through a clean implementation using:

  • Wintun: High-performance Layer-3 TUN driver for Windows
  • X25519: Elliptic curve Diffie-Hellman for key exchange
  • ChaCha20-Poly1305: AEAD cipher for authenticated encryption
  • HKDF-SHA256: Key derivation from shared secrets
  • UDP: Fast transport with custom ACK mechanism

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Client (Windows)                        β”‚
β”‚                                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              Wintun Virtual Interface                   β”‚   β”‚
β”‚  β”‚                  (10.0.0.2/24)                          β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚ IP Packets                            β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚            Packet Processing Layer                      β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  1. Read IP packet from Wintun                          β”‚   β”‚
β”‚  β”‚  2. Generate random 12-byte nonce                       β”‚   β”‚
β”‚  β”‚  3. Encrypt with ChaCha20-Poly1305                      β”‚   β”‚
β”‚  β”‚  4. Prepend nonce to ciphertext                         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚                                       β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚            X25519 Key Exchange Layer                    β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  β€’ Generate ephemeral keypair                           β”‚   β”‚
β”‚  β”‚  β€’ Exchange public keys                                 β”‚   β”‚
β”‚  β”‚  β€’ Compute shared secret                                β”‚   β”‚
β”‚  β”‚  β€’ Derive encryption key (HKDF-SHA256)                  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚                                       β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              UDP Transport Layer                        β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  β€’ Send encrypted packets over UDP                      β”‚   β”‚
β”‚  β”‚  β€’ Retry with 400ms timeout until ACK                   β”‚   β”‚
β”‚  β”‚  β€’ Handle acknowledgments                               β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          β”‚
                          β”‚ UDP Tunnel
                          β”‚ (Encrypted Traffic)
                          β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         β”‚                  Server               β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              UDP Transport Layer                        β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  β€’ Receive encrypted packets                            β”‚   β”‚
β”‚  β”‚  β€’ Send ACK responses                                   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚                                       β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚            X25519 Key Exchange Layer                    β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  β€’ Generate ephemeral keypair                           β”‚   β”‚
β”‚  β”‚  β€’ Exchange public keys                                 β”‚   β”‚
β”‚  β”‚  β€’ Compute shared secret                                β”‚   β”‚
β”‚  β”‚  β€’ Derive encryption key (HKDF-SHA256)                  β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                         β”‚                                       β”‚
β”‚                         ↓                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚            Packet Processing Layer                      β”‚   β”‚
β”‚  β”‚                                                         β”‚   β”‚
β”‚  β”‚  1. Extract nonce (first 12 bytes)                      β”‚   β”‚
β”‚  β”‚  2. Extract ciphertext                                  β”‚   β”‚
β”‚  β”‚  3. Decrypt with ChaCha20-Poly1305                      β”‚   β”‚
β”‚  β”‚  4. Log decrypted packet contents                       β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Features

  • πŸ”’ Modern cryptography (X25519 + ChaCha20-Poly1305 + HKDF)
  • πŸš€ UDP-based transport with retry logic
  • πŸͺŸ Windows-native using Wintun driver
  • πŸ”§ Ephemeral keys for forward secrecy
  • πŸ“¦ Clean Rust implementation (~300 lines)

Prerequisites

  • Rust (latest stable version)
  • Windows OS
  • Administrator privileges (required for network interface creation)

Installation

git clone https://github.com/chahat-101/MiniGuard.git
cd MiniGuard
cargo build --release

Usage

Server Mode

Start the server to listen for incoming connections:

cargo run --bin server -- --listen 0.0.0.0:4000 --salt "your-secret-salt"

Arguments:

  • --listen, -l: Bind address and port (default: 0.0.0.0:4000)
  • --salt, -s: Shared salt for key derivation (must match client)

Client Mode

⚠️ Administrator privileges required to create Wintun network interfaces.

cargo run --bin client -- --data "client1" --target 192.168.1.100:4000 --salt "your-secret-salt"

Arguments:

  • --data: Local data identifier
  • --target: Server address and port
  • --salt: Shared salt for key derivation (must match server)

The client automatically creates a Wintun adapter with:

  • IP Address: 10.0.0.2
  • Netmask: 255.255.255.0
  • Gateway: 10.0.0.1

Test the connection:

ping 203.0.113.10

How It Works

Protocol Flow

Client                                    Server
  β”‚                                         β”‚
  β”œβ”€β”€β”€β”€ X25519 Public Key ─────────────────→│  1. Handshake
  │←─── X25519 Public Key ─────────────────── 
  β”œβ”€β”€β”€β”€ ACK ───────────────────────────────→│
  β”‚                                         β”‚
  β”‚     (Both derive shared key via HKDF)   β”‚  2. Key Derivation
  β”‚                                         β”‚
  β”œβ”€β”€β”€β”€ [Nonce || Encrypted Packet] ──────→ β”‚  3. Data Transfer
  │←─── ACK ─────────────────────────────── ─

Step-by-Step

  1. Handshake: Client and server exchange ephemeral X25519 public keys over UDP
  2. Key Derivation: Both compute shared secret and derive ChaCha20 key using HKDF with the shared salt
  3. Encryption: Client reads IP packets from Wintun, encrypts with ChaCha20-Poly1305 (random nonce per packet)
  4. Transmission: Encrypted packets sent over UDP with retry logic until ACK received
  5. Decryption: Server decrypts packets and logs contents (no forwarding implemented)

Security Details

Cryptographic Primitives:

  • X25519: Curve25519 ECDH providing ~128-bit security
  • ChaCha20-Poly1305: AEAD providing both confidentiality and authenticity
  • HKDF-SHA256: Cryptographically strong key derivation
  • Random Nonces: 12-byte nonce generated per packet using OsRng

Security Properties:

  • Ephemeral key exchange (new keys per connection)
  • Forward secrecy enabled
  • Authenticated encryption prevents tampering
  • Salt-based key derivation prevents rainbow table attacks

Note: Salt must be kept secret and shared between client and server.

Configuration

Network Settings

Client automatically configures:

IP Address:    10.0.0.2
Netmask:       255.255.255.0
Gateway:       10.0.0.1
Adapter Name:  minguard

Timeout Settings

  • Handshake retry: 400ms
  • ACK timeout: 400-500ms
  • Retries: Infinite until success

Limitations

⚠️ This is an educational project demonstrating VPN cryptography and protocols.

Current limitations:

  • Windows only (Wintun driver dependency)
  • No packet forwarding or routing implementation
  • Server only decrypts and logs packets
  • No concurrent connection handling
  • No reconnection mechanism
  • No key rotation (reconnect for new keys)
  • No authentication beyond shared salt
  • No rate limiting or DoS protection

Dependencies

Core dependencies:

  • tokio - Async runtime
  • wintun - Windows TUN driver
  • x25519-dalek - X25519 key exchange
  • chacha20poly1305 - AEAD encryption
  • hkdf + sha2 - Key derivation
  • clap - CLI parsing

Built With

Rust Tokio

Special Thanks

This project is built on the shoulders of these excellent Rust crates:

Networking & System:

  • tokio - Asynchronous runtime for Rust
  • wintun - Safe Rust bindings for the Wintun driver

Cryptography:

Utilities:

  • clap - Command Line Argument Parser
  • rand - Random number generation
  • hex - Hexadecimal encoding/decoding

A huge thank you to all the maintainers and contributors of these crates! πŸ™

Troubleshooting

"Access Denied" error:

  • Run client as Administrator
  • Right-click PowerShell/CMD β†’ "Run as administrator"

Connection timeouts:

  • Verify server is running
  • Check firewall allows UDP on specified port
  • Ensure salt matches exactly between client and server

Wintun adapter issues:

  • Check Windows Device Manager for adapter status
  • Review Windows Event Viewer for driver errors
  • Try deleting existing "minguard" adapter

Contributing

Contributions welcome! Feel free to open issues or submit pull requests.

License

See repository for license details.

Disclaimer

MiniGuard is for educational purposes only. It demonstrates VPN concepts but lacks features needed for production use. For real-world VPN needs, use established solutions like WireGuard, OpenVPN, or IPsec.

Acknowledgments

Inspired by WireGuard's minimalist design philosophy and modern cryptographic choices.


Project Stats: ~300 lines of Rust demonstrating X25519 key exchange, HKDF key derivation, and ChaCha20-Poly1305 AEAD encryption in a VPN context.

About

MiniGuard is a minimal Layer-3 VPN that uses a TUN interface and a UDP tunnel secured with X25519 key exchange and ChaCha20-Poly1305 encryption.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages