Microsoft Remote Desktop Services

Introduction

Note

Microsoft has changed many times the name of the product related to terminal services. Please read this technet article Terminal Services Is Now Remote Desktop Services

Remote Desktop Services, formerly Terminal Services, is a technology from Microsoft that allows users to access remotely to a session-based desktop, virtual machine-based desktop or applications hosted in a datacenter from their corporate network or from the internet.

Multiple RDS servers can be used in a farm. Hence we need to balance the load against them. To achieve this purpose, we have different ways:

  1. using a connection broker
  2. using a load-balancer with the connection broker
  3. using a load-balancer without the connection broker

Microsoft Terminal Services architecture are split in multiple components:

  1. RDP client (could be mstst.exe, rdsktop, xfreerdp, etc...)
  2. windows Terminal servers
  3. Connection brokers / Session Directory (optional) or a Load-Balancer
  4. Terminal Server Gateway (for external access)

3 main scenarios can be established to load-balance terminal services:

  1. RDS without connection broker
  2. Using a Connection broker
  3. Remote Desktop gateway

The connection broker, formerly Session broker, main purpose is to reconnect a user to his existing session. Since Windows 2008, the connection broker also have some load-balancing mechanism. HAProxy can provide this persistence feature as well, using stick-table.

So, why using a load-balancer if the connection broker can do load-balance? Answer is simple: security. Since the HAProxy is a Reverse-Proxy, it breaks the TCP connection between the client and the server. It can be deployed in DMZ to give access to users coming from internet to a RDS farm deployed in the VLAN dedicated to servers.

RDS without connection broker

It is possible to load-balance Terminal services without relying on a Connection broker component. In such case, we use the HAProxy to perform the persistence and session resumption, using the mstshash cookie, stored in a stick-table.

peers hapee
  peers hapee1 192.168.1.1:3389
  peers hapee2 192.168.1.2:3389

frontend ft_rdp
  mode tcp
  bind 192.168.13.128:3389 name rdp
  timeout client 1h
  log global
  option tcplog
  tcp-request inspect-delay 2s
  tcp-request content accept if RDP_COOKIE
  default_backend bk_rdp

backend bk_rdp
  mode tcp
  balance leastconn
  timeout server 1h
  timeout connect 4s
  log global
  option tcplog
  stick-table type string len 32 size 10k expire 8h peers hapee
  stick on rdp_cookie(mstshash)
  option tcp-check
  tcp-check connect port 3389 ssl
  default-server inter 3s rise 2 fall 3
  server srv01 192.168.13.13:3389 weight 10 check
  server srv02 192.168.13.14:3389 weight 10 check

It is possible to read the content from the stick table to know which user has been afected to which server.

hapee-lb-cmd <<<"show table bk_rdp"
# table: bk_rdp, type: string, size:10240, used:5
0x21c7eac: key=Administrator use=0 exp=83332288 server_id=1
0x21c7eac: key=test-001 use=0 exp=83332288 server_id=2

Note

RDP clients don’t behave the same way when sending mstshash cookie. Read below

Using a Connection broker

The configuration below should be used when the HAPEE is deployed in a Microsoft Terminal Services architecture where a Connection broker is used to dispatch sessions amongst TS servers.

Main purpose of Connection broker is to be able to reconnect a user to his disconnected session. All session information are stored in a database.

Note

it is possible (and recommended) to configure the connection brokers and the database in a high available way.

To install a Connection broker, follows the instructions provided on Microsoft Technet:

The configuration below

frontend ft_rdp
  mode tcp
  bind 192.168.13.128:3389 name rdp
  timeout client 1h
  log global
  option tcplog
  tcp-request inspect-delay 2s
  tcp-request content accept if RDP_COOKIE
  default_backend bk_rdp

backend bk_rdp
  mode tcp
  balance leastconn
  persist rdp-cookie
  timeout server 1h
  timeout connect 4s
  log global
  option tcplog
  option tcp-check
  tcp-check connect port 3389 ssl
  default-server inter 3s rise 2 fall 3
  server srv01 192.168.13.13:3389 weight 10 check
  server srv02 192.168.13.14:3389 weight 10 check

Remote Desktop gateway

HAProxy can be used to load-balance Remote Desktop Gateway. It’s an HTTPs based service one can Load-balance in two ways:

  • SSL bridging mode
  • SSL passthrough

SSL briding mode

In this mode, HAProxy decipher the traffic in the frontend and cipher it on the server connection:

frontend fe_rdp_tsc
 bind 192.168.13.128:443 name rdp_web ssl crt 2013.haproxylab.net
 mode http
 capture request header Host len 32
 log global
 option httplog
 timeout client 300s
 maxconn 1000
 acl path_rdweb path_beg -i /RDWeb/
 http-request redirect location /RDWeb/ if { path -i / /RDWeb }
 http-request deny unless path_rdweb
 default_backend be_rdp_tsc

backend be_rdp_tsc
 balance leastconn
 mode http
 log global
 option httplog
 timeout connect 4s
 timeout server 300s
 option httpchk GET /RDWeb
 cookie RDPWEB insert nocache
 default-server inter 3s    rise 2  fall 3
 server srv01 192.168.13.11:443 maxconn 1000 weight 10 ssl check cookie srv01
 server srv02 192.168.13.12:443 maxconn 1000 weight 10 ssl check cookie srv02

Note

In this mode, it is also possible to setup a configuration to protect against brute force.

SSL passthrough

In this mode, HAProxy establish a TCP connection between the client and the server and let them discuss together:

frontend fe_rdp_tsc
 bind 192.168.13.128:443 name rdp_web
 mode tcp
 log global
 option tcplog
 timeout client 300s
 maxconn 1000
 default_backend be_rdp_tsc

backend be_rdp_tsc
 balance source
 mode tcp
 log global
 option tcplog
 timeout connect 4s
 timeout server 300s
 option httpchk GET /RDWeb
 default-server inter 3s rise 2 fall 3
 server srv01 192.168.13.11:443 maxconn 1000 weight 10 check check-ssl
 server srv02 192.168.13.12:443 maxconn 1000 weight 10 check check-ssl