A secure, high-performance user-space IP-over-UDP tunnel implementation written in Rust using async I/O and modern cryptography.
opentun creates a TUN interface that tunnels IP packets over UDP with ChaCha20-Poly1305 encryption. It enables secure communication between peers across networks using Curve25519 key exchange and YAML-based configuration.
- ✅ IP-over-UDP tunneling - Encapsulate IP packets in UDP for transport
- ✅ Async I/O - Built with Tokio for high performance
- ✅ ChaCha20-Poly1305 encryption - Modern authenticated encryption
- ✅ Curve25519 key exchange - Elliptic curve Diffie-Hellman key agreement
- ✅ YAML configuration - Persistent peer and key management
- ✅ Key generation tools - Built-in cryptographic key utilities
- ✅ IPv4 support - Full IPv4 packet routing
- ⏳ Planned: IPv6 support, rate limiting, improved error handling
- Rust 1.70+
- Linux/macOS (requires TUN interface support)
- Root privileges (for TUN interface creation)
git clone https://github.com/yourusername/opentun
cd opentun
cargo build --releaseGenerate cryptographic keys for secure communication:
# Generate a private key
./target/release/opentun genkey
# Generate public key from private key
./target/release/opentun pubkeyCreate a config.yaml file or let opentun generate a default one:
name: "utun0"
address: "10.0.0.1"
port: 1194
secret: "base64-encoded-private-key"
pubkey: "base64-encoded-public-key"
peers:
10.0.0.2:
sock_addr: "192.168.1.100:1194"
pub_key: "peer-base64-public-key"# Run with configuration file (recommended)
sudo ./target/release/opentun
# CLI arguments (legacy support)
sudo ./target/release/opentun [NAME] [ADDRESS] [PORT]# Build and run with proper capabilities
chmod +x run.sh
./run.shUsage: opentun [OPTIONS] [NAME] [ADDRESS] [PORT]
Arguments:
[NAME] TUN interface name (default: from config)
[ADDRESS] Local IP address (default: from config)
[PORT] UDP port to bind (default: from config)
Commands:
genkey Generate a new private key
pubkey Generate public key from private key
Options:
-h, --help Print help
-V, --version Print version
- TUN Interface: Creates a virtual network interface that captures IP packets
- Encryption: Each packet is encrypted with ChaCha20-Poly1305 using shared secrets
- Key Exchange: Curve25519 Diffie-Hellman establishes shared secrets between peers
- UDP Transport: Encrypted packets are transmitted over UDP with random nonces
- Configuration: Peers are defined in YAML with their public keys and addresses
┌─────────────┐ Encrypted UDP ┌─────────────┐
│ Client A │◄─────────────────►│ Client B │
│ │ ChaCha20-Poly1305 │ │
│ TUN: tun0 │ + Curve25519 │ TUN: tun0 │
│ IP: 10.0.0.1│ │ IP: 10.0.0.2│
└─────────────┘ └─────────────┘
Peer A (10.0.0.1) Peer B (10.0.0.2)
┌─────────────────┐ ┌─────────────────┐
│ Application │ │ Application │
└─────────┬───────┘ └─────────┬───────┘
│ IP packet (10.0.0.1 → 10.0.0.2) │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ TUN Device │ │ TUN Device │
│ (utun0) │ │ (utun0) │
└─────────┬───────┘ └─────────┬───────┘
│ ▲
│ 1. Read IP packet │ 6. Write decrypted
▼ │ IP packet
┌─────────────────┐ ┌─────────────────┐
│ opentun Process │ │ opentun Process │
│ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ Extract │ │ │ │ Decrypt │ │
│ │ dst IP │ │ │ │ with shared │ │
│ └─────────────┘ │ │ │ secret │ │
│ ┌─────────────┐ │ │ └─────────────┘ │
│ │ Lookup peer │ │ │ ┌─────────────┐ │
│ │ config │ │ │ │ Verify │ │
│ └─────────────┘ │ │ │ nonce + │ │
│ ┌─────────────┐ │ │ │ auth tag │ │
│ │ Generate │ │ │ └─────────────┘ │
│ │ random │ │ │ │
│ │ nonce │ │ │ │
│ └─────────────┘ │ │ │
│ ┌─────────────┐ │ │ │
│ │ Encrypt │ │ │ │
│ │ with shared │ │ │ │
│ │ secret │ │ │ │
│ └─────────────┘ │ │ │
└─────────┬───────┘ └─────────┬───────┘
│ ▲
│ 2. Send encrypted │ 5. Receive encrypted
│ packet over UDP │ packet from UDP
▼ │
┌─────────────────┐ ┌─────────────────┐
│ UDP Socket │ │ UDP Socket │
│ (port 1194) │ │ (port 1194) │
└─────────┬───────┘ └─────────┬───────┘
│ ▲
│ 3. Network transmission │
│ [nonce(12) + encrypted_data + auth_tag(16)] │
└─────────────────────────────────────────────────────┘
4. Internet/LAN
Legend:
- Shared Secret = ECDH(local_private_key, peer_public_key)
- Encryption = ChaCha20-Poly1305(shared_secret, nonce, ip_packet)
- Packet Format = nonce || encrypted_data_with_auth_tag
Node A:
- Generate keys:
# Generate private key
PRIVATE_A=$(./target/release/opentun genkey)
# Generate public key
PUBLIC_A=$(echo "$PRIVATE_A" | ./target/release/opentun pubkey)- Create config.yaml:
name: "utun0"
address: "10.0.0.1"
port: 1194
secret: "$PRIVATE_A"
pubkey: "$PUBLIC_A"
peers:
10.0.0.2:
sock_addr: "192.168.1.100:1194"
pub_key: "$PUBLIC_B" # Get from Node B- Run:
sudo ./target/release/opentunNode B:
- Generate keys and create similar config with reversed IPs
- Exchange public keys securely with Node A
- Run the tunnel
After starting opentun, configure routing:
# Add route for the tunnel network
sudo ip route add 10.0.0.0/24 dev utun0
# Bring interface up (if needed)
sudo ip link set up dev utun0- Async Design: Uses
tokio::select!for concurrent TUN/UDP handling - Encryption: ChaCha20-Poly1305 authenticated encryption with random nonces
- Key Exchange: Curve25519 elliptic curve Diffie-Hellman key agreement
- Configuration: YAML-based peer management with persistent keys
- Zero-Copy: Efficient packet forwarding with minimal allocations
- Error Resilience: Continues operation despite individual packet errors
This project is in active development. See PRD.md for the roadmap.
- IPv4 only
- Static peer configuration (no dynamic discovery)
- No structured logging
- No rate limiting or DoS protection
- Basic error recovery
MIT License - see LICENSE file for details.
✅ This software uses ChaCha20-Poly1305 encryption with Curve25519 key exchange for secure communication. While cryptographically secure, ensure proper key management and consider additional security measures for production environments.