mm_os 3.3.0 → 3.3.1

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.
Files changed (42) hide show
  1. package/core/base/mqtt/index.js +1109 -1106
  2. package/core/base/web/index.js +245 -243
  3. package/core/com/event/README.md +4 -4
  4. package/core/com/event/com.json +3 -3
  5. package/core/com/event/config.tpl.json +18 -18
  6. package/core/com/event/drive.js +132 -132
  7. package/core/com/event/index.js +344 -344
  8. package/core/com/event/script.js +25 -25
  9. package/core/com/middleware/com.js +1 -0
  10. package/core/com/sql/drive.js +1 -1
  11. package/core/com/static/index.js +1 -1
  12. package/index.js +50 -31
  13. package/middleware/cors/index.js +119 -0
  14. package/middleware/cors/middleware.json +20 -0
  15. package/middleware/csrf/index.js +202 -0
  16. package/middleware/csrf/middleware.json +24 -0
  17. package/middleware/ip_firewall/index.js +476 -0
  18. package/middleware/ip_firewall/middleware.json +109 -0
  19. package/middleware/mqtt_base/middleware.json +2 -1
  20. package/middleware/security_audit/index.js +13 -19
  21. package/middleware/security_audit/middleware.json +3 -3
  22. package/middleware/waf/index.js +27 -32
  23. package/middleware/waf_ddos/index.js +2 -2
  24. package/middleware/waf_ddos/middleware.json +3 -3
  25. package/middleware/waf_xss/index.js +1 -1
  26. package/middleware/waf_xss/middleware.json +1 -1
  27. package/middleware/web_after/middleware.json +2 -1
  28. package/middleware/web_base/middleware.json +2 -1
  29. package/middleware/web_before/middleware.json +2 -1
  30. package/middleware/web_check/middleware.json +2 -1
  31. package/middleware/web_main/middleware.json +2 -1
  32. package/middleware/web_proxy/middleware.json +2 -1
  33. package/middleware/web_render/middleware.json +2 -1
  34. package/middleware/web_socket/middleware.json +2 -1
  35. package/middleware/web_static/middleware.json +2 -1
  36. package/package.json +13 -11
  37. package/middleware/performance/index.js +0 -151
  38. package/middleware/performance/middleware.json +0 -16
  39. package/middleware/security_headers/index.js +0 -487
  40. package/middleware/security_headers/middleware.json +0 -45
  41. package/middleware/waf_ip/index.js +0 -379
  42. package/middleware/waf_ip/middleware.json +0 -49
