NodeJS 如何对socket.iohttp服务器上的/ www.example.com路由进行速率限制?

myzjeezk  于 2023-04-20  发布在  Node.js
关注(0)|答案(1)|浏览(98)

我正在使用socket.io并使用rate-limiter-flexiblelimiter来限制请求速率,但我注意到路由/socket.io没有从任何一个接收429,事实上,我无法使用app.use('/socket.io')..记录来自此路由的任何请求
我想socket.io正在对此路由进行一些处理,对吗?如果是这样,我如何确保在达到限制后,对/socket.io的请求也会收到429?
连接时的速率限制器:

this.io.on(this.SocketConstants.CONNECTION, async (client) => {
      this.client = client;
      try {
        await this.rateLimiter.consume(client.handshake.address);
      } catch (rejRes) {
        // On flood
        client.error('Too many requests');
        client.disconnect(true);
      }

http服务器上的速率限制器:

class RateLimiting {
    constructor() {
        this.limiter = new RateLimiter(2, 'minute', true);
        this.index = this.index.bind(this);
    }

    index(req,res,next){
        try {
            this.limiter.removeTokens(1, function(err, remainingRequests) {
                if (remainingRequests < 1) {
                    res.writeHead(429, {'Content-Type': 'text/plain;charset=UTF-8'});
                    res.end('429 Too Many Requests - your IP is being rate limited');
                    // res.status(429).json({ message: 'Too many requests' });
                } else {
                    next();
                }
            });
        }
        catch(err){
            console.log('Error', err);
        }
    }
}

编辑

对于任何有类似问题的人,我最终尝试了几种不同的方法来实现这一点,其中最简单的是:
1.编写自己的allowRequest
AllowRequest是一个通过/失败函数,可以用来覆盖默认的“checkRequest”函数(参考这里)

checkBucket(err, remainingRequests) {
    remainingRequests < 1 ? false : true;
  }

allowRequest(req, callback) {
    const limit = this.limiter.removeTokens(1, this.checkBucket);
    callback(limit ? null : 'Too many requests', limit);
  }

服务器启动为

this.io = this.socketServer(server, 
        { 
          allowRequest: this.allowRequest
        });

1.选择不同的路由,使用express添加所需的任何中间件并禁用默认路由
您可以通过将serveClient设置为false并将path设置为您需要的任何值来实现这一点。
this.io = this.socketServer(server,{ path:'/newSocketRoute',serveClient:});
这对我来说不太有效,所以我提供套接字文件的方式可能有问题,但它看起来是这样的:

app.get("/socket", this.limiter.initialize(), function(req, res) {
        if (0 === req.url.indexOf('/newSocketRoute/socket.io.js.map')) {
          res.sendFile(join(__dirname, "../../node_modules/socket.io-client/dist/socket.io.js.map"));
        } else if (0 === req.url.indexOf('/newSocketRoute/socket.io.js')) {
          res.sendFile(join(__dirname, "../../node_modules/socket.io-client/dist/socket.io.js"));
        }
      });
gudnpqoy

gudnpqoy1#

Socket.io 通过将自己作为第一个侦听器插入到request事件(此处引用socket.io代码)来将自己附加到您的http服务器,这意味着它完全绕过了任何Express中间件。
如果您试图对/socket.io/socket.io.js(客户端www.example.com代码)的请求进行速率限制socket.io,那么您可以使用自己的自定义路由器在Express中为该文件创建自己的路由,并使用不同的路径,让您的客户端只使用Express版本的路径,然后您可以禁用通过socket.io提供该文件(有一个选项可以禁用它)。
如果您试图对传入的www.example.com连接进行速率限制socket.io,则可能需要修改速率限制器,以便它可以参与socket.io连接事件。
现在我想起来了,您可以像www.example.com一样破解request事件侦听器列表socket.io(你可以看到上面引用的代码链接,了解它是如何做到的),你可以在它看到请求之前插入你自己的速率限制。的中间件,并切到行的前面,这样他们就可以在任何传入的http请求上获得第一个破解,并在其他人处理过的情况下隐藏它。你可以用你的速率限制器做同样的事情。然后,你会在一个“军备竞赛”,看谁先破解。就我个人而言,我可能只是挂接connect事件,并杀死那里的连接,如果速率限制规则被违反。但是,你可以黑客离开,并在socket.io代码前面。

相关问题