How to use Caddy reverse proxy MQTT connection based on wss protocol

I hope to use Caddy to reverse proxy a web front-end site. This front-end site uses the mqtt.js library to connect to the emqx instance of the server using the WSS protocol. The following configuration cannot connect. Is there any problem?

caddyfile reverse proxy configuration:

:17001 {
        tls /data/certs/cert.pem /data/certs/key.pem
        file_server {
                root /var/lib/adc/dist
        }
        handle /prod-api/api/* {
                respond "Not Found" 404 {
                        close
                }
        }
        handle_path /prod-api/* {
                reverse_proxy http://127.0.0.1:17000
        }
        handle_path /oss/* {
                file_server {
                        root /var/lib/adc/file
                }
        }
        handle /mqtt {
                reverse_proxy http://127.0.0.1:8083
        }
}

As you can see, I deployed an Https site on port 17001, which contains static pages and API parts. By default, the static pages will initiate an mqtt connection of the ws protocol to the /mqtt path.
When I initiate a wss-based mqtt connection like port 17001, the connection fails and the caddy log is as follows

{"level":"debug","ts":1732671595.6586242,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"127.0.0.1:8083","duration":0.000336022,"request":{"remote_ip":"10.127.150.57","remote_port":"56526","client_ip":"10.127.150.57","proto":"HTTP/1.1","method":"GET","host":"10.130.64.10:17001","uri":"/mqtt","headers":{"X-Forwarded-For":["10.127.150.57"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["10.130.64.10:17001"],"Sec-Websocket-Version":["13"],"Sec-Websocket-Key":["Q4b8yO+GkN8Wd39mfzziYA=="],"Connection":["Upgrade"],"User-Agent":[""],"Upgrade":["websocket"],"Sec-Websocket-Extensions":["permessage-deflate; client_max_window_bits"],"Sec-Websocket-Protocol":["mqtt"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","server_name":""}},"error":"dial tcp 127.0.0.1:8083: connect: connection refused"}
{"level":"error","ts":1732671595.6587446,"logger":"http.log.error","msg":"dial tcp 127.0.0.1:8083: connect: connection refused","request":{"remote_ip":"10.127.150.57","remote_port":"56526","client_ip":"10.127.150.57","proto":"HTTP/1.1","method":"GET","host":"10.130.64.10:17001","uri":"/mqtt","headers":{"Sec-Websocket-Version":["13"],"Sec-Websocket-Key":["Q4b8yO+GkN8Wd39mfzziYA=="],"Connection":["Upgrade"],"Upgrade":["websocket"],"Sec-Websocket-Extensions":["permessage-deflate; client_max_window_bits"],"Sec-Websocket-Protocol":["mqtt"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","server_name":""}},"duration":0.000561208,"status":502,"err_id":"fuy6gbsh0","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}

In addition, I use Docker to deploy emqx mqtt broker

version: '3.1'
networks:
  rms-network:
    external: true
services:
  emqx:
    container_name: emqx
    image: emqx/emqx:latest
    ports:
      - 1883:1883
      - 9001:8083
      - 8084:8084
      - 18083:18083
    volumes:
      - ./emqx.conf:/opt/emqx/etc/emqx.conf
      - ./log:/opt/emqx/log
      - ./data:/opt/emqx/data
    networks:
      - rms-network

Among them, 8083 is the ws connection port provided by emqx, and 8084 is the wss port.

Howdy @liang_li, welcome to the Caddy community.

There could be a problem, but I don’t really know enough about your setup to say. Certainly, having a look at your Caddyfile, nothing looks too crazy.

Can your websocket client connect directly to http://127.0.0.1:8083 without Caddy in the way?

If you wanna fill out the Help topic template so we’ve got a better picture of your setup we might be able to help you troubleshoot.

I found the key to the problem. According to Howdy, this configuration can indeed take effect. The fundamental reason why I can’t connect is that I use the Docker container to map emqx’s ws 8083 exposed port to the host’s 9001 port, so I can’t connect.