Angular CLI 代理:将不安全的本地 websocket 重定向到安全的远程 websocket

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

我正在尝试通过反向代理通过 Websockets 建立 MQTT 连接。是否可以配置 Angular CLI 代理将请求转发到 ws://localhost:4200/mqttwss://mqtt.example.com/mqtt

我已经尝试了多次 configurations,但似乎无法正常工作。这是我的 proxy.conf.json:

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

我尝试了各种组合,使用 secure and/or changeOrigin 为真或假,但我永远无法连接。

使用 "secure": false, "ws": true, "changeOrigin": true,"secure": true, "ws": true, "changeOrigin": true, 我总是得到:

Error during WebSocket handshake: Unexpected response code: 502

更新

我更改了代理定义以省略 changeOrigin 选项并将 /mqtt 附加到目标:

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

现在得到不同的错误信息:

Error during WebSocket handshake: Unexpected response code: 404

我的问题是我看不到 Angular CLI 发送到远程服务器的确切请求,我已经将 logLevel 设置为 debug 但那没有提供任何有用的输出来诊断问题。如果我能看到代理对远程服务器发出的确切请求,那么调试它会非常有帮助。

更新 2

绝对没有必要在目标中包含 /mqtt,因为那样我在代理发出的最终请求中会得到 /mqtt/mqtt

进一步调试我在我的 Kubernetes Ingress 控制器中发现了以下错误消息:

upstream prematurely closed connection while reading response header from upstream,

但是,当我使用本地 MQTT 客户端 (MqttBox) 直接连接到安全 websocket 时,连接正常,所以我仍然认为这不是上游配置的问题,而是代理连接中引入的问题。

更新 3

当我查看 mosquitto 代理日志时,我不断看到以下输出:

1581786178: Socket error on client , disconnecting.

另外我想知道我的问题是否是由于部分连接通过 TLS 引起的,因此连接链如下所示:

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

通过 tcpdump -vvvs 1500 - -i any port 9001 检查流量我能够提取以下内容 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

更新 4

我对此进行了进一步调查。当我在 Kubernetes Ingress 控制器上禁用 TLS 并且整个链正在不安全地通信时,我没有问题,我可以通过 Angular CLI 代理 Websocket 连接。但是,一旦我启用 TLS,我就会 运行 进入我上面描述的错误。所以综上所述,以下三个星座比较适合:

# 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)

这是可能的;以下配置适用于 eclipse test server:

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

注意: https://mqtt.eclipse.org:443/mqttwss://mqtt.eclipse.org:443/mqtt 都可以。

通过该配置,我可以使用 Paho JS MQTT Client:

连接(和 subscribe/publish 等)

我不确定你的配置有什么问题,但怀疑 "target": "wss://mqtt.example.com/" 应该是 "target": "wss://mqtt.example.com/mqtt"(但这可能只是因为你如何匿名化数据?)。希望在测试服务器上尝试它会为您指明正确的方向(我假设您已经检查过代理是否适用于标准 http 页面)。