Proxy RDP-Connection, no RDP_COOKIE available?

Hello,
I am new to HAProxy and the Linux world. I would like to use HAProxy to route RDP connections. The routing should be based on the RDP cookie. But first, it should basically work. It is no problem to accept the connection and simply forward it. This configuration work, but RDP_COOKIE is always empty.

frontend rdp443
bind *:443
mode tcp
tcp-request inspect-delay 5s

tcp-request content accept
default_backend gw

backend gw
mode tcp
server tsplus 192.168.100.10:443

No matter what I do, RDP_COOKIE is always empty. This causes the connection to be interrupted.

tcp-request content reject if !RDP_COOKIE

No cookie.

tcp-request content set-var(txn.cnt) req.rdp_cookie_cnt

log-format “RDP %ci:%cp cookie=%[var(txn.cnt)]”

I checked with Wireshark, and the client sends the cookie.

I asked the AI, and it says that Ubuntu 24.04 has HAProxy without an RDP parser in its repository. Is that possible?

I am at a loss.

I think your content accept rule is missing the IF RDP_COOKIE bit…?

A full config snipet would be:

option tcpka
tcp-request inspect-delay 5s
tcp-request content accept if RDP_COOKIE
tcp-request content reject if { req_ssl_hello_type 1 }
stick-table type string size 10240k expire 12h peers loadbalancer_replication
stick on rdp_cookie(mstshash) upper
timeout client 12h
timeout server 12h

https://www.loadbalancer.org/blog/load-balancing-windows-terminal-server-haproxy-and-rdp-cookies/

But hang on why are you on port 443? Is the backend an RDP Gateway? Rather than RDP Session Host Server 3389?
If so you won’t be able to read the cookies because you are outside the gateway?
https://pdfs.loadbalancer.org/Microsoft_Remote_Desktop_Services_Deployment_Guide.pdf

Hello,

Sorry for the late reply. I use TSPlus. TSPlus accepts HTTPS and RDP connections simultaneously on port 443. I probably don’t understand HAProxy yet.

That won’t work. Not quite, the connection itself works, but the cookie should contain the name of the server to which the connection is to be made. However, the cookie is empty.

tcp-request inspect-delay 5s

tcp-request content set-var(txn.cnt) req.rdp_cookie_cnt

tcp-request content accept

log-format “RDP %ci:%cp cookie=%[var(txn.cnt)]”

default_backend gw

Does that mean I definitely need a wait condition? As in your example.

tcp-request content accept if RDP_COOKIE

Does that mean I accept the connection too early, when no data has been transferred yet?

I don’t understand something. When I try to log req.payload(0.512), it is also empty.

I can’t try it right now. Do I also need a condition for set-var? Like this:

tcp-request inspect-delay 5s
acl have_bytes req.len gt 0
tcp-request content set-var(sess.raw) req.payload(0,1024) if have_bytes
tcp-request content accept if RDP_COOKIE || have_bytes
log-format “RAW=%[var(sess.raw),hex,ifempty:NA] len=%[req.len]”

I continue my research.

Thank you very much.

Hello,

I think the problem is solved. There is no RDP cookie in TSPlus or HAProxy does not parse it because it is not the usual mstshash. But that’s not a problem because you can also check the payload directly. Then you have to keep two things in mind.

  1. You definitely need a wait condition. Something like
    if WAIT_END
    if req.len ge XY
    otherwise you check even though no data is available yet.
  2. You must not try to read more than the data in the buffer with req.payload(0, XYZ). Then there is no return value. So either req.payload(0,0), which simply reads to the end, or a size that is definitely available.

Hi lnxrookie,

I’m trying to do the same with HAProxy and TSPlus. Didi you succeed in finding a working configuration?

Regards,

Pascal