mm_os 2.1.8 → 2.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const {
|
|
3
|
+
exec
|
|
4
|
+
} = require('child_process');
|
|
5
|
+
const platform = os.platform();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 获取客户端IP
|
|
9
|
+
* @param {Object} req 请求对象
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
12
|
+
function getClientIP(req) {
|
|
13
|
+
return req.headers['x-forwarded-for'] || req.headers['X-Forwarded-For'] ||
|
|
14
|
+
req.connection.remoteAddress ||
|
|
15
|
+
req.socket.remoteAddress ||
|
|
16
|
+
req.connection.socket.remoteAddress;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 设置黑名单
|
|
21
|
+
* @param {String} ip IP地址
|
|
22
|
+
*/
|
|
23
|
+
function setting_blacklist(ip) {
|
|
24
|
+
var cmd;
|
|
25
|
+
if (platform == "win32") {
|
|
26
|
+
// window 系统
|
|
27
|
+
cmd = `netsh advfirewall firewall add rule name="Blacklist ${ip}" dir=in action=block remoteip="${ip}" protocol=any`
|
|
28
|
+
} else {
|
|
29
|
+
// linux 系统
|
|
30
|
+
cmd = `sudo iptables -A INPUT -s ${ip} -j DROP`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
exec(cmd, (error, stdout, stderr) => {
|
|
34
|
+
if (error) {
|
|
35
|
+
console.error(`执行的错误: ${error}`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
$.log.info(`加入黑名单: ${ip}`);
|
|
39
|
+
if (stderr) {
|
|
40
|
+
console.error(`标准错误输出: ${stderr}`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 应用
|
|
47
|
+
* @param {Object} server 服务
|
|
48
|
+
* @param {Object} config 配置参数
|
|
49
|
+
*/
|
|
50
|
+
module.exports = function(server, config) {
|
|
51
|
+
var limit = config.request_limit || 0;
|
|
52
|
+
var duration = config.request_duration || 0;
|
|
53
|
+
var block = config.request_block || false;
|
|
54
|
+
|
|
55
|
+
if (limit && duration) {
|
|
56
|
+
/* WAF(web防火墙) */
|
|
57
|
+
server.use(async (ctx, next) => {
|
|
58
|
+
var pass = true;
|
|
59
|
+
// 获取IP
|
|
60
|
+
var ip = getClientIP(ctx.req);
|
|
61
|
+
var num = 1;
|
|
62
|
+
var now = new Date();
|
|
63
|
+
var date = now.toStr('yyyy-MM-dd');
|
|
64
|
+
var time;
|
|
65
|
+
var str = await $.cache.get("ip_" + ip);
|
|
66
|
+
var json;
|
|
67
|
+
if (str) {
|
|
68
|
+
json = JSON.parse(str);
|
|
69
|
+
if (json.date !== date) {
|
|
70
|
+
num = 1;
|
|
71
|
+
} else {
|
|
72
|
+
// 判断时间间隔是否在范围外
|
|
73
|
+
if (json.time.toTime().interval(now) > duration) {
|
|
74
|
+
num = 1;
|
|
75
|
+
} else {
|
|
76
|
+
// 如果是在周期内,访问次数+1,并判断是否超出上限
|
|
77
|
+
num = json.num + 1;
|
|
78
|
+
if (num > limit) {
|
|
79
|
+
// 超出上限禁止访问,并加入黑名单
|
|
80
|
+
pass = false;
|
|
81
|
+
if (block) {
|
|
82
|
+
setting_blacklist(ip);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!time) {
|
|
89
|
+
time = now.toStr('yyyy-MM-dd hh:mm:ss');
|
|
90
|
+
}
|
|
91
|
+
if (pass) {
|
|
92
|
+
console.log(ip, num, time, json ? json : '');
|
|
93
|
+
await $.cache.set("ip_" + ip, JSON.stringify({
|
|
94
|
+
date,
|
|
95
|
+
time,
|
|
96
|
+
num
|
|
97
|
+
}), duration);
|
|
98
|
+
await next();
|
|
99
|
+
} else {
|
|
100
|
+
ctx.status = 429;
|
|
101
|
+
ctx.body = '请求频率过高,请稍后再试。';
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return server;
|
|
106
|
+
};
|