Using reverse proxy with secured web sockets (WSS)

Hi, guys. I’m so sorry if those kind of topic were already discussed here, but I was not able to find any mentioning of using HAProxy as a reverse proxy for secured web sockets. Let me give an example to clarify what I’m talking about:
Let me say, that i have a site (example.com), one directory of which (example.com/test) should point to another site (helloworld.com), masking its content. So, when I open a page example.com/test I will see a helloworld.com page, but it still will be example.com/test in by browser’s address bar. This is what reverse proxy basically do.
Also, example.com has cloudflare CDN enabled (I’m not sure if this is important or not).

Now the main point. Let me say that I have a helloworld.com/socket page, that is used as endpoint of my websocket. When I’m opening helloworld.com some scripts are opening this websocket. Request URL from my browser looks like wss://helloworld.com/socket. And it is working pretty fine.
However, when I’m trying to open example.com/test I’m getting 403 error trying to open socket. And I can’t get any error on the server side.
Am I doing smth wrong? Pasting config below. Many thanks for any answer!

global
        debug
        log /dev/log    local0 debug
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /run/haproxy/admin.sock mode 660 level admin
        stats timeout 30s
        user haproxy
        group haproxy
        daemon
        ca-base /etc/ssl/certs
        crt-base /etc/ssl/private
        ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
        ssl-default-bind-options no-sslv3

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        option  http-server-close
        option  redispatch
        option  contstats
        timeout tunnel  3600
        timeout connect 5000
        timeout client  50000
        timeout server  50000
        errorfile 400 /etc/haproxy/errors/400.http
        errorfile 403 /etc/haproxy/errors/403.http
        errorfile 408 /etc/haproxy/errors/408.http
        errorfile 500 /etc/haproxy/errors/500.http
        errorfile 502 /etc/haproxy/errors/502.http
        errorfile 503 /etc/haproxy/errors/503.http
        errorfile 504 /etc/haproxy/errors/504.http

frontend def
        bind *:80
        mode http
        acl is_upgrade hdr(Connection) -i upgrade
        acl is_websocket hdr(Upgrade) -i websocket

        acl is_test path_beg /test
        use_backend test if is_test
        use_backend test_ws if is_websocket

backend test
        mode http
        acl is_test path_beg /test
        reqirep ^([^\ ].*)test[/]?(.*) \1\2 if is_test
        http-request set-header X-Forwarded-Host %[req.hdr(Host)]
        http-request set-header X-Client-IP %[src]
        http-request set-header Host helloworld.com
        cookie network insert
        server test helloworld.com:443 cookie core ssl verify none check

backend test_ws
        acl hdr_websocket_key      hdr_cnt(Sec-WebSocket-Key)      eq 1
        acl hdr_websocket_version  hdr_cnt(Sec-WebSocket-Version)  eq 1
        http-request deny if ! hdr_websocket_key ! hdr_websocket_version
        option forwardfor
        http-request set-header X-Client-IP %[src]
        http-request set-header X-Forwarded-Host %[req.hdr(Host)]
        http-request set-header Host helloworld.com
        cookie network insert
        server default helloworld.com:443 ssl verify none cookie core check
2 Likes

Heeey… Can anybody lend me a hand on this?

Okay. I was able to manage this issue myself.
I’ve added the following changes into my config:
http-request set-header Origin https://helloworld.com

Now i receive 101 code, just as expected.

Hi Arsenii, first of all, thanks for returning with the answer to your own question.
I am new to HAProxy and working with sockets in general. I have trouble hole-punching through the proxy to the endpoint that starts up the socket. The line of code you added, should it be under the frontend or backend label in the config? As of now, I am not even sure the problem is Origin related.

The setup:

Postman → Firewall (HaProxy) → Server
Between the client and Firewall the connection has SSL.
Between the Firewall and server there is no SSL

Is this set up even possible? I mean is it necessary for the socket (wss) to have SSL directly from client to server?