IronRDP: A Sans-I/O Rust RDP Stack for Clients, Servers, and Proxies
Rust implementation of the Microsoft Remote Desktop Protocol (RDP).
At a glance
- What is it?
- IronRDP is a modular Rust implementation of the Remote Desktop Protocol with a sans-I/O core. It targets client, server, and proxy builders who need protocol fidelity without being locked into a transport or runtime.
- Who is it for?
- Adopt IronRDP if you are building an RDP client, server, or proxy in Rust and need a protocol core that does not dictate your I/O model. It is also a strong fit for non-Rust targets through its WebAssembly and .NET bindings.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- Devolutions/IronRDP3,302 ★ · +211
| Repository | 2026-07-31 | 2026-11-13 |
|---|---|---|
| Devolutions/IronRDP | 3.1k | 3.3k |
211 Stars in the last 105 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The Problem IronRDP Solves
Implementing RDP from scratch is a large, error-prone task. The protocol spans connection negotiation, security layers, graphics codecs, and virtual channels. Most existing implementations are monolithic clients, which makes them hard to embed in a server or a proxy. IronRDP addresses this by splitting the protocol into composable crates, each handling a slice of the stack. The intended audience is not end users who want to click a remote desktop icon. It is developers building RDP-capable products: gateway vendors, browser-based access tools, automation agents, or custom servers. The README lists Devolutions Gateway, Cloudflare Access, Teleport, and several community servers as adopters, which confirms that the design targets integration rather than standalone use.
The Sans-I/O Core and What It Means
The central design choice is the sans-I/O core. The protocol state machines perform no I/O themselves. They accept bytes and produce bytes, leaving the transport to the caller. The README says the core is no_std-compatible and can be driven with blocking I/O, tokio, futures, or a custom event loop. This is a significant departure from typical RDP libraries that assume a socket. For a proxy or a gateway, this is a practical advantage: the same protocol logic can sit behind a TCP socket, a WebSocket, or a named pipe without modification. The trade-off is that you must write the I/O glue yourself. The examples show a blocking screenshot tool and a minimal server, but for production you need to integrate the state machines into your runtime. The documentation does not provide a ready-made async runtime adapter, so expect to build that layer.
Running the Prebuilt Binaries
Two binaries ship with each release: ironrdp-viewer and ironrdp-agent. The viewer is a windowed client with asynchronous I/O and software rendering. You run it with a hostname and credentials, or load a .rdp file. The command is straightforward: ironrdp-viewer <HOSTNAME> --username <USERNAME> --password <PASSWORD>. Omitted credentials are prompted interactively. The agent is a daemon-backed CLI for automation. It splits a long-lived daemon from short-lived commands. You start the daemon with ironrdp-agent daemon-start --overlay ./credentials.rdp, then connect with ironrdp-agent connect --server <HOSTNAME> --username <USER>. The connect command fails with missing required fields unless credentials are available, which is a deliberate safety measure to keep secrets out of the IPC caller's hands. Both binaries link native audio, so Linux builds require ALSA development headers and Windows builds require NASM. Prebuilt archives are checksummed and attached to each release, which simplifies deployment.
The Crate Layout and Feature Selection
As a library, IronRDP is a meta crate that re-exports standalone crates. The README shows a dependency on ironrdp with features like connector, session, and graphics. Each feature maps to a crate, so you can depend on ironrdp-pdu, ironrdp-connector, ironrdp-session directly. This modularity is the core of the project's design. You do not pull in the graphics stack if you only need a connection sequence. The feature list is broad: PDU codecs, connection and session state machines, virtual channels, and image codecs. The graphics side includes client-side decoding for raw bitmaps, Interleaved RLE, RDP 6.0 compression, and RemoteFX. Server-side encoding includes RDP 6.0, RemoteFX, and optional NSCodec, QOI, and QOI+zstd. Bulk compression covers MPPC, NCRUSH, and XCRUSH. The virtual channel list includes clipboard, audio, device redirection, and display control. This is a wide surface, and the README claims the core is continuously fuzzed. Still, the sheer number of codecs means you should verify which ones are fuzzed before relying on them in a security-sensitive context.
Security Features and Their Boundaries
The README emphasizes security first. Core crates are fuzzed, unsafe is heavily linted, and the workspace enforces strict correctness lints. The protocol support includes TLS 1.2 and 1.3, Network Level Authentication via CredSSP with NTLM and Kerberos, KDC proxy, and RDCleanPath for gateway-mediated connections. It also supports the Terminal Services Gateway transport. These are the mechanisms you need to connect to modern Windows hosts. The security posture is credible, but the README does not specify which fuzzing targets exist or how long they have run. Fuzzing is not a guarantee of correctness, and RDP has a history of subtle parsing bugs. For a production gateway, you should treat the fuzzing claim as a starting point, not a certification. The no_std compatibility of the core is a plus for embedded or minimal environments, but it also means the core excludes any I/O or platform-specific code, which you must supply.
Server-Side Support and Its Current Limits
IronRDP is not just a client. The README describes a server skeleton and an acceptor, and the example server binds to 127.0.0.1:3389. The server side includes encoding for RDP 6.0 and RemoteFX, and the list of adopters includes several server projects: Lamco RDP Server for Wayland, MacRDP for macOS, and qemu-rdp for QEMU displays. This shows that the server path is usable, but the README does not describe a full RDP server implementation. There is no mention of session management, multiple monitors, or advanced licensing beyond the connection sequence. The server example is minimal, and the agent is a client-side automation tool, not a server. If you need a complete RDP server with user management and session lifecycle, you will likely need to build a substantial layer on top of the crate. The acceptor and server skeleton are a foundation, not a finished product.
Bindings and Cross-Language Use
The protocol core also targets WebAssembly and .NET. The README mentions a protocol-agnostic web component called @devolutions/iron-remote-desktop and C#/.NET bindings generated with Diplomat, named Devolutions.IronRdp. This is a differentiator. Most RDP libraries are tied to a single language or platform. IronRDP's core is language-agnostic, so the same protocol logic can power a browser client and a .NET server. The Diplomat binding generation is a concrete mechanism: it produces C# APIs from the Rust code, which reduces the cost of maintaining two implementations. However, the README does not detail the maturity of these bindings. The .NET binding is listed as a feature, but there is no API documentation or example in the README. You should evaluate the bindings on their own merits before committing to them. The web component is also mentioned without specifics, so its feature set and limitations are unclear.
Alternatives and the Difference in Approach
The closest alternative is FreeRDP, a C-based RDP implementation with a long history. FreeRDP uses a traditional architecture where the library manages its own I/O and provides a client and server API. It is mature, widely deployed, and has extensive codec support. The difference is architectural: FreeRDP is not sans-I/O. You integrate it by calling its API, and it handles sockets and threads internally. IronRDP's sans-I/O core is a deliberate contrast. It gives you control over the transport, which is valuable for proxies and gateways that need to multiplex or tunnel connections. The trade-off is that you must write the I/O loop and integrate it with your runtime. FreeRDP also has a larger community and more production history. For a Rust-native project, IronRDP is the obvious choice, but for a C or C++ codebase, FreeRDP is more practical. The choice depends on whether you value control over the I/O layer or maturity of the overall stack.
Maintenance, Licensing, and Upgrade Considerations
IronRDP is licensed under Apache-2.0, which is permissive and suitable for commercial use. The repository is active, with recent releases for the viewer and agent in July 2026. The README does not specify a release cadence or a deprecation policy. The MSRV is defined as the oldest of three versions, but the README is truncated before listing them. You will need to check the repository for the current MSRV before adopting. The modular crate structure means upgrades can be incremental: you can update individual crates without touching the whole stack. However, the feature flags and crate names may change between versions, as the meta crate version 0.17 suggests. The README does not provide a migration guide for major version bumps. The fuzzing and linting practices are a positive sign for long-term maintenance, but the project is still young, and the API may shift. Budget time for keeping up with releases.
Editorial conclusion
Adopt IronRDP if you are building an RDP client, server, or proxy in Rust and need a protocol core that does not dictate your I/O model. It is also a strong fit for non-Rust targets through its WebAssembly and .NET bindings. Skip it if you want a turnkey client with a GUI or if you need production-grade server features like full session management, which are not yet complete. Before adopting, verify the current MSRV, confirm the fuzzing coverage for the specific codecs you plan to enable, and test interoperability against the exact Windows versions you must support, especially for NLA and RemoteFX.
Frequently asked questions
What is IronRDP and what kind of library is it?
It is a modular Rust implementation of the Remote Desktop Protocol, split into composable crates covering PDU codecs, connection and session state machines, virtual channels, and image codecs. Its core is Sans-I/O and no_std compatible: it performs no I/O, so the application supplies the transport and runtime and can use blocking I/O, an async runtime, or its own event loop.
Which binaries does IronRDP ship?
Two, each released under its own tag prefix. ironrdp-viewer is a portable windowed RDP client with asynchronous I/O and software rendering, and ironrdp-agent is a daemon-backed command line tool for scripts and language-model-driven automation. Both are at version 0.1.0, while the library the README asks you to depend on is at 0.17.
What do I need to install IronRDP with Cargo?
Two commands, cargo install ironrdp-viewer and cargo install ironrdp-agent. Both binaries link native audio, so Linux builds need the ALSA development headers, named as libasound2-dev on Debian and Ubuntu, and Windows builds need NASM. Checksummed archives per platform are also attached to each repository release.
Which graphics codecs does IronRDP support?
In both directions. Client-side decoding covers uncompressed raw bitmaps, Interleaved RLE, RDP 6.0 bitmap compression, and RemoteFX. Server-side encoding covers RDP 6.0 bitmap compression, RemoteFX, optional NSCodec, and optional QOI or QOI with zstd. Additional codec primitives ship as libraries, including ClearCodec, RemoteFX Progressive, ZGFX, and the graphics pipeline PDUs, and bulk compression covers MPPC, NCRUSH, and XCRUSH.
What does ironrdp-agent do and how are credentials handled?
It combines a long-lived daemon with short-lived command line invocations for scripts and automation. You can preload credentials when starting the daemon with an overlay file, which the README says keeps secrets away from the IPC caller, or pass a password to the connect command instead. A flag prints a machine-readable description of every operation, and the agent documentation covers the IPC format, secret handling, and remote execution support.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/devolutions-ironrdp)Star history chart for your README
[](https://hysenlabs.com/projects/devolutions-ironrdp)Was this useful?