Skip to content

clintcan/macrdp

Repository files navigation

macrdp

Latest release License Ko-fi

A native RDP server for macOS, written in Rust on top of IronRDP. Connect from mstsc, Microsoft Remote Desktop, or FreeRDP to drive your Mac desktop with keyboard, mouse, real-cursor-shape forwarding, text + image clipboard sync, Mac↔Windows file copy, read-write drive redirection (mount the client's drives in Finder), smart-card redirection (use the client's smart card from macOS apps), system audio forwarding, and optional H.264 video (EGFX/AVC420, hardware-encoded). NLA/CredSSP is supported. Authenticates against your local Mac account via PAM.

This is the macOS equivalent of xrdp. Not a client, not a VNC bridge.

Status

v0 — daily-driver usable on a trusted LAN, and usable over the internet (VPN / ZeroTier / high-latency links, including mobile). Latest release: v0.9.0the webcam release: a webcam redirected from the client now presents as a real macOS camera. Turn on --enable-camera-redirection, tick Video capturing devices in the client, and "macrdp Camera" shows the client's live webcam in Photo Booth / Zoom / FaceTime / Teams. As far as is known the first open-source RDP server to present a client-redirected webcam as a native OS camera — and the path that actually works for mstsc, which routes webcams over MS-RDPECAM rather than raw USB. The pipeline is H.264 over the RDCamera channel → VideoToolbox decode → a CoreMediaIO Camera system extension, zero-copy via IOSurface; live-verified at 1080p/~30 fps with zero dropped frames. Opt-in and default OFF — the default runtime path is byte-identical when off (presenting the camera needs the signed/notarized build + a one-time extension activation; see docs/camera-extension-setup.md). Builds on v0.8.40 (the headless-laptop release), v0.8.39 (the smooth-resize release), and v0.8.38 (the Ctrl+Alt+Shift+R A/V resync hotkey).

Full per-release notes (what shipped, what was verified live, and the war stories): docs/release-history.md.

Production readiness

Short version: a polished v0 daily-driver for trusted LANs and your own VPN — not an enterprise RDP server. Use it to reach your own Mac over a network you control; don't put it on a public IP or treat it as multi-user/critical infrastructure.

Solid (verified on real mstsc / Microsoft Remote Desktop / FreeRDP): TLS + NLA/CredSSP auth against your Mac account (Keychain-backed, real CA certs supported, per-IP rate-limiting + lockout + audit log); the full daily workflow (display, input incl. non-US layouts, clipboard/files both ways, audio, drive + smart-card redirection, headless virtual displays); H.264 with congestion-responsive rate control that degrades gracefully instead of freezing; signed/notarized packaging with a LaunchAgent, menu-bar controller, and a health-check watchdog; 160+ tests in CI.

Know before relying on it: single session/single user; no multi-monitor or printer redirection; DRM video and password-manager windows capture black (macOS policy, not fixable); synthetic input can't reach the login window/secure fields (same); reconnecting mstsc can briefly show a blank screen (client quirk — the server now auto-heals it in ~4 s by reactivating the RDP core in place, no user action); the UDP paths are opt-in and newer than the TCP core; it's a solo v0 on vendored IronRDP forks, no SLA. Never expose any RDP server on a raw public IP — reach it over a VPN or RD Gateway.

Details and the path to closing the gaps: docs/production-readiness-roadmap.md.

Quick start

cargo build --release
codesign -s - --force target/release/macrdp   # ad-hoc sign so TCC grants persist
./target/release/macrdp

First run will prompt for:

  1. Screen Recording permission (System Settings → Privacy & Security → Screen Recording → enable macrdp → restart it).
  2. Accessibility permission (same path, "Accessibility" — required to forward keyboard and mouse).
  3. Your Mac password at the terminal — validated against your local account via PAM checkpw, then used as the RDP credential.

Then connect from a client to <your-mac-ip>:3390 with your Mac username and password. mstsc will prompt for credentials in its own NLA dialog — no need to pre-type the username.

Common flags to try next (full reference: docs/configuration.md):

./macrdp --enable-h264                      # H.264 video — crisper AND lighter than the default bitmaps
./macrdp --enable-h264 --adaptive-bitrate   # + congestion-responsive rate control (recommended off-LAN)
./macrdp --bind 0.0.0.0:3390                # accept LAN connections (keep it OFF public IPs)
./macrdp --virtual-display --width 2560 --height 1440   # headless second desktop; local screen untouched
./macrdp --map-ctrl-to-cmd                  # Windows Ctrl+C/V/X muscle memory drives macOS copy/paste

Hotkeys

