【问题标题】:Prevent external users to connect websocket (wss)防止外部用户连接websocket(wss)
【发布时间】:2021-12-06 23:11:29
【问题描述】:

我正在https://example.com 建立一个 react-nodejs 网站,它使用 websocket(使用 socket.io 库),但现在人们只需 npm install socket.io-client 并连接使用这个到我的 websocket:

const {io} = require("socket.io-client");
const socket = io("wss://example.com");

现在他们可以发出/收听我的后端。目前,我使用 ReCAPTCHA 来防止机器人,所以你需要传递一个令牌来连接到 socket.io 服务器,我想知道是否有比这更好的解决方案。

【问题讨论】:

  • 当您的客户端连接到a时,socket.io会生成一个连接令牌。您可以将其存储在服务器端以发送和收听事件。通过使用令牌和用户ID在双方使用套接字连接

标签: node.js reactjs websocket socket.io


【解决方案1】:

您是对的,您无法阻止人们使用socket.io-client 使用自定义脚本手动连接到您的 socket.io 服务器。通常这是您以某种方式设计服务器的原因,即连接的客户端套接字不会造成任何伤害。客户端套接字通常在接收端。

当然,关于如何验证连接客户端的最佳实践,如果验证失败,则阻止连接。查看socket.io Documentation 关于client options。有一个auth 字段可用:

客户

import { io } from "socket.io-client";

const socket = io({
  auth: {
    token: "abcd"
  }
});

服务器

io.on("connection", (socket) => {
  console.log(socket.handshake.auth); // prints { token: "abcd" }
});

因此,一旦用户登录,使用 JWT(令牌)(假设您有 JWT 身份验证)并在建立连接期间传递它。然后在服务器端验证 JWT。

客户端证书认证

还有a more advanced 选项用于使用证书的客户端身份验证:

客户

const fs = require("fs");
const socket = require("socket.io-client")("https://example.com", {
  ca: fs.readFileSync("./server-cert.pem"),
  cert: fs.readFileSync("./client-cert.pem"),
  key: fs.readFileSync("./client-key.pem"),
});

服务器

const fs = require("fs");
const server = require("https").createServer({
  cert: fs.readFileSync("./server-cert.pem"),
  key: fs.readFileSync("./server-key.pem"),
  requestCert: true,
  ca: [
    fs.readFileSync('client-cert.pem')
  ]
});
const io = require("socket.io")(server);

【讨论】:

  • 对于 JWT,我相信它们存储在浏览器存储中(例如 localstorage),这意味着攻击者可以从浏览器中复制粘贴令牌并将其传递给连接 socket.io 服务器对吗?我会期待客户端证书认证。
  • 不一定需要存储在本地存储中。这取决于你。 JWT 通常存储在本地存储中,因此它们可以用于以后进行 API 调用。但是要验证 socket.io 连接,它只会被使用一次。您还可以将 JWT 的过期时间设置为几秒钟。之后 JWT 过期。这也意味着,攻击者需要访问用户浏览器。
  • 再一次,我总是会考虑这种情况,即某些用户可能会未经授权手动连接到您的 socket.io 服务器...... socket.io 是一个众所周知的库。所以即使这个人连接到你的服务器,它会造成什么危害?
  • 哦,所以在连接 socket.io 之前,客户端应该使用 REST API 或其他方式获取 JWT 令牌?但是攻击者也可以从外部获取令牌吗?或者如果有其他方法可以获取令牌,请告诉我:)。你可以说我的网站就像“agar.io”,在那里你可以收集积分并在排行榜上排名,我已经实现了一个钳位机制(只允许 50 分/秒),但让我很困扰的是人们只能 socket.emit ("x", { points: 50}) 而不是按预期获得分数。
  • 所以是的,通常使用 REST 端点获取 JWT ......但我想到的情况至少涉及密码和用户名。
猜你喜欢
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 2015-02-14
  • 2014-07-06
  • 2021-09-28
  • 2021-06-19
  • 2020-08-26
  • 1970-01-01
相关资源
最近更新 更多