CHAN.RUN

Products
Restunnel
Guide

Contributing

Contributing

Restunnel is a Rust monorepo with platform-specific apps for Android (Kotlin) and macOS (Tauri). This page covers how to build from source and understand the project structure.

Prerequisites

  • Rust 1.93+ — see mise.toml for the exact version
  • mise — manages all tool versions (Rust, Node, Android SDK, etc.)
# Install mise, then from the repo root:
mise install

Android development

  • Android SDK (API 34) + NDK 27 — installed via mise
  • Build: mise run android:build
  • Lint: mise run android:lint

Desktop development (Tauri)

  • Node.js (LTS) — required for Tauri CLI
  • Build: mise run desktop:build
  • Dev mode: mise run desktop:dev

Project Structure

tunnel.chan.run/
├── crates/
│   ├── core/           # restunnel-core — shared library
│   │   └── src/
│   │       ├── noise.rs        # Noise protocol handshake
│   │       ├── transport.rs    # Encrypted channel read/write
│   │       ├── protocol.rs     # Binary message codec
│   │       ├── relay.rs        # TCP relay + private IP blocking
│   │       ├── auth.rs         # Enrollment + key management
│   │       ├── node.rs         # Node-side protocol
│   │       ├── keepalive.rs    # PING/PONG state machine
│   │       ├── reconnect.rs    # Exponential backoff
│   │       └── session/        # Connection management + stream relay
│   ├── hub/            # restunnel-hub binary
│   ├── node-cli/       # restunnel-node binary
│   └── android/        # JNI bridge (cdylib)
├── apps/
│   ├── android/        # Kotlin Android project
│   └── desktop/        # Tauri macOS app
├── docs/               # Internal project documentation
├── docs-site/          # Public documentation (this site)
└── infra/              # Hetzner test infrastructure (OpenTofu)

Key crates

CrateTypePurpose
restunnel-coreLibraryNoise handshake, transport, codec, relay, auth, session loop. Shared by all consumers.
restunnel-hubBinaryTunnel server, SOCKS5/HTTP proxy, dashboard, node management.
restunnel-nodeBinaryCLI exit node — thin wrapper around restunnel-core.
restunnel-androidcdylibJNI bridge — exposes core to Kotlin via high-level functions.
restunnel-desktopBinaryTauri app — uses core directly via Rust.

Build & Test

# Build all workspace crates
mise run build

# Run tests
mise run test

# Format check + linting
mise run format
mise run lint

# Security audit
mise run audit

Android

mise run android:build     # Build .so + APK (debug)
mise run android:install   # Install on connected device
mise run android:lint      # Kotlin lint

Desktop

mise run desktop:dev       # Dev mode with hot reload
mise run desktop:build     # Release build (.dmg)
mise run desktop:lint      # Clippy on desktop crate

Cross-compilation (for deployment)

The hub runs on ARM Linux (Hetzner). Cross-compile from macOS:

mise run cross:build       # Builds hub + node for aarch64-linux-gnu
mise run deploy:hub        # Cross-compile + deploy + restart

Requires Docker running (uses cross).

Fuzz testing

mise run fuzz:all          # Run all fuzz targets (60s each)
mise run fuzz:message 300  # Fuzz message codec for 5 minutes

Requires cargo-fuzz and nightly Rust.

Code Conventions

Commits

Conventional Commits with phase scope during phased work:

feat(phase-1a): implement Noise_IK handshake in core
fix(hub): prevent panic on malformed frame
docs: update readme

Commit types drive automated version bumps via release-please.

Error handling

  • thiserror for typed errors in restunnel-core (callers need to match variants)
  • anyhow for binaries (hub, node-cli)
  • No .unwrap() outside of tests

Logging

tracing crate with structured fields:

tracing::info!(node_id = %id, latency_ms = lat, "node connected");

Testing

Security-critical code (noise, relay, auth, protocol) gets tests immediately. Everything else grows coverage incrementally. See the fuzz targets for codec robustness testing.

Test Infrastructure

A Hetzner Cloud server is available for real-world testing:

mise run infra:apply    # Create the server
mise run infra:info     # Get IPs
mise run deploy:hub     # Deploy the hub binary
mise run infra:destroy  # Tear down

See infra/README.md for details.