@@ -1,379 +0,0 @@
1
- const {
2
- exec
3
- } = require('child_process');
4
- const platform = require('os').platform();
5
-
6
- /**
7
- * 获取客户端IP
8
- * @param {Object} req 请求对象
9
- * @returns {String} 返回真实IP
10
- */
11
- function getClientIP(req) {
12
- var ip = req.headers['x-forwarded-for'] || req.headers['X-Forwarded-For'] || req.headers['x-real-ip'] ||
13
- req.connection.remoteAddress ||
14
- req.socket.remoteAddress ||
15
- req.connection.socket.remoteAddress;
16
- if (ip && ip.split(',').length > 0) {
17
- ip = ip.split(',')[0]; // 取第一个IP地址
18
- }
19
- // 处理IPv6本地地址
20
- if (ip === '::1' || ip === '::ffff:127.0.0.1') {
21
- ip = '127.0.0.1';
22
- }
23
- // 移除可能的端口号
24
- if (ip && ip.includes(':')) {
25
- ip = ip.split(':')[0];
26
- }
27
- return ip;
28
- };
29
-
30
- /**
31
- * 检查IP是否在白名单中
32
- * @param {String} ip IP地址
33
- * @param {Array} whitelist 白名单IP数组
34
- * @returns {Boolean} 是否在白名单中
35
- */
36
- function isInWhitelist(ip, whitelist) {
37
- if (!whitelist || !Array.isArray(whitelist)) return false;
38
- return whitelist.some(whiteIP => {
39
- // 支持CIDR格式(如192.168.1.0/24)
40
- if (whiteIP.includes('/')) {
41
- return ipInCidr(ip, whiteIP);
42
- }
43
- return ip === whiteIP;
44
- });
45
- }
46
-
47
- /**
48
- * 检查IP是否在CIDR范围内
49
- * @param {String} ip IP地址
50
- * @param {String} cidr CIDR格式字符串(如192.168.1.0/24)
51
- * @returns {Boolean} 是否在范围内
52
- */
53
- function ipInCidr(ip, cidr) {
54
- const [network, prefixLength] = cidr.split('/');
55
- const netmask = -1 << (32 - parseInt(prefixLength, 10));
56
-
57
- function ipToInt(ip) {
58
- return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) >>> 0;
59
- }
60
-
61
- return (ipToInt(ip) & netmask) === (ipToInt(network) & netmask);
62
- }
63
-
64
- /**
65
- * 设置黑名单
66
- * @param {String} ip IP地址
67
- * @param {Object} config 配置参数
68
- */
69
- async function setting_blacklist(ip, config) {
70
- // 检查是否已在黑名单中
71
- const blacklistKey = `blacklist_${ip}`;
72
- try {
73
- const isBlacklisted = await $.cache.get(blacklistKey);
74
- if (isBlacklisted) {
75
- $.log.info(`IP ${ip} 已在黑名单中,无需重复添加`);
76
- return;
77
- }
78
- } catch (error) {
79
- $.log.error('检查黑名单缓存错误:', error);
80
- }
81
-
82
- var cmd;
83
- if (platform == "win32") {
84
- // Windows系统
85
- cmd = `netsh advfirewall firewall add rule name="Blacklist ${ip}" dir=in action=block remoteip="${ip}" protocol=any`;
86
- } else {
87
- // Linux系统 - 不使用sudo,让系统确保权限
88
- cmd = `iptables -A INPUT -s ${ip} -j DROP`;
89
- }
90
-
91
- try {
92
- // 使用Promise包装exec以支持异步操作
93
- await new Promise((resolve, reject) => {
94
- exec(cmd, (error, stdout, stderr) => {
95
- if (error) {
96
- console.error(`执行黑名单命令错误: ${error}`);
97
- reject(error);
98
- return;
99
- }
100
- $.log.info(`IP ${ip} 已加入防火墙黑名单`);
101
- if (stderr) {
102
- console.error(`黑名单命令标准错误: ${stderr}`);
103
- }
104
- resolve();
105
- });
106
- });
107
-
108
- // 记录到缓存,支持黑名单过期时间
109
- const expireTime = config.blacklist_expire_time || 86400000; // 默认1天
110
- await $.cache.set(blacklistKey, true, expireTime);
111
-
112
- // 记录黑名单IP,便于管理
113
- const blacklistIPsKey = 'blacklisted_ips';
114
- let blacklistIPs = [];
115
- try {
116
- const existing = await $.cache.get(blacklistIPsKey);
117
- if (existing) {
118
- blacklistIPs = typeof existing === 'string' ? JSON.parse(existing) : existing;
119
- }
120
- if (!Array.isArray(blacklistIPs)) {
121
- blacklistIPs = [];
122
- }
123
- if (!blacklistIPs.includes(ip)) {
124
- blacklistIPs.push(ip);
125
- await $.cache.set(blacklistIPsKey, blacklistIPs, 0); // 永不过期
126
- }
127
- } catch (cacheError) {
128
- $.log.error('保存黑名单IP列表错误:', cacheError);
129
- }
130
- } catch (error) {
131
- $.log.error(`添加IP ${ip} 到黑名单失败:`, error);
132
- }
133
- }
134
-
135
- /**
136
- * 从防火墙中移除黑名单IP
137
- * @param {String} ip IP地址
138
- */
139
- async function remove_blacklist(ip) {
140
- var cmd;
141
- if (platform == "win32") {
142
- // Windows系统
143
- cmd = `netsh advfirewall firewall delete rule name="Blacklist ${ip}"`;
144
- } else {
145
- // Linux系统
146
- cmd = `iptables -D INPUT -s ${ip} -j DROP`;
147
- }
148
-
149
- try {
150
- await new Promise((resolve, reject) => {
151
- exec(cmd, (error, stdout, stderr) => {
152
- if (error) {
153
- console.error(`移除黑名单命令错误: ${error}`);
154
- // 对于Windows,如果规则不存在,delete命令也会返回错误,但这不是严重问题
155
- if (platform !== "win32") {
156
- reject(error);
157
- return;
158
- }
159
- }
160
- $.log.info(`IP ${ip} 已从防火墙黑名单中移除`);
161
- if (stderr) {
162
- console.error(`移除黑名单命令标准错误: ${stderr}`);
163
- }
164
- resolve();
165
- });
166
- });
167
-
168
- // 从缓存中移除
169
- await $.cache.del(`blacklist_${ip}`);
170
-
171
- // 从黑名单列表中移除
172
- const blacklistIPsKey = 'blacklisted_ips';
173
- try {
174
- const existing = await $.cache.get(blacklistIPsKey);
175
- if (existing) {
176
- let blacklistIPs = typeof existing === 'string' ? JSON.parse(existing) : existing;
177
- if (Array.isArray(blacklistIPs)) {
178
- blacklistIPs = blacklistIPs.filter(ipItem => ipItem !== ip);
179
- await $.cache.set(blacklistIPsKey, blacklistIPs, 0);
180
- }
181
- }
182
- } catch (cacheError) {
183
- $.log.error('更新黑名单IP列表错误:', cacheError);
184
- }
185
- } catch (error) {
186
- $.log.error(`移除IP ${ip} 从黑名单失败:`, error);
187
- }
188
- }
189
-
190
- /**
191
- * 初始化功能 - 加载持久化的黑名单并应用
192
- * @param {Object} config 配置参数
193
- */
194
- async function initBlacklist(config) {
195
- if (!config.persist_blacklist) return;
196
-
197
- try {
198
- const blacklistIPsKey = 'blacklisted_ips';
199
- const existing = await $.cache.get(blacklistIPsKey);
200
- if (existing) {
201
- let blacklistIPs = typeof existing === 'string' ? JSON.parse(existing) : existing;
202
- if (Array.isArray(blacklistIPs) && blacklistIPs.length > 0) {
203
- $.log.info(`正在应用 ${blacklistIPs.length} 个持久化的黑名单IP规则...`);
204
- for (const ip of blacklistIPs) {
205
- // 重新应用黑名单规则
206
- await setting_blacklist(ip, config);
207
- }
208
- }
209
- }
210
- } catch (error) {
211
- $.log.error('初始化持久化黑名单失败:', error);
212
- }
213
- }
214
-
215
- /**
216
- * IP防火墙
217
- * @param {Object} server 服务
218
- * @param {Object} config 配置参数
219
- */
220
- module.exports = async function(server, config) {
221
- // 从配置中获取参数,提供默认值
222
- var limit = config.request_limit || 1000; // 默认每分钟1000请求
223
- var duration = config.request_duration || 60000; // 默认60秒
224
- var block = config.request_block || true; // 默认启用黑名单
225
- var whitelist = config.ip_whitelist || []; // IP白名单
226
- var blacklist_expire_time = config.blacklist_expire_time || 86400000; // 默认黑名单1天过期
227
- var persist_blacklist = config.persist_blacklist !== undefined ? config.persist_blacklist : true; // 是否持久化黑名单
228
-
229
- // 初始化持久化黑名单
230
- if (persist_blacklist) {
231
- await initBlacklist(config);
232
- }
233
-
234
- if (limit && duration) {
235
- /* WAF(web防火墙) */
236
- server.use(async (ctx, next) => {
237
- try {
238
- var pass = true;
239
- // 获取IP
240
- var ip = getClientIP(ctx.req);
241
-
242
- // 检查白名单
243
- if (isInWhitelist(ip, whitelist)) {
244
- ctx.request.ip = ip;
245
- ctx.ip = ip;
246
- await next();
247
- return;
248
- }
249
-
250
- // 检查是否已被黑名单
251
- try {
252
- const isBlacklisted = await $.cache.get(`blacklist_${ip}`);
253
- if (isBlacklisted) {
254
- ctx.status = 403;
255
- ctx.body = '您的IP已被禁止访问';
256
- return;
257
- }
258
- } catch (blacklistCheckError) {
259
- $.log.error('检查黑名单状态错误:', blacklistCheckError);
260
- }
261
-
262
- var num = 1;
263
- var now = new Date();
264
- var date = now.toStr('yyyy-MM-dd');
265
- var time;
266
- var json;
267
-
268
- try {
269
- var str = await $.cache.get("ip_" + ip);
270
- if (str) {
271
- if (typeof(str) === "string") {
272
- try {
273
- json = JSON.parse(str);
274
- } catch (jsonError) {
275
- $.log.error('WAF IP中间件JSON解析错误:', jsonError);
276
- json = null;
277
- }
278
- } else {
279
- json = str;
280
- }
281
-
282
- if (json) {
283
- try {
284
- if (json.date !== date) {
285
- num = 1;
286
- } else {
287
- // 判断时间间隔是否在范围外
288
- // 安全地处理json.time,无论它是字符串还是对象
289
- if (typeof json.time === 'string') {
290
- // 如果json.time是字符串,尝试解析它
291
- const savedTime = new Date(json.time);
292
- if (!isNaN(savedTime.getTime()) && (now - savedTime) > duration) {
293
- num = 1;
294
- } else {
295
- // 如果是在周期内,访问次数+1,并判断是否超出上限
296
- num = json.num + 1;
297
- if (num > limit) {
298
- // 超出上限禁止访问,并加入黑名单
299
- pass = false;
300
- if (block) {
301
- await setting_blacklist(ip, config);
302
- }
303
- }
304
- }
305
- } else if (json.time && json.time.toTime && typeof json.time.toTime().interval === 'function') {
306
- // 原有逻辑,处理对象类型的时间
307
- if (json.time.toTime().interval(now) > duration) {
308
- num = 1;
309
- } else {
310
- // 如果是在周期内,访问次数+1,并判断是否超出上限
311
- num = json.num + 1;
312
- if (num > limit) {
313
- // 超出上限禁止访问,并加入黑名单
314
- pass = false;
315
- if (block) {
316
- await setting_blacklist(ip, config);
317
- }
318
- }
319
- }
320
- } else {
321
- // 默认情况:如果时间格式不正确,重置计数
322
- num = 1;
323
- }
324
- }
325
- } catch (timeError) {
326
- $.log.error('WAF IP中间件时间处理错误:', timeError);
327
- // 出错时重置计数以保证安全
328
- num = 1;
329
- }
330
- }
331
- }
332
- } catch (cacheError) {
333
- $.log.error('WAF IP中间件缓存操作错误:', cacheError);
334
- // 缓存出错时,默认允许请求通过
335
- }
336
-
337
- if (!time) {
338
- time = now.toStr('yyyy-MM-dd hh:mm:ss');
339
- }
340
-
341
- if (pass) {
342
- try {
343
- await $.cache.set("ip_" + ip, JSON.stringify({
344
- date,
345
- time,
346
- num
347
- }), duration);
348
- } catch (setCacheError) {
349
- $.log.error('WAF IP中间件缓存设置错误:', setCacheError);
350
- // 缓存设置失败不影响请求处理
351
- }
352
- ctx.request.ip = ip;
353
- ctx.ip = ip;
354
- await next();
355
- } else {
356
- ctx.status = 429;
357
- ctx.body = '请求频率过高,请稍后再试。';
358
- }
359
- } catch (error) {
360
- $.log.error('WAF IP中间件错误:', error);
361
- // 出错时默认允许请求通过
362
- ctx.ip = getClientIP(ctx.req);
363
- await next();
364
- }
365
- });
366
- }
367
-
368
- // 提供手动管理黑名单的API方法
369
- if (!$.waf_ip) {
370
- $.waf_ip = {
371
- addBlacklist: setting_blacklist,
372
- removeBlacklist: remove_blacklist,
373
- getClientIP: getClientIP,
374
- isInWhitelist: isInWhitelist
375
- };
376
- }
377
-
378
- return server;
379
- };
@@ -1,49 +0,0 @@
1
- {
2
- "name": "web_waf_ip",
3
- "title": "IP防火墙增强版",
4
- "description": "增强版IP防火墙,支持IP白名单、黑名单持久化、自动过期等功能,有效防止DOS攻击",
5
- "version": "2.0",
6
- "type": "web",
7
- "process_type": "common_before",
8
- "sort": 10,
9
- "state": 1,
10
- "config": {
11
- "request_limit": {
12
- "type": "number",
13
- "title": "请求限制数量",
14
- "description": "在指定时间内允许的最大请求数",
15
- "value": 1000,
16
- "placeholder": "请输入数字"
17
- },
18
- "request_duration": {
19
- "type": "number",
20
- "title": "统计时间窗口(毫秒)",
21
- "description": "请求计数的时间窗口,单位为毫秒",
22
- "value": 60000,
23
- "placeholder": "请输入毫秒数"
24
- },
25
- "request_block": {
26
- "type": "boolean",
27
- "title": "启用黑名单封禁",
28
- "description": "是否将超限IP添加到系统防火墙黑名单",
29
- "value": true
30
- },
31
- "ip_whitelist": [
32
- "192.168.31.5",
33
- "127.0.0.1"
34
- ],
35
- "blacklist_expire_time": {
36
- "type": "number",
37
- "title": "黑名单过期时间(毫秒)",
38
- "description": "IP被添加到黑名单后自动失效的时间,单位为毫秒",
39
- "value": 86400000,
40
- "placeholder": "请输入毫秒数"
41
- },
42
- "persist_blacklist": {
43
- "type": "boolean",
44
- "title": "持久化黑名单",
45
- "description": "系统重启后是否自动重新应用已保存的黑名单规则",
46
- "value": true
47
- }
48
- }
49
- }