Raw capture โ raw/rustdesk.md
url: https://github.com/rustdesk/rustdesk title: "RustDesk โ Open Source Remote Desktop" author: "rustdesk (Purslane Tech Pte. Ltd.)" date_fetched: 2026-07-25 date_published: 2021
RustDesk is an open-source, self-hostable remote desktop application written primarily in Rust with a Flutter UI frontend. It is the leading open-source alternative to TeamViewer and AnyDesk, with ~80K GitHub stars. The project is maintained by Purslane Tech Pte. Ltd. and a large open-source community.
rustdesk) and a library (librustdesk) in cdylib, staticlib, and rlib formatsThe Cargo.toml defines three binaries: rustdesk (default), naming (src/naming.rs), and service (src/service.rs). The library is compiled as librustdesk for FFI linking with Flutter via flutter_rust_bridge.
src/
โโโ main.rs โ entry point: desktop (core_main+ui) vs mobile/flutter (test+init)
โโโ lib.rs โ crate root, re-exports all public modules
โโโ client.rs โ (4327 lines) client-side connection, NAT traversal, audio/video decode
โ โโโ io_loop.rs โ main I/O event loop for connected sessions
โ โโโ helper.rs โ connection helpers
โ โโโ file_trait.rs โ file transfer trait
โ โโโ screenshot.rs โ screenshot handling
โโโ server/ โ server-side services
โ โโโ connection.rs โ (7129 lines) incoming connection handler, auth, session mgmt
โ โโโ video_service.rs โ screen capture + encoding (H264/H265/VP8/VP9/AV1)
โ โโโ audio_service.rs โ audio capture + encoding (Opus)
โ โโโ input_service.rs โ keyboard/mouse input processing
โ โโโ clipboard_service.rs โ clipboard sync
โ โโโ display_service.rs โ multi-monitor display mgmt
โ โโโ terminal_service.rs โ remote terminal access
โ โโโ printer_service.rs โ remote printing
โ โโโ portable_service.rs โ portable (no-install) mode
โ โโโ video_qos.rs โ adaptive video quality
โโโ rendezvous_mediator.rs โ (1002 lines) registration + connection brokering with hbbs
โโโ common.rs โ (3047 lines) shared state, crypto, NAT testing, config
โโโ flutter_ffi.rs โ (3170 lines) FFI bridge to Dart/Flutter
โโโ flutter.rs โ Flutter-specific session management
โโโ ipc.rs โ (2227 lines) inter-process communication
โโโ port_forward.rs โ TCP tunnel / RDP forwarding
โโโ platform/ โ OS-specific implementations
โ โโโ mod.rs โ (248 lines) trait definitions
โ โโโ windows.rs โ Windows: service install, UAC, Winlogon, screen capture
โ โโโ macos.rs โ macOS: accessibility, TCC permissions, retina
โ โโโ linux.rs โ Linux: X11/Wayland detection, display mgmt, headless
โโโ ui/ โ DEPRECATED Sciter UI (replaced by Flutter)
โโโ plugin/ โ plugin framework (opt-in via feature flag)
โโโ whiteboard/ โ cross-platform whiteboard/annotation overlay
โโโ hbbs_http/ โ HTTP client for hbbs server API (sync, account, download)
โโโ keyboard.rs โ keyboard layout handling
โโโ clipboard.rs โ clipboard state machine
โโโ clipboard_file.rs โ file copy/paste between platforms
โโโ lang.rs โ Rust-side translation strings
โโโ lang/ โ per-language translation modules (sq.rs, ko.rs, ru.rs, ...)
โโโ privacy_mode.rs โ privacy mode (blank remote screen)
โโโ virtual_display_manager.rs โ Windows virtual display driver
โโโ kcp_stream.rs โ KCP reliable UDP transport
โโโ updater.rs โ auto-update logic
| Library | Purpose |
|---|---|
hbb_common |
Core shared: protobuf messages, TCP/UDP wrappers, config, file transfer, crypto, TLS |
scrap |
Screen capture: DXGI (Windows), CoreGraphics (macOS), X11/PipeWire/Wayland (Linux), MediaProjection (Android) |
enigo |
Cross-platform keyboard/mouse simulation |
clipboard |
Cross-platform clipboard (text + files) |
virtual_display |
Virtual display driver for headless Windows |
portable |
Portable app packaging |
remote_printer |
Remote printer redirection |
RustDesk uses a three-tier network architecture:
Rendezvous Server (hbbs): ID-based device registry and NAT traversal broker. Devices register their ID + public key. Clients request connections by peer ID. The rendezvous server exchanges NAT addresses to enable hole punching but does not relay data.
Relay Server (hbbr): Fallback relay for when direct connections fail (symmetric NAT, firewall). Relays encrypted traffic between peers.
Direct P2P: The preferred path. Three concurrent strategies raced with select_ok:
- TCP hole punching: Direct TCP connection using addresses exchanged via rendezvous
- UDP hole punching: UDP NAT traversal with STUN-style port prediction
- IPv6 direct: Direct IPv6 connection when both peers have IPv6
- KCP (KCP Stream): Reliable UDP transport layered on top for UDP connections
From client.rs:371-631, the _start_inner method:
PunchHoleRequest containing: peer ID, token, NAT type, licence key, conn type, version, UDP port, IPv6 addr, force_relay flagPunchHoleResponse containing: peer's socket address, NAT type, is_local flag, signed public key, relay server address, feedbackselect_ok (client.rs:695-709):
- TCP direct to peer address
- UDP direct via NAT hole-punched socket
- IPv6 direct via IPv6 socketclient.rs:760-836):
- Server sends SignedId (peer ID signed with server's Ed25519 private key)
- Client verifies signature against the public key obtained from rendezvous
- Client generates ephemeral Curve25519 keypair, sends public key encrypted with server's public key
- Both derive shared symmetric key via NaCl box_ key exchange
- All subsequent traffic encrypted with symmetric keyNAT traversal intelligence (client.rs:660-691): Connection timeout is dynamically computed based on detected NAT types. Symmetric NAT โ 1s. Asymmetric-to-asymmetric โ full CONNECT_TIMEOUT (18s). Unknown NAT โ adaptive based on punch time ร multiplier. Direct failures are tracked per peer and used to adjust future timeout strategies.
Audio pipeline (client.rs:1181-1541): Opus audio decoding โ optional sample rate conversion (via dasp/rubato/samplerate feature flags) โ platform-specific output. On non-Linux: ring buffer (3 seconds at 48kHz stereo) with jitter-compensating adaptive drop (AudioBuffer.try_shrink). On Linux: direct PulseAudio simple API.
Video pipeline (video_service.rs): Multiple codec backends via feature flags โ hwcodec (H264/H265 via platform APIs), vram (GPU VRAM direct), software VP8/VP9/AV1. Adaptive quality via VideoQoS that monitors network conditions.
Plugin framework (plugin/): Opt-in via plugin_framework feature. Native plugin DLLs loaded at runtime. Each plugin declares capabilities via a JSON descriptor. Can intercept and modify input events (src/server/connection.rs:152-177).
Clipboard sync: Polling-based with platform-specific listeners (clipboard_listener). Supports text, images, and files (via unix-file-copy-paste feature flag). File copy/paste uses platform-specific backends (FUSE on Linux, NSFilePromise on macOS, OLE on Windows).
Security model: End-to-end encryption by default using NaCl/libsodium. Key hierarchy:
- Long-term: Ed25519 keypair (device identity, registered with rendezvous)
- Per-session: Ephemeral Curve25519 for forward secrecy
- Password: Stored as salted SHA-256 hash (src/server/connection.rs:1716-1722)
- 2FA: TOTP support via totp-rs crate
- Trusted devices: Device-based bypass for 2FA
The release profile (Cargo.toml:238-244) is optimized for size:
- lto = true (link-time optimization)
- codegen-units = 1 (single codegen unit for better optimization)
- panic = 'abort' (no unwinding)
- strip = true (strip symbols)
The Rust core compiles as a cdylib linked by Flutter via flutter_rust_bridge v1.80. The bridge generates Dart bindings from Rust function signatures. Key bridge modules:
flutter_ffi.rs: Session management, connection lifecycle, event streamingflutter.rs: State models, peer management, async task schedulingflutter/lib/models/: Dart-side models for peers, state, address book, inputThe Flutter UI supports desktop (Windows/macOS/Linux), mobile (Android/iOS), and web.
Rather than scattering #[cfg(target_os = ...)] throughout the codebase, platform-specific functionality is extracted into dedicated crates:
scrap โ screen capture (one trait, per-platform implementations)enigo โ keyboard/mouse controlclipboard โ clipboard read/writesrc/platform/ โ higher-level platform glue (service management, display control, window management)This is clean but has costs: scrap and enigo are RustDesk forks (not upstream), maintained as git dependencies in Cargo.toml. Several dependencies are pinned to RustDesk-org forks (parity-tokio-ipc, magnum-opus, rdev, cpal, arboard, clipboard-master, portable-pty, etc.), creating a maintenance burden.
Race-all-the-things connection strategy: Instead of trying TCP first and falling back, RustDesk races TCP, UDP, IPv6, and relay simultaneously. This minimizes connection time at the cost of network overhead.
Protobuf everywhere: All network messages use Protocol Buffers. This provides cross-version compatibility (new fields default to empty) and language-agnostic serialization (the Dart side can parse messages too).
Dual UI โ Sciter deprecated, Flutter current: The original UI was Sciter (a lightweight HTML/CSS engine). The project migrated to Flutter for better cross-platform support (mobile, web), but Sciter code remains in src/ui/ (deprecated) and can still be compiled.
Self-hostable by design: The rendezvous/relay servers are a separate open-source project (rustdesk-server). Users can run their own infrastructure. The client has no hard dependency on the public servers.
Plugin framework as opt-in feature: The plugin system is behind a compile-time feature flag. This prevents accidental plugin loading and keeps the core binary smaller for users who don't need it.
Size-optimized release builds: The project prioritizes binary size over compilation speed, with aggressive LTO and symbol stripping.
The audio buffer's statistical shrink algorithm (client.rs:1231-1291): Rather than a simple fixed-size ring buffer, the audio buffer tracks occupancy levels over 12-second windows in 30 buckets, identifies the "safe water mark" (longest consecutive near-empty period), and drops samples at a rate of min(zero, max/N) of the buffer capacity per adjustment. This is a sophisticated jitter-compensation strategy that avoids both underruns and excessive latency.
The restart grace window (client.rs:100): A 5-minute grace period where restarting_remote_device tracking prevents false reconnections during remote reboots. On Windows, the peer may briefly reconnect before the actual reboot disconnect, and this grace window prevents treating that as a failed reconnection.
The "deploy" backoff (rendezvous_mediator.rs:70-79): When a device hasn't been deployed to the server yet, registration attempts are throttled to once every 30 seconds via deploy_register_throttled(). This prevents tight-loop reconnection storms when the device is awaiting operator deployment.
The clipboard listener unsubscribe mechanism (client.rs:950-952): Clipboard monitoring uses a named subscription model ("client-clipboard") with reference counting. Only when all Flutter sessions disconnect does the clipboard thread actually stop.
The display connection tracking (video_service.rs:76): A global DISPLAY_CONN_IDS map tracks which connections are subscribed to which displays. This allows targeted notifications when frames arrive, rather than broadcasting to all connections.
vs TeamViewer: Similar rendezvous/relay architecture, but RustDesk is fully open-source and self-hostable. TeamViewer uses proprietary protocols; RustDesk uses documented protobuf messages. TeamViewer's NAT traversal is more battle-tested (they've been doing this for 20+ years), but RustDesk's approach is architecturally equivalent.
vs AnyDesk: AnyDesk uses a custom DeskRT video codec optimized for low latency. RustDesk uses standard codecs (H264/H265/VP8/VP9/AV1) with hardware acceleration. AnyDesk's codec is more bandwidth-efficient for text-heavy screens; RustDesk trades some efficiency for codec compatibility.
vs Sunshine/Moonlight: Sunshine/Moonlight are optimized for game streaming (ultra-low latency, high FPS) using NVIDIA/AMD hardware encoders. RustDesk targets general remote desktop use with broader codec and platform support.
vs VNC/RDP: VNC is pixel-based (no codec intelligence), RDP is Windows-centric. RustDesk provides codec-aware streaming with cross-platform support and NAT traversal that neither VNC nor RDP offer.