Teleport Blog - How we built a secure RDP client - Sep 8, 2023
How we built a secure RDP client
Today’s remote desktop protocol (RDP) clients don’t do enough to promote a strong security posture. They default to weak password-based authentication, leaving Windows infrastructure vulnerable to brute force attacks, and assume a direct connection to a well-known port is available. At Teleport we’re a bit bonkers about always trying to build the most secure solution, so we set out to do something different.
Design goals for a secure RDP client
There are a number of design goals we knew we wanted to achieve:
- We wanted to avoid exposing port 3389 on public networks.
- We wanted strong authentication - including integration with SSO, a strong second factor hardware key, and no passwords anywhere in the picture.
- We aimed to build as secure rdp client as we could:
- We would only use memory-safe programming languages, like Go or Rust.
- There should be strong isolation between the client and the rest of your system.
- The client should be easy to keep patched and up to date.
We knew that RDP was a large protocol and that implementing a full featured client from scratch would be a huge undertaking, so we evaluated FreeRDP, which is one of the most popular open source RDP implementations. We found it to be both mature and performant, and are aware of several open source and commercial remote desktop solutions that are powered by FreeRDP. We didn’t want to compromise on memory safety and were uncomfortable with pulling in many thousands of lines of unsafe C code.
We decided on a path forward:
- We would build our solution in Rust, a language known for its safety. The rdp-rs crate served as an excellent starting point.
- Our client would be as naive as possible, implementing only the smallest subset of the protocol necessary to provide remote desktop sessions. This would keep the surface area small and easier to comprehend, which is important for us to reason about its security.
- We would only provide remote desktop access via the web browser. Modern browsers are very good at staying patched automatically, they are already available on nearly every workstation, and they provide a strong sandbox that would isolate our client from the host machine. This is important, since remote desktop clients typically have access to tons of sensitive resources, including your system clipboard, storage, and even connected devices like cameras and microphones.
It looks like this:
This approach ensures that the RDP connection between the Teleport Desktop Service and the Windows hosts runs over a private local network and that RDP is not exposed to the internet. Removing the need to open up port 3389 on the firewall, or to set up a VPN. Multiple desktop services can sit in front of the same set of hosts for high availability, and separate desktop services can be deployed in hard-to-reach networks.
It hasn’t been easy, but we’ve delivered on most of the goals we set out to achieve. The biggest challenges we faced were: authenticating to the Windows host without passwords, lack of features and performance.
At Teleport, we’re not fans of passwords and prefer to use short-lived certificates wherever possible. Certificates have a built-in lifetime (TTL), significantly reducing the attack window if the credential is compromised. They’re also resistant to brute force attacks, and allow us to bake arbitrary metadata directly in the credential.
In order to support certificate-based authentication for any Windows server, there’s really only one option: smart cards.
Smart cards are physical devices similar to hardware security modules or U2F tokens - they store private keys and expose certificates and basic asymmetric cryptographic operations. In most cases, the credentials stored on the device are long-lived and unlocked by a PIN known only to the owner of the device.
When smart cards are used over RDP, a technology called device redirection makes a smart card appear connected to a remote machine by serializing hardware commands and sending them over a network connection. In most applications, RDP clients proxy these commands from a card reader that is attached to the client machine. This is where our approach is unique. We take advantage of the fact that we own the client and instead of sending back responses from a real hardware device, we emulate a virtual smart card. When there’s not a physical device to read a certificate from, we can issue a new certificate on demand for each and every session
While physical smart cards are a clear improvement over passwords, Teleport’s virtual smart cards are even more secure. The certificates that we generate are unique for each session, so there is no credential reuse. They are only valid for a small amount of time, rendering them useless shortly after the connection is established. Rather than relying on a user-configurable PIN (123456 anyone?), we are also able to generate a cryptographically secure, per-session PIN using the maximum number of allowed digits. Teleport automatically sends this pin in the RDP connection sequence and doesn’t share it with the user, so the smart card is not useful after the initial login, even for the user it was issued to. Teleport's in-built inventory of hosts and lack of passwords, makes the login UX simple. There are no more sticky notes with the IP address and passwords for systems.
By deliberately implementing a naive client and not leveraging a feature-packed solution like FreeRDP, our initial releases lacked initial support for a lot of features that people have come to expect from remote desktop solutions - bidirectional copy/paste, file sharing, etc. Our decision to use the web browser as the user-facing client meant that we don’t have access to system resources in the way that a native client would.
While this was a challenge, it forced us to evaluate each feature request carefully and to separate the must-have features that people have ingrained into their workflows from the features that people enjoy if they’re available but aren’t deal breakers. While there will always be some features that we won’t be able to support due to running in a web browser, we realized we could push the browser quite far. Teleport’s clipboard sharing is powered by the browser’s Clipboard API, and directory sharing allows you to mount a local directory with the File System Access API. To our knowledge, it’s the first browser-based remote desktop client to offer this functionality.
Performance is important for interactive workflows like remote desktop. Our approach has created a couple of challenges:
First, there are several network hops between the user and the Windows desktop. As a result, we require a low-latency connection from end-to-end. Performance issues related to network latency are often mitigated at the infrastructure level. For example, we run Teleport proxies worldwide for our cloud customers, ensuring that users are able to connect to a proxy that is geographically close to them. Similarly, our reverse tunneling architecture allows customers to deploy Teleport Windows Desktop Services very close to the target hosts, ensuring that the RDP connection happens over a fast local network.
Next, our RDP client implementation is deliberately naive, so it lacks support for many features that improve performance. For example, Teleport uses the RDP 6 bitmap codec and encodes screen segments as PNGs for transport. The RDP protocol has evolved, and there are now more advanced codecs that support bitmap caching and more efficient encoding and compression algorithms. Solving these problems is a tradeoff between keeping our client small and simple and implementing the full gamut of RDP options. To date, we’ve made significant improvements by optimizing our PNG encoding process (from Go’s default PNG encoding, to an optimized Go encoder, all the way to a Rust-based encoder). Our next foray into performance improvements involves a migration to IronRDP, which is a better RDP implementation that is actively maintained and supports the RemoteFX codec (a significant improvement over RDP6 bitmaps).
Instead of sticking with traditional password-based authentication, we're leading with passwordless authentication backed by short-lived credentials. Teleport's passwordless access works with Active Directory users as well as local Windows users, and is now available in Teleport Community Edition as well as Team and Enterprise.
Stay up-to-date with the newest Teleport releases by subscribing to our monthly updates.