NodeJS 服务器-服务器安全通信



我在同一域上有两个使用 NodeJS 的服务器。(server1.example.com 和 server2.example.com)

我想以安全的方式将消息从一台服务器发送到另一台服务器。

现在,我正在使用通过发送HTTPS POST来发送消息,例如带有{secret:XXXXX,message:1234}https://example.com

有没有更清洁的方法可以做到这一点?如果是这样,需要采取哪些确切步骤? 注意:我在网站上有 SSL 证书。两台服务器位于同一域中。

我能想到一些选项,当然,这取决于您正在寻找的加密和安全性,如果HTTPS不足以满足特定通信的要求。(尽管如前所述,您确实有HTTPS。

  1. 您可以让发送服务器发出整个 JWT 路由。使用令牌发送信息并在另一端进行验证。确保令牌也具有较短的 TTL。(如果你真的想在这里破产,你可以开始实现OAuth2框架,尽管这可能完全是矫枉过正。

  2. 此外,您可以创建 Websocket HTTPS 服务器,并且仅接受特定传入端口上的信息中的信息。这将允许您使用 JWT 并通过端口访问进一步验证。您打开的端口将只允许接受来自特定 IP(即您的发送服务器)的数据包。

  3. 您可以通过加密整个消息(通过其中一个节点 NPM 模块或通过 Crypto)来添加另一个层,以便对消息和密钥进行哈希处理。

  4. 您还可以添加一个缓存层(Redis 或节点缓存模块),所有解密都将在其中完成以加快该过程。

  5. 尽管您必须制定实际时间表,但使用的另一个技巧是根据流程或不同的时间或您想要的任何时间表混合您使用的各种哈希例程。

  6. 最后,有时被忽视的选择是在接收计算机上安装防火墙,其中包含有关接收内容和从何处接收的非常具体的规则。(虽然这不是一个 Node 进程,可能需要一些时间才能正确处理。

以上都没有链接到Express或中间件。我假设如果您采用上述任何一种,您将在最终结果中需要一些 NPM 模块。

可能忘记了一些选择,但希望这有帮助。

只是为了添加到已经发布的其他解决方案中,您可以在两端使用证书,这样您就可以在TLS层而不是应用程序层进行身份验证,如果有帮助的话。

假设您在两台服务器上都使用 node,您可以像这样实现:

创建一个
  1. 自定义 CA,然后为每个服务器创建一个证书和一个私钥。
  2. 每个服务器可能具有如下代码:

    const tls = require('tls');
    function onMessage(socket, msg) {
    // `msg` is a parsed message received from `socket`
    }
    // Receive incoming messages
    tls.createServer({
    rejectUnauthorized: true,
    requestCert: true,
    ca: MY_CUSTOM_CA,
    cert: THIS_SERVER_CERT,
    key: THIS_SERVER_PRIVATE_KEY
    }, (socket) => {
    if (!socket.authorized)
    return socket.end(); // Certificate did not check out
    console.log('Connection accepted');
    // example protocol: newline-delimited JSON
    var jsonBuffer = '';
    socket.setEncoding('utf8');
    socket.on('data', (chunk) => {
    var chunks = chunk.split('n');
    var numComplete = chunks.length - 1;
    // Last line does not have trailing newline
    var incompleteChunk = chunks[numComplete];
    if (numComplete === 0) {
    jsonBuffer += incompleteChunk;
    return;
    }
    chunks[0] = jsonBuffer + chunks[0];
    for (var i = 0; i < numComplete; ++i) {
    try {
    onMessage(socket, JSON.parse(chunks[i]));
    } catch (ex) {}
    }
    jsonBuffer = incompleteChunk;
    });
    socket.on('end', () => {
    console.log('Connection ended');
    });
    }).listen(MY_PORT);
    // Send outgoing messages
    function sendMessages(host, port, msgs, cb) {
    if (!Array.isArray(msgs))
    msgs = [msgs];
    var req = tls.connect({
    host,
    port,
    rejectUnauthorized: true,
    ca: MY_CUSTOM_CA,
    cert: THIS_SERVER_CERT,
    key: THIS_SERVER_PRIVATE_KEY
    }, () => {
    if (!this.authorized)
    return this.end(); // Certificate did not check out
    for (var i = 0; i < msgs.length; ++i)
    this.write(JSON.stringify(msgs[i]) + 'n');
    this.end();
    }).once('error', onError).once('close', onClose);
    function onError(err) {
    req.removeListener('close', onClose);
    cb(err);
    }
    function onClose() {
    cb();
    }
    }
    
  3. onMessage()中添加传入消息处理,并使用sendMessages()发送传出消息。

您也可以始终保持单个套接字打开,而不是每组传出消息使用新连接,但这会涉及更多,因为您需要添加应用程序级保持连接机制等,但这肯定是可行的。

您可以通过HOSTORIGIN标头验证请求的主机来进一步强化安全性。

退房: https://stackoverflow.com/questions/18498726/how-do-i-get-the-domain-originating-the-request-in-express-js

从本质上讲,您将确保具有加密密钥的请求实际上来自特定服务器,而不仅仅是任何服务器。

最新更新