Can I load balance an RDP server farm?
Short answer
Yes, with an L7 TCP vService. Port 3389 is published in the frontend with the TCP protocol, RDP Cookie is selected in the LB Algorithm box in the Details panel, and mstshash is written in the RDP Cookie Name field. The RDP client sends the user name with this cookie at the start of the connection; TR7 routes the same user to the same Backend Service on every connection. Since RDP Cookie provides persistence itself, a separate Persistence is not selected. So that sessions that stay idle after the connection is established are not dropped, the Tunnel(Websocket) Timeout value (default 120 seconds) in the Timeouts profile is increased.
Problem: Why Must the RDP Session Return to the Same Server?
A remote desktop session stays open on the server the user connected to. If the user is routed to another server when the connection drops or when the user reconnects, the user cannot reach the open session and a new session is opened. In addition, an RDP connection can stay open for hours; while the user performs no action, the connection can time out while it waits idle.
Solution
L7 TCP vService and the RDP Cookie Algorithm
- How it works The RDP client writes the user name in the
mstshashcookie in the first packet of the connection; TR7 selects a server according to this value and always sends the same user to the same server. - Where it is opened vService → Details → LB Algorithm → RDP Cookie → RDP Cookie Name
- Requirement The frontend protocol being TCP (the TLS of RDP starts inside the RDP handshake; it is not terminated on TR7)
- vService type L7 TCP
- Backend Service side No change is required. By default, the servers see the connection as coming from the IP of TR7; if the client IP is needed in audit logs, SNAT → Use Client IP is used on the Backend Service.
Step-by-Step Configuration
The Load Balancer → Profiles → Health Checks → Add steps are followed (how to add).
Name is entered and TCP is selected as the Check Type (the default is HTTP; the type cannot be changed after saving).
The Add button at the bottom of the form is clicked.
The Load Balancer → Backend Services → Add steps are followed (How is a Backend Service added; which information is required?). This step and the next two steps are repeated for each RDP server.
Backend Service Name and Address (e.g. 192.0.2.50:3389) are entered; in the Health Check field, the profile created in steps 1–3 is selected. A Backend Service with no health check defined is always considered reachable.
The Add button at the bottom of the form is clicked.
The Load Balancer → Profiles → Timeouts → Add steps are followed (how to add).
Name is entered; in the Tunnel(Websocket) Timeout field, a value greater than the time users can stay idle is written in seconds (e.g. 28800; at most 60,000). In L7 TCP, this is the idle time that applies after the connection is established.
The Add button at the bottom of the form is clicked.
The Load Balancer → Load Balancer vService List → Add steps are followed; Name is entered and L7 TCP is selected as the Type.
In the Frontend row, the IP is selected, the port is set to 3389 and TCP in the Unencrypted group is selected as the Protocol (the new row comes with 80 / TCP). If the IP is not in the list, it is first added with Network → Interfaces → Actions → Add IP (Why can't I type the Frontend IP manually; what should I do to use an IP that is not in the list (e.g. IPv6) on a vService?).
The Backend Services added in steps 4–6 are selected in the Default Backend Services table.
The Details switch at the top right of the form is turned on; in the Algorithm field in the LB Algorithm box, RDP Cookie (with the Self-persistent note in the list) is selected. Since this algorithm provides persistence itself, the Persistence field is hidden.
The required RDP Cookie Name field comes empty; mstshash is written in the field.
In the Details panel, the Timeout box is checked and the profile created in steps 7–9 is selected.
The Save button is clicked. In a cluster setup, the change is also transferred to the peer device with the default auto-sync; if Manual Sync Mode is on, it is sent manually with Synchronize.
Verification
A connection is made with mstsc /v:203.0.113.40 by entering a user name, and the connection is closed and established again. On the vService Sessions screen of the vService, the Backend Service the connection went to is checked.
The same user goes to the same Backend Service on every connection and returns to the open sessionCommon Mistakes
- Writing the RDP Cookie Name field incorrectly. The field must be
mstshash; if another name is written, the cookie cannot be found. - Selecting TCP + TLS in the Frontend. Since the TLS of RDP starts inside the RDP handshake, it cannot be terminated on TR7; TCP is selected as the Protocol.
- Leaving the duration at the default. Tunnel(Websocket) Timeout is 120 seconds; RDP connections in which no data flows during this time are closed.
- Not assigning a health check. If there is no health check, an RDP server that goes down continues to receive connections.
How it is done in the documentation
