我怎么能涉及一些验证之前代理到一个websocket服务器与http代理中间件?



我可能做错了。

目标:通过apache接收https连接,并在将其路由到websocket服务器之前进行一些验证。如果无效则返回403状态码,如果有效则继续进行websocket连接。

我决定尝试涉及节点代理,基于http-proxy-middleware。在apache中,我有一个虚拟主机条目,其中包括:

<Location /testws>
ProxyPass        ws://127.0.0.1:6006/testws
ProxyPassReverse        ws://127.0.0.1:6006/testws
</Location>

我在端口6006上运行的节点代理是:

const express = require('express');
const { createProxyMiddleware, responseInterceptor } = require('http-proxy-middleware');
const app = express();
// proxy middleware options
const wsProxyOptions = {
target: 'http://example.org', // target host
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
router: {
// when request.headers.host == 'dev.localhost:3000',
// override target 'http://www.example.org' to 'http://localhost:8000'
// 'dev.localhost:3000': 'http://localhost:8000',
'/testws': 'ws://127.0.0.1:6082',  //my websocket server is running on port 6082
},
selfHandleResponse: true,
onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
res.statusCode = 418; // set different response status code
const response = responseBuffer.toString('utf8');
return response.replace('Example ', 'NewText');
}),
logLevel: 'debug'
};
// The setup below is recommended for external websocket upgrades
// https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade
const wsProxy = createProxyMiddleware(wsProxyOptions);
app.use(wsProxy);
const server = app.listen(6006);
server.on('upgrade', wsProxy.upgrade); // optional: upgrade externally

当我使用该设置时,我从浏览器转到https://server.ip/testws。我被路由到我的websocket服务器如预期。然而,onProxyRes(responseInterceptor)永远不会被访问。我还尝试了其他事件选项,如onProxyReq和onProxyReqWs。他们也不会被击中。

接下来,我尝试改变ProxyPass和ProxyPassReverse设置在我的apache设置转到http://127.0.0.1:6006/testws而不是ws://127.0.0.1:6006/testws。现在,onProxyReq确实被访问了,但是我从我的websocket服务器得到一个响应说&;Upgrade required &;,这可能是有意义的,因为升级还没有发生。这里的网络有可能升级吗?如果有,怎么做?

我一直在尝试的另一件事是为路由器选项添加异步函数。这对我来说可以确定新的目标应该是什么,但是似乎没有一种方法可以从那里涉及状态码,因为它只是想要返回一个目标值。

我想尝试responseInterceptor的原因是因为我想在连接到我的websocket服务器之前做一些验证,如果验证失败,返回一个状态码403,而不是继续与websocket连接。对此有什么想法吗?或者,这对我想做的事情来说是错误的方法吗?

更新:我想这是有道理的,onProxyRes不会是我需要的,因为升级可能发生在那之前。我仍然不确定为什么onProxyReq选项不起作用。不管怎样,我开始看:

server.on('upgrade', wsProxy.upgrade);

如果验证失败,我是否能够以某种方式响应状态码?例如:

server.on('upgrade', (req, socket, head) => {
if (valid) {
wsProxy.upgrade(req, socket, head);
} else {
//somehow return status 403
}
});

看起来这篇文章问的是同样的问题,但更清楚:

拦截(并可能拒绝)web套接字升级请求

我不确定是否有更合适的解决方案,但到目前为止,上面提到的那个似乎对我有效。它基本上展示了如何在升级时使用http状态码进行响应:

server.on('upgrade', (req, socket, head) => {
if (validationPasses) {
wsProxy.upgrade(req, socket, head);
} else {
socket.write('HTTP/1.1 403 Access Deniedrn' +
'Upgrade: WebSocketrn' +
'Connection: Upgradern' +
'rn');
socket.destroy();
return;
}
});

最新更新