Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何限制Node.JS中每个ip的请求量?_Node.js - Fatal编程技术网

如何限制Node.JS中每个ip的请求量?

如何限制Node.JS中每个ip的请求量?,node.js,Node.js,我一直在想一种方法,如果我遭到DDOS攻击,可以帮助最小化对node.js应用程序的破坏。我想限制每个IP的请求。我想把每个IP地址限制在每秒这么多请求。例如:没有IP地址可以每3秒超过10个请求 到目前为止,我已经得出了以下结论: http.createServer(req, res, function() { if(req.connection.remoteAddress ?????? ) { block ip for 15 mins } } 我认为

我一直在想一种方法,如果我遭到DDOS攻击,可以帮助最小化对node.js应用程序的破坏。我想限制每个IP的请求。我想把每个IP地址限制在每秒这么多请求。例如:没有IP地址可以每3秒超过10个请求

到目前为止,我已经得出了以下结论:

 http.createServer(req, res, function() {
     if(req.connection.remoteAddress ?????? ) {
        block ip for 15 mins
      }
}

我认为这不应该在http服务器级别上完成。基本上,它不会阻止用户访问您的服务器,即使他们在15分钟内看不到任何东西

在我看来,你应该在你的系统中使用防火墙来处理这个问题。虽然这更像是一场关于or的讨论,但让我给你们一些建议

  • 使用iptables在您的入口点(您的服务器或您可以访问的任何其他服务器)上设置防火墙。iptables允许您设置每个IP的最大连接数限制。不过,如果你没有网络背景,学习曲线相当陡峭。这是传统的方式

    这里有一个面向初学者的好资源:

    和你在这里需要的东西类似:

  • 我最近遇到了一个非常好的软件包,名为it碰巧有一个选项来限制每个IP的连接速率,它可以在几分钟内安装好。对于更复杂的东西,您仍然需要iptables

    总之,正如我所说

    让您的应用程序服务器做他们最擅长的事情。。。运行应用程序

    让防火墙做他们最擅长的事情,从你的服务器上清除不需要的IP


  • 如果您想自己在应用服务器级别构建此应用程序,则必须构建一个数据结构,记录来自特定IP地址的每次最近访问,以便在新请求到达时,您可以回顾历史,查看它是否执行了太多请求。如果是,请拒绝提供任何进一步的数据。而且,为了防止这些数据堆积在服务器中,还需要一些清除旧访问数据的代码

    下面是一个实现这一点的方法(未经测试的代码来说明该方法):

    函数访问记录器(n、t、阻塞时间){
    该数量=n;
    这个时间=t;
    this.blockTime=blockTime;
    this.requests={};
    //定期安排清理(每30分钟一次)
    this.interval=setInterval(this.age.bind(this),30*60*1000);
    }
    AccessLogger.prototype={
    检查:功能(ip){
    var信息、访问时间、现在、限制、cnt;
    //添加此访问权限
    本条增补(ip);
    //应该始终是一个信息在这里,因为我们刚刚添加了它
    info=此。请求[ip];
    accessTimes=info.accessTimes;
    //计算时限
    now=Date.now();
    极限=现在-这个时间;
    //如果已阻塞此ip,则短路
    如果(info.blockUntil>=现在){
    返回false;
    }
    //短路一个甚至还没有最大数量访问的访问
    if(accessTimes.length<此数量){
    返回true;
    }
    cnt=0;
    对于(var i=accessTimes.length-1;i>=0;i--){
    if(访问次数[i]>限制){
    ++碳纳米管;
    }否则{
    //假设CNT按时间顺序排列,因此无需再查看
    打破
    }
    }
    如果(cnt>此数量){
    //阻止从现在到现在+此.blockTime
    info.blocktill=now+this.blockTime;
    返回false;
    }否则{
    返回true;
    }
    },
    添加:功能(ip){
    var info=this.requests[ip];
    如果(!info){
    info={accessTimes:[],blockUntil:0};
    此。请求[ip]=信息;
    }
    //将此访问时间推入此IP的访问阵列
    info.accessTimes.push[Date.now()];
    },
    年龄:函数(){
    //清除在此时间内未出现且当前未被阻止的所有访问
    var ip,info,accessTimes,now=Date.now(),limit=now-this.time,index;
    for(此.requests中的ip){
    if(this.requests.hasOwnProperty(ip)){
    info=此。请求[ip];
    accessTimes=info.accessTimes;
    //如果当前没有阻止这个
    如果(info.blockUntil<现在){
    //如果最新访问时间早于时间限制,则对整个项目进行核爆
    如果(!accessTimes.length | | accessTimes[accessTimes.length-1]<限制){
    删除此。请求[ip];
    }否则{
    //如果一个ip经常访问,那么它最近的访问永远不会过时
    //我们必须使较旧的访问时间变长,以防止它们受到影响
    //永远积累
    if(accessTimes.length>(this.qty*2)和&accessTimes[0]<限制){
    指数=0;
    对于(var i=1;i
    这种方法是可行的
    function AccessLogger(n, t, blockTime) {
        this.qty = n;
        this.time = t;
        this.blockTime = blockTime;
        this.requests = {};
        // schedule cleanup on a regular interval (every 30 minutes)
        this.interval = setInterval(this.age.bind(this), 30 * 60 * 1000);
    }
    
    AccessLogger.prototype = {
        check: function(ip) {
            var info, accessTimes, now, limit, cnt;
    
            // add this access
            this.add(ip);
    
            // should always be an info here because we just added it
            info = this.requests[ip];
            accessTimes = info.accessTimes;
    
            // calc time limits
            now = Date.now();
            limit = now - this.time;
    
            // short circuit if already blocking this ip
            if (info.blockUntil >= now) {
                return false;
            }
    
            // short circuit an access that has not even had max qty accesses yet
            if (accessTimes.length < this.qty) {
                return true;
            }
            cnt = 0;
            for (var i = accessTimes.length - 1; i >= 0; i--) {
                if (accessTimes[i] > limit) {
                    ++cnt;
                } else {
                    // assumes cnts are in time order so no need to look any more
                    break;
                }
            }
            if (cnt > this.qty) {
                // block from now until now + this.blockTime
                info.blockUntil = now + this.blockTime;
                return false;
            } else {
                return true;
            }
    
        },
        add: function(ip) {
            var info = this.requests[ip];
            if (!info) {
                info = {accessTimes: [], blockUntil: 0};
                this.requests[ip] = info;
            }
            // push this access time into the access array for this IP
            info.accessTimes.push[Date.now()];
        },
        age: function() {
            // clean up any accesses that have not been here within this.time and are not currently blocked
            var ip, info, accessTimes, now = Date.now(), limit = now - this.time, index;
            for (ip in this.requests) {
                if (this.requests.hasOwnProperty(ip)) {
                    info = this.requests[ip];
                    accessTimes = info.accessTimes;
                    // if not currently blocking this one
                    if (info.blockUntil < now) {
                        // if newest access is older than time limit, then nuke the whole item
                        if (!accessTimes.length || accessTimes[accessTimes.length - 1] < limit) {
                            delete this.requests[ip];
                        } else {
                            // in case an ip is regularly visiting so its recent access is never old
                            // we must age out older access times to keep them from 
                            // accumulating forever
                            if (accessTimes.length > (this.qty * 2) && accessTimes[0] < limit) {
                                index = 0;
                                for (var i = 1; i < accessTimes.length; i++) {
                                    if (accessTimes[i] < limit) {
                                        index = i;
                                    } else {
                                        break;
                                    }
                                }
                                // remove index + 1 old access times from the front of the array
                                accessTimes.splice(0, index + 1);
                            }
                        }
                    }
                }
            }
        }
    };
    
    var accesses = new AccessLogger(10, 3000, 15000);
    
    // put this as one of the first middleware so it acts 
    // before other middleware spends time processing the request
    app.use(function(req, res, next) {
        if (!accesses.check(req.connection.remoteAddress)) {
            // cancel the request here
            res.end("No data for you!");
        } else {
            next();
        }
    });
    
    npm i limiting-middleware
    
    const LimitingMiddleware = require('limiting-middleware');
    app.use(new LimitingMiddleware({ limit: 100, resetInterval: 1200000 }).limitByIp());
    // 100 request limit. 1200000ms reset interval (20m).