lanoxx
lanoxx

Reputation: 13041

Angular CLI Proxy: Redirect unsecured local websocket to secured remote websocket

I am trying to establish an MQTT connection via Websockets over a reverse proxy. Is it possible to configure the Angular CLI proxy to forward requests to ws://localhost:4200/mqtt to wss://mqtt.example.com/mqtt?

I have been trying multiple configurations and can't seem to get it to work. Here is what I have in my proxy.conf.json:

"/mqtt/*": {
  "target": "wss://mqtt.example.com/",
  "secure": false,
  "ws": true,
  "changeOrigin": true,
  "logLevel": "debug"
}

I have tried various combinations, using secure and/or changeOrigin to either true or false and I am never able to connect.

Using "secure": false, "ws": true, "changeOrigin": true, or "secure": true, "ws": true, "changeOrigin": true, I always get:

Error during WebSocket handshake: Unexpected response code: 502

Update

I changed the proxy definition to omit the changeOrigin option and append /mqtt to the target:

"/mqtt": {
  "target": "wss://mqtt.example.com/mqtt",
  "secure": false,
  "ws": true,
  "logLevel": "debug"
},

Now get a different error message:

Error during WebSocket handshake: Unexpected response code: 404

My problem is that I cannot see the exact request that the Angular CLI is sending to the remote server, I have already set the logLevel to debug but that does not give any useful output to diagnose the problem. It would be very helpful to debug this if I could see the exact request that the proxy makes to the remote server.

Update 2

Its definitely not necessary to include /mqtt in the target, because then I end up with /mqtt/mqtt in the final request that the proxy makes.

Debugging this further I have discovered the following error message in my Kubernetes Ingress controller:

upstream prematurely closed connection while reading response header from upstream,

However, when I connect directly to the secure websocket using a local MQTT client (MqttBox) then the connection works, so I still think that its not a problem with the upstream configuration but something introduced in to the proxy connection.

Update 3

When I look at the mosquitto broker logs I keep seeing the following output:

1581786178: Socket error on client , disconnecting.

Also I am wondering if my problem might be caused because part of the connection goes via TLS, so the connection chain looks like this:

Browser/Client 
  -- WS/HTTP --> Angular CLI Proxy (localhost:4200) 
  -- WSS/HTTPS --> Ingress Controller (mqtt.example.com:443)
  -- WS/HTTP --> MQTT Broker (port 9001)

Inspecting traffic via tcpdump -vvvs 1500 - -i any port 9001 I was able to extract the following header:

GET /mqtt HTTP/1.1
Host: mqtt.example.com
Upgrade: websocket
Connection: upgrade
X-Request-ID: [...]
X-Real-IP: [...]
X-Forwarded-For: [...]
X-Forwarded-Host: [...]
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Original-URI: /mqtt
X-Scheme: https
sec-websocket-protocol: mqtt
sec-websocket-extensions: permessage-deflate; client_max_window_bits
sec-websocket-key: [...]
accept-language: en-US,en;q=0.9
accept-encoding: gzip, deflate, br
sec-websocket-version: 13
origin: chrome-extension://[...]
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36
cache-control: no-cache
pragma: no-cache

Update 4

I have investigated this further. When I disable TLS on the Kubernetes Ingress controller and the whole chain is communicating unsecured, then I have no problems and I can proxy the Websocket connection via the Angular CLI. However, as soon as I enable TLS then I run into the errors that I described above. So to sum up, the following three constellations work fine:

# whole chain unsecured (WORKS OK):
Browser/Client 
  -- WS/HTTP --> Angular CLI Proxy (localhost:4200) 
  -- WS/HTTP --> Ingress Controller (mqtt.example.com:443)
  -- WS/HTTP --> MQTT Broker (port 9001)

# wss to public eclipse mqtt broker (WORKS OK):
Browser/Client
  -- WS/HTTP --> Angular CLI Proxy (localhost:4200) 
  -- WSS/HTTPS --> MQTT Broker (mqtt.eclipse.org:443)

# secured connection directly from browser/client to broker (WORKS OK):
Browser/Client
  -- WSS/HTTPS --> Ingress Controller (mqtt.example.com:443)
  -- WS/HTTP --> MQTT Broker (port 9001)

Upvotes: 2

Views: 4165

Answers (1)

Brits
Brits

Reputation: 18245

This is possible; the following config works with the eclipse test server:

"/wss": {
    "target": "https://mqtt.eclipse.org:443/mqtt",
    "secure": false,
    "ws": true
},

note: Both https://mqtt.eclipse.org:443/mqtt and wss://mqtt.eclipse.org:443/mqtt work ok.

With that configuration I am able to connect (and subscribe/publish etc) using the Paho JS MQTT Client:

paho js mqtt client screenshot

I'm not sure what is wrong with your config but suspect that "target": "wss://mqtt.example.com/" should be "target": "wss://mqtt.example.com/mqtt" (but that might just be due to how you anonymised the data?). Hopefully trying it with the test server will point you in the right direction (I assume you have checked that the proxy works with a standard http page).

Upvotes: 2

Related Questions