如何限制Node.JS中每个ip的请求量?
我一直在想一种方法,如果我遭到DDOS攻击,可以帮助最小化对node.js应用程序的破坏。我想限制每个IP的请求。我想把每个IP地址限制在每秒这么多请求。例如:没有IP地址可以每3秒超过10个请求 到目前为止,我已经得出了以下结论:如何限制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 } } 我认为
http.createServer(req, res, function() {
if(req.connection.remoteAddress ?????? ) {
block ip for 15 mins
}
}
我认为这不应该在http服务器级别上完成。基本上,它不会阻止用户访问您的服务器,即使他们在15分钟内看不到任何东西 在我看来,你应该在你的系统中使用防火墙来处理这个问题。虽然这更像是一场关于or的讨论,但让我给你们一些建议
如果您想自己在应用服务器级别构建此应用程序,则必须构建一个数据结构,记录来自特定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).