macrdp reimplements the macOS symbolic hotkeys in user space (WindowServer won't fire them for forwarded events). On a Windows client the Cmd key is the Windows key, so press the Win-key equivalent:

Keys (on the client) Action
Cmd+Tab / Cmd+Shift+Tab Cycle apps (forward / back); the app you land on is surfaced
Cmd+` / Cmd+Shift+` Cycle windows of the current app
Cmd+Space Spotlight
Cmd+Shift+3 / 4 / 5 Screenshots (full screen / region / Screenshot.app)
Ctrl+Alt+G Gather windows stranded off the virtual display (headless --capture-primary/--detach-primary modes)
Ctrl+Alt+Shift+R On-demand A/V resync — repaint a stale/idle-blanked screen (forced keyframe) and re-sync drifted audio, without disconnecting. Handy for mstsc after hours idle.

Optional flags: --alt-tab-switch / --alt-backtick-switch accept Option+Tab / Option+` as the same triggers; --app-switcher-hud draws a visible switcher overlay; --map-ctrl-to-cmd remaps Windows Ctrl+C/V/X/… editing shortcuts to their Cmd equivalents.

mstsc tip: if Cmd+Tab seems ignored, set Local Resources → Keyboard → "Apply Windows key combinations" to "On the remote computer" (or go full-screen) — the windowed default eats Win+Tab locally as Task View.

Auto-start at login (launchd)

dist/install.sh

Builds + signs + installs to ~/.local/bin/macrdp, stores your Mac password in the macOS Keychain under service macrdp, drops a launchd plist at ~/Library/LaunchAgents/com.user.macrdp.plist, and loads it. macrdp will start on every login and restart if it crashes. Re-run the script after cargo build --release to refresh the installed binary.

launchctl print gui/$UID/com.user.macrdp | head    # status
launchctl kickstart -k gui/$UID/com.user.macrdp    # restart
launchctl bootout gui/$UID/com.user.macrdp         # stop / uninstall

Building the full app

dist/install.sh installs a bare binary. For a proper signed macrdp.app — stable bundle identity (TCC grants survive rebuilds), background-agent behavior, the embedded smart-card IFD handler, optional notarization, the menu-bar controller app, and a distributable DMG:

packaging/make-app.sh                                 # build + sign + install to /Applications
security add-generic-password -s macrdp -a "$(id -un)" -w 'YOUR_PASSWORD'
packaging/install-launchagent.sh                      # load LaunchAgent (label com.clintcan.macrdp)

Feature toggles, bind address, and extra flags live in ~/Library/Application Support/macrdp/config.env — outside the bundle, so edits never disturb the signature or TCC grants. The full packaging guide (Developer-ID signing, notarization, the DMG, the controller app, icons, TCC notes): packaging/README.md.

Release artifacts

Pushing a v* tag runs the release workflow, which builds on an Apple-Silicon runner and attaches these to a draft GitHub Release (Apple Silicon / aarch64-apple-darwin only):

File What it is
macrdp-<ver>-aarch64-apple-darwin.tar.gz the bare CLI binary + LICENSE/README
macrdp-<ver>-aarch64-apple-darwin-app.zip the full macrdp.app, with the embedded smart-card IFD handler + installer — the only artifact that carries everything --enable-smartcard-redirection needs
SHA256SUMS checksums for both

Both are ad-hoc signed, not notarized — open the app once via right-click → Open (or xattr -dr com.apple.quarantine macrdp.app). For a Developer-ID-signed + notarized build, or the menu-bar controller app (neither is produced in CI), build locally with packaging/make-app.sh.

Documentation

Guide What's in it
Configuration & CLI Every flag, the auth-hardening environment variables (rate-limit/lockout/audit), headless mode (--virtual-display, --detach-primary/--capture-primary), and a full set of example invocations.
Video The H.264/EGFX pipeline, Retina capture (--hidpi), client-resolution auto-adopt and letterboxing, bitrate/keyframe tuning, the mstsc reconnect-blank quirk and its in-place auto-recovery, and the vImage color-conversion benchmarks.
Audio RDPSND PCM, opt-in AAC compression (--enable-aac), the self-healing capture stream, and mute-on-minimize.
File copy Mac↔Windows clipboard file copy (files and folder trees), lazy vs eager paste, and the two Windows-side gotchas (Explorer folder-copy, archive shell extensions).
Drive redirection Mounting the client's drives as read-write Finder volumes (--enable-drive-redirection) — how the in-process NFS bridge works and what to expect from permissions.
Smart-card redirection Using the client's smart card from macOS apps (--enable-smartcard-redirection) — one-time IFD-handler install, the USB-trigger caveat, upgrade/reload notes, and why it's a user-space handler rather than USB passthrough.
Audit log & SIEM The security audit events (accept / reject / auth / disconnect) — every field and how to interpret them — plus forwarding the JSON stream to a SIEM/SOC collector (Vector / Fluent Bit / rsyslog) and a runnable OpenSearch SIEM tutorial that detects an RDP brute-force end-to-end.
Release history Per-release narrative of what shipped and what was live-verified.
CLAUDE.md Developer/agent reference — architecture, feature status, macOS gotchas, known quirks.

Why this was made

This was done to scratch an itch. There are practically no active open source RDP servers for macOS. The closest project with this functionality is xrdp; however it only runs on Linux/Unix machines and has no homebrew equivalent on Macs. The initial POC was done in a few hours with the help of Claude and ran pretty well from the start. Additional combing through pcap files and documentation, and debugging each mstsc/FreeRDP connect, is what makes this work tedious yet rewarding when it finally works. Multi-monitor support is on the list for when I'm bored or need a distraction from real life.

Support this project

macrdp is free and open source. If it's helped you out, you can buy me a coffee to help me get through the bumps — totally optional, no pressure.

License

Licensed under either of MIT or Apache-2.0 at your option. Being permissively licensed, a productized/notarized build may be sold commercially with support — that's selling the product, not a license exemption.

About

A native RDP server for macOS, written in Rust on top of IronRDP.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

17 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors