How to route different domains to TCP and WebSocket backends using a single HAProxy port?

I would like to configure HAProxy to handle multiple domains on a single listening port and route traffic to different backend services based on the requested domain name.

Here is my scenario:

  • I have two different domains (for example: domain1.com and domain2.com)

  • HAProxy listens on a single port (e.g., 443 or a custom port)

  • Depending on the domain name (Host / SNI), traffic should be forwarded to different backends

  • The backends may use different protocols:

    • One backend may use plain TCP

    • Another backend may use WebSocket (possibly over HTTP/HTTPS)

My questions are:

  1. Is it possible to handle both TCP and WebSocket routing on the same HAProxy frontend?

  2. Should I use TCP mode or HTTP mode in this case?

  3. What is the recommended way to distinguish traffic by domain name? (e.g., SNI vs HTTP Host header)

  4. If mixing TCP and WebSocket is not recommended in a single frontend, what would be the best architecture?

Any configuration examples or best practices would be greatly appreciated.

Thank you very much!

Hi and Welcome,

Is one of the backends needing to be a TCP a requirement? I’m not sure I understand that well.
I can already tell you it’s possible, but we might need more info. It would also be nice to know what you’ve tried so far.

  1. yes
  2. Depends
  3. I’m not sure but I’d use SNI.
  4. if you need to handle both tcp and http (l4/l7) traffic. You’d route it through TCP first. Anything that listens directly for TCP can be done like this

acl direct_tcp req.ssl_sni -i yoururl.com
and to select the backend based on the acl
use_backend be_somebackend if direct_tcp

if you only have 2 backends, you can then use a default backend for all other traffic.

(I’m no expert btw, but I can share my experience).

Thanks for your reply!

Yes, having one backend use raw TCP is actually a requirement in my case. The backend service listens on both a TCP port and a WebSocket (HTTP/HTTPS) port at the same time.

What I’m trying to achieve is:

  • HAProxy listens on a single port (e.g. 443)

  • Based on the requested domain name:

    • domain1.com → forward to the TCP backend

    • domain2.com → forward to the WebSocket (HTTP) backend

From what I understand so far, a possible approach is to use TCP mode on the frontend and route based on SNI, something like:

frontend fe_main
    bind *:443 ssl crt /etc/haproxy/ssl/ accept-proxy
    mode tcp

    tcp-request inspect-delay 5s
    tcp-request content capture req.ssl_sni len 100

    tcp-request content accept if { req.ssl_hello_type 1 }

    acl is_tcp req.ssl_sni -i domain1.com
    acl is_ws  req.ssl_sni -i domain2.com

    use_backend be_tcp if is_tcp
    use_backend be_ws  if is_ws

    default_backend be_tcp

backend be_tcp
    mode tcp
    option tcpka
    option srvtcpka
    balance roundrobin
    server tcp 192.168.1.66:9090

backend be_ws
    mode http
    option http-server-close
    option forwardfor
    balance roundrobin
    server ws 192.168.1.66:9091

Then:

  • be_tcp would stay in TCP mode

  • be_ws could either stay in TCP mode (pass-through TLS) or switch to HTTP mode if TLS is terminated

Does this approach make sense?

Also, would you recommend:

  • keeping everything in TCP mode (TLS passthrough), or

  • terminating TLS in HAProxy and handling WebSocket in HTTP mode?

Thanks again for your help!

If the traffic is TLS with SNI in the TLS client_hello, then matching SNI and routing based on it will work.

If it isn’t, then it will not work, because there will be no SNI in the TLS client_hello that haproxy can actually match.

Unless you need specific HTTP features, I would suggest you keep it simple by keeping everyything in TCP mode.

Thank you for your reply. One of my services listens on a TCP port and a WebSocket port. HAProxy exposes only the listening port and uses multiple domains to distinguish between forwarding to the TCP or WebSocket service ports. I want to use this port for multiplexing and avoid maintaining multiple ports. It would be great if this could be achieved.