mm_os 3.3.0 → 4.0.0

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 (380) hide show
  1. package/LICENSE +21 -201
  2. package/README.md +491 -99
  3. package/README_EN.md +498 -0
  4. package/adapter/adapter.js +431 -0
  5. package/adapter/custom_persistence.js +660 -0
  6. package/adapter/mqtt.js +273 -0
  7. package/adapter/socket.js +113 -0
  8. package/adapter/web.js +67 -0
  9. package/adapter/websocket.js +146 -0
  10. package/com/api/com.json +5 -0
  11. package/{core/com → com}/api/config.tpl.json +8 -8
  12. package/com/api/drive.js +708 -0
  13. package/com/api/index.js +198 -0
  14. package/com/api/oauth.js +200 -0
  15. package/com/api/script.tpl.js +32 -0
  16. package/com/cmd/README.md +11 -0
  17. package/com/cmd/com.json +5 -0
  18. package/com/cmd/config.tpl.json +122 -0
  19. package/com/cmd/drive.js +1548 -0
  20. package/com/cmd/index.js +1066 -0
  21. package/com/cmd/msg.json +48 -0
  22. package/com/cmd/nlp.js +525 -0
  23. package/com/cmd/script.tpl.js +32 -0
  24. package/com/db/com.json +5 -0
  25. package/com/db/drive.js +1999 -0
  26. package/com/db/index.js +242 -0
  27. package/com/event/com.json +5 -0
  28. package/{core/com → com}/event/config.tpl.json +8 -8
  29. package/com/event/drive.js +59 -0
  30. package/com/event/index.js +409 -0
  31. package/com/event/script.tpl.js +23 -0
  32. package/com/mqtt/com.json +5 -0
  33. package/{core/com → com}/mqtt/config.tpl.json +3 -5
  34. package/com/mqtt/drive.js +676 -0
  35. package/com/mqtt/index.js +822 -0
  36. package/com/mqtt/mm_mqtt.js +425 -0
  37. package/com/mqtt/script.tpl.js +723 -0
  38. package/com/nav/com.json +5 -0
  39. package/com/nav/config.tpl.json +84 -0
  40. package/com/nav/drive.js +702 -0
  41. package/com/nav/index.js +231 -0
  42. package/{core/com → com}/nav/tpl/admin_pc/page_config.vue +280 -280
  43. package/{core/com → com}/nav/tpl/admin_pc/page_config_form.vue +194 -194
  44. package/com/nav/tpl/admin_pc/page_form.vue +180 -0
  45. package/com/nav/tpl/admin_pc/page_view.vue +124 -0
  46. package/com/nav/tpl/dev_pc/page_default.vue +247 -0
  47. package/com/nav/tpl/dev_pc/page_type.vue +313 -0
  48. package/com/nav/tpl/home_pc/page_default.vue +234 -0
  49. package/com/nav/tpl/home_pc/page_form.vue +137 -0
  50. package/com/nav/tpl/home_pc/page_list.vue +234 -0
  51. package/com/nav/tpl/home_pc/page_nav.vue +221 -0
  52. package/com/nav/tpl/home_pc/page_type.vue +234 -0
  53. package/com/nav/tpl/home_pc/page_view.vue +125 -0
  54. package/com/nav/tpl/home_phone/page_channel.vue +234 -0
  55. package/com/nav/tpl/home_phone/page_default.vue +234 -0
  56. package/com/nav/tpl/home_phone/page_form.vue +137 -0
  57. package/com/nav/tpl/home_phone/page_nav.vue +237 -0
  58. package/com/nav/tpl/home_phone/page_type.vue +234 -0
  59. package/com/nav/tpl/home_phone/page_view.vue +125 -0
  60. package/com/nav/viewmodel.js +446 -0
  61. package/com/param/com.json +5 -0
  62. package/{core/com → com}/param/config.tpl.json +7 -1
  63. package/com/param/drive.js +502 -0
  64. package/com/param/index.js +155 -0
  65. package/com/param/script.tpl.js +12 -0
  66. package/com/pendant/com.json +5 -0
  67. package/{core/com/component → com/pendant}/config.tpl.json +15 -13
  68. package/com/pendant/drive.js +204 -0
  69. package/com/pendant/index.js +441 -0
  70. package/com/pendant/pendant.html +16 -0
  71. package/com/pendant/script.tpl.js +18 -0
  72. package/com/socket/com.json +5 -0
  73. package/com/socket/config.tpl.json +12 -0
  74. package/com/socket/drive.js +651 -0
  75. package/com/socket/index.js +351 -0
  76. package/com/socket/script.tpl.js +41 -0
  77. package/com/sql/com.json +5 -0
  78. package/{core/com → com}/sql/config.tpl.json +13 -9
  79. package/com/sql/drive.js +1259 -0
  80. package/com/sql/index.js +150 -0
  81. package/com/sql/script.tpl.js +47 -0
  82. package/com/static/com.json +5 -0
  83. package/{core/com → com}/static/config.tpl.json +10 -6
  84. package/com/static/drive.js +194 -0
  85. package/com/static/index.js +226 -0
  86. package/com/static/script.tpl.js +28 -0
  87. package/com/task/com.json +5 -0
  88. package/{core/com → com}/task/config.tpl.json +4 -6
  89. package/com/task/drive.js +405 -0
  90. package/com/task/index.js +148 -0
  91. package/com/task/script.tpl.js +37 -0
  92. package/com/template/com.json +5 -0
  93. package/com/template/config.tpl.json +16 -0
  94. package/com/template/drive.js +80 -0
  95. package/com/template/index.js +141 -0
  96. package/com.js +156 -0
  97. package/common/README.md +2 -0
  98. package/common/handler/msg/handler.json +22 -0
  99. package/common/handler/msg/index.js +23 -0
  100. package/common/handler/player/handler.json +22 -0
  101. package/common/handler/player/index.js +287 -0
  102. package/common/handler/user/handler.json +22 -0
  103. package/common/handler/user/index.js +23 -0
  104. package/common/middleware/web_after/index.js +29 -0
  105. package/common/middleware/web_after/middleware.json +9 -0
  106. package/common/middleware/web_base/index.js +113 -0
  107. package/common/middleware/web_base/middleware.json +19 -0
  108. package/common/middleware/web_before/index.js +33 -0
  109. package/common/middleware/web_before/middleware.json +9 -0
  110. package/common/middleware/web_cors/index.js +87 -0
  111. package/common/middleware/web_cors/middleware.json +24 -0
  112. package/common/middleware/web_error/index.js +119 -0
  113. package/common/middleware/web_error/middleware.json +18 -0
  114. package/common/middleware/web_ip/index.js +15 -0
  115. package/common/middleware/web_ip/middleware.json +14 -0
  116. package/common/middleware/web_logger/index.js +156 -0
  117. package/common/middleware/web_logger/middleware.json +14 -0
  118. package/common/middleware/web_main/index.js +24 -0
  119. package/common/middleware/web_main/middleware.json +9 -0
  120. package/common/middleware/web_static/index.js +73 -0
  121. package/common/middleware/web_static/middleware.json +54 -0
  122. package/common/middleware/web_waf/index.js +385 -0
  123. package/common/middleware/web_waf/middleware.json +13 -0
  124. package/common/model/msg/index.js +88 -0
  125. package/common/model/msg/model.json +401 -0
  126. package/common/model/player/index.js +63 -0
  127. package/common/model/player/model.json +185 -0
  128. package/common/model/user/index.js +11 -0
  129. package/common/model/user/model.json +219 -0
  130. package/core/app/config.tpl.json +67 -0
  131. package/core/app/index.js +632 -0
  132. package/core/app/script.tpl.js +52 -0
  133. package/core/channel/index.js +899 -0
  134. package/core/channel/matcher.js +585 -0
  135. package/core/com/config.tpl.json +16 -0
  136. package/core/com/index.js +74 -0
  137. package/core/com/script.tpl.js +5 -0
  138. package/core/component/component.js +42 -0
  139. package/core/component/config.tpl.json +63 -0
  140. package/core/component/index.js +273 -0
  141. package/core/component/script.tpl.js +19 -0
  142. package/core/controller/config.tpl.json +14 -0
  143. package/core/controller/index.js +373 -0
  144. package/core/controller/script.tpl.js +27 -0
  145. package/core/factory/config.tpl.json +14 -0
  146. package/core/factory/entity.js +275 -0
  147. package/core/factory/index.js +241 -0
  148. package/core/factory/script.tpl.js +16 -0
  149. package/core/game/bat/index.js +137 -0
  150. package/core/game/bat/world.js +622 -0
  151. package/core/game/config.tpl.json +16 -0
  152. package/core/game/entity_admin.js +230 -0
  153. package/core/game/index.js +186 -0
  154. package/core/handler/config.tpl.json +22 -0
  155. package/core/handler/index.js +181 -0
  156. package/core/handler/script.tpl.js +23 -0
  157. package/core/logic/config.tpl.json +14 -0
  158. package/core/logic/index.js +59 -0
  159. package/core/logic/script.tpl.js +19 -0
  160. package/core/middleware/config.tpl.json +16 -0
  161. package/core/middleware/index.js +125 -0
  162. package/core/middleware/script.tpl.js +37 -0
  163. package/core/mod/config.tpl.json +22 -0
  164. package/core/mod/index.js +130 -0
  165. package/core/mod/script.tpl.js +34 -0
  166. package/core/model/config.tpl.json +219 -0
  167. package/core/model/index.js +272 -0
  168. package/core/model/model.js +27 -0
  169. package/core/model/script.tpl.js +20 -0
  170. package/core/notifier/config.tpl.json +14 -0
  171. package/core/notifier/index.js +77 -0
  172. package/core/notifier/script.tpl.js +20 -0
  173. package/core/plugin/config.tpl.json +24 -0
  174. package/core/plugin/index.js +232 -0
  175. package/core/plugin/script.tpl.js +51 -0
  176. package/core/pusher/config.tpl.json +14 -0
  177. package/core/pusher/index.js +161 -0
  178. package/core/pusher/script.tpl.js +20 -0
  179. package/core/room/bat/index.js +170 -0
  180. package/core/room/bat/room.js +524 -0
  181. package/core/room/config.tpl.json +20 -0
  182. package/core/room/index.js +249 -0
  183. package/core/room/room.js +61 -0
  184. package/core/scene/config.tpl.json +14 -0
  185. package/core/scene/index.js +466 -0
  186. package/core/scene/loop.js +1255 -0
  187. package/core/scene/map.js +28 -0
  188. package/core/scene/script.tpl.js +22 -0
  189. package/core/sender/config.tpl.json +14 -0
  190. package/core/sender/index.js +79 -0
  191. package/core/sender/script.tpl.js +20 -0
  192. package/core/service/config.tpl.json +14 -0
  193. package/core/service/index.js +100 -0
  194. package/core/service/script.tpl.js +25 -0
  195. package/core/store/config.tpl.json +26 -0
  196. package/core/store/index.js +1755 -0
  197. package/core/store/script.tpl.js +22 -0
  198. package/core/store/sql.js +1464 -0
  199. package/core/system/config.tpl.json +18 -0
  200. package/core/system/index.js +312 -0
  201. package/core/system/script.tpl.js +77 -0
  202. package/core/view/config.tpl.json +14 -0
  203. package/core/view/index.js +91 -0
  204. package/core/view/script.tpl.js +20 -0
  205. package/core/zone/bat/index.js +725 -0
  206. package/core/zone/config.tpl.json +54 -0
  207. package/core/zone/index.js +614 -0
  208. package/core/zone/script.tpl.js +10 -0
  209. package/core/zone/zone_bat.js +136 -0
  210. package/core//345/237/272/347/261/273/346/250/241/345/235/227/346/270/205/345/215/225.md +24 -0
  211. package/index.js +17 -314
  212. package/os.js +57 -0
  213. package/package.json +60 -58
  214. package/server.js +598 -0
  215. package/README.en.md +0 -36
  216. package/conf.json +0 -3
  217. package/core/base/mqtt/index.js +0 -1107
  218. package/core/base/mqtt/lib.js +0 -40
  219. package/core/base/web/index.js +0 -243
  220. package/core/com/api/com.json +0 -4
  221. package/core/com/api/drive.js +0 -668
  222. package/core/com/api/index.js +0 -108
  223. package/core/com/api/oauth.js +0 -158
  224. package/core/com/api/script.js +0 -32
  225. package/core/com/app/README.md +0 -3
  226. package/core/com/app/com.json +0 -4
  227. package/core/com/app/config.tpl.json +0 -16
  228. package/core/com/app/drive.js +0 -309
  229. package/core/com/app/index.js +0 -211
  230. package/core/com/app/script.js +0 -155
  231. package/core/com/cmd/com.json +0 -4
  232. package/core/com/cmd/config.tpl.json +0 -66
  233. package/core/com/cmd/drive.js +0 -513
  234. package/core/com/cmd/index.js +0 -354
  235. package/core/com/cmd/old/5w2h.js +0 -54
  236. package/core/com/cmd/old/drive.js +0 -423
  237. package/core/com/cmd/script.js +0 -11
  238. package/core/com/component/README.md +0 -3
  239. package/core/com/component/com.json +0 -4
  240. package/core/com/component/component.html +0 -16
  241. package/core/com/component/drive.js +0 -197
  242. package/core/com/component/index.js +0 -312
  243. package/core/com/component/script.js +0 -18
  244. package/core/com/db/com.json +0 -4
  245. package/core/com/db/drive.js +0 -1160
  246. package/core/com/db/index.js +0 -176
  247. package/core/com/event/com.json +0 -4
  248. package/core/com/event/drive.js +0 -133
  249. package/core/com/event/index.js +0 -345
  250. package/core/com/event/script.js +0 -26
  251. package/core/com/eventer/com.js +0 -477
  252. package/core/com/eventer/com.json +0 -4
  253. package/core/com/middleware/com.js +0 -153
  254. package/core/com/middleware/com.json +0 -4
  255. package/core/com/middleware/config.tpl.json +0 -8
  256. package/core/com/middleware/script.js +0 -9
  257. package/core/com/mqtt/com.json +0 -4
  258. package/core/com/mqtt/drive.js +0 -600
  259. package/core/com/mqtt/index.js +0 -572
  260. package/core/com/mqtt/mm_mqtt.js +0 -330
  261. package/core/com/mqtt/script.js +0 -604
  262. package/core/com/msg/com.js +0 -296
  263. package/core/com/msg/com.json +0 -4
  264. package/core/com/nav/com.json +0 -4
  265. package/core/com/nav/config.tpl.json +0 -75
  266. package/core/com/nav/drive.js +0 -549
  267. package/core/com/nav/index.js +0 -182
  268. package/core/com/nav/tpl/admin_pc/page_form.vue +0 -180
  269. package/core/com/nav/tpl/admin_pc/page_view.vue +0 -124
  270. package/core/com/nav/tpl/dev_pc/page_default.vue +0 -247
  271. package/core/com/nav/tpl/dev_pc/page_type.vue +0 -313
  272. package/core/com/nav/tpl/home_pc/page_default.vue +0 -234
  273. package/core/com/nav/tpl/home_pc/page_form.vue +0 -137
  274. package/core/com/nav/tpl/home_pc/page_list.vue +0 -234
  275. package/core/com/nav/tpl/home_pc/page_nav.vue +0 -221
  276. package/core/com/nav/tpl/home_pc/page_type.vue +0 -234
  277. package/core/com/nav/tpl/home_pc/page_view.vue +0 -125
  278. package/core/com/nav/tpl/home_phone/page_channel.vue +0 -234
  279. package/core/com/nav/tpl/home_phone/page_default.vue +0 -234
  280. package/core/com/nav/tpl/home_phone/page_form.vue +0 -137
  281. package/core/com/nav/tpl/home_phone/page_nav.vue +0 -237
  282. package/core/com/nav/tpl/home_phone/page_type.vue +0 -234
  283. package/core/com/nav/tpl/home_phone/page_view.vue +0 -125
  284. package/core/com/nav/viewmodel.js +0 -296
  285. package/core/com/param/drive.js +0 -366
  286. package/core/com/param/index.js +0 -80
  287. package/core/com/param/script.js +0 -12
  288. package/core/com/param/test.js +0 -98
  289. package/core/com/plugin/README.md +0 -3
  290. package/core/com/plugin/com.json +0 -4
  291. package/core/com/plugin/config.tpl.json +0 -26
  292. package/core/com/plugin/drive.js +0 -536
  293. package/core/com/plugin/index.js +0 -259
  294. package/core/com/plugin/script.js +0 -213
  295. package/core/com/rpc/com.json +0 -4
  296. package/core/com/rpc/drive.js +0 -160
  297. package/core/com/rpc/index.js +0 -87
  298. package/core/com/rpc/rpc.js +0 -118
  299. package/core/com/socket/com.json +0 -4
  300. package/core/com/socket/config.tpl.json +0 -14
  301. package/core/com/socket/drive.js +0 -403
  302. package/core/com/socket/index.js +0 -62
  303. package/core/com/socket/script.js +0 -42
  304. package/core/com/sql/drive.js +0 -1087
  305. package/core/com/sql/index.js +0 -83
  306. package/core/com/sql/script.js +0 -48
  307. package/core/com/static/com.json +0 -4
  308. package/core/com/static/drive.js +0 -220
  309. package/core/com/static/index.js +0 -149
  310. package/core/com/static/script.js +0 -28
  311. package/core/com/task/com.json +0 -4
  312. package/core/com/task/drive.js +0 -403
  313. package/core/com/task/index.js +0 -110
  314. package/core/com/task/script.js +0 -37
  315. package/core/com/timer/com.js +0 -217
  316. package/core/com/timer/com.json +0 -4
  317. package/core/com/tpl/com.js +0 -19
  318. package/core/com/tpl/com.json +0 -4
  319. package/lib/actions.js +0 -50
  320. package/lib/base.js +0 -361
  321. package/lib/com.js +0 -29
  322. package/lib/ref.js +0 -121
  323. package/middleware/mqtt_base/index.js +0 -10
  324. package/middleware/mqtt_base/middleware.json +0 -10
  325. package/middleware/performance/index.js +0 -151
  326. package/middleware/performance/middleware.json +0 -16
  327. package/middleware/security_audit/index.js +0 -549
  328. package/middleware/security_audit/middleware.json +0 -48
  329. package/middleware/security_headers/index.js +0 -487
  330. package/middleware/security_headers/middleware.json +0 -45
  331. package/middleware/waf/index.js +0 -348
  332. package/middleware/waf/middleware.json +0 -10
  333. package/middleware/waf_ddos/index.js +0 -520
  334. package/middleware/waf_ddos/middleware.json +0 -38
  335. package/middleware/waf_ip/index.js +0 -379
  336. package/middleware/waf_ip/middleware.json +0 -49
  337. package/middleware/waf_xss/index.js +0 -269
  338. package/middleware/waf_xss/middleware.json +0 -18
  339. package/middleware/web_after/index.js +0 -33
  340. package/middleware/web_after/middleware.json +0 -9
  341. package/middleware/web_base/index.js +0 -90
  342. package/middleware/web_base/middleware.json +0 -9
  343. package/middleware/web_before/index.js +0 -27
  344. package/middleware/web_before/middleware.json +0 -9
  345. package/middleware/web_check/index.js +0 -28
  346. package/middleware/web_check/middleware.json +0 -9
  347. package/middleware/web_main/index.js +0 -28
  348. package/middleware/web_main/middleware.json +0 -9
  349. package/middleware/web_proxy/index.js +0 -37
  350. package/middleware/web_proxy/middleware.json +0 -9
  351. package/middleware/web_render/index.js +0 -87
  352. package/middleware/web_render/middleware.json +0 -9
  353. package/middleware/web_socket/index.js +0 -34
  354. package/middleware/web_socket/middleware.json +0 -9
  355. package/middleware/web_static/index.js +0 -115
  356. package/middleware/web_static/middleware.json +0 -9
  357. /package/{core/com → com}/api/README.md +0 -0
  358. /package/{core/com → com}/db/README.md +0 -0
  359. /package/{core/com → com}/event/README.md +0 -0
  360. /package/{core/com → com}/mqtt/README.md +0 -0
  361. /package/{core/com → com}/nav/README.md +0 -0
  362. /package/{core/com → com}/nav/tpl/admin_pc/page_channel.vue +0 -0
  363. /package/{core/com → com}/nav/tpl/admin_pc/page_default.vue +0 -0
  364. /package/{core/com → com}/nav/tpl/admin_pc/page_lang.vue +0 -0
  365. /package/{core/com → com}/nav/tpl/admin_pc/page_nav.vue +0 -0
  366. /package/{core/com → com}/nav/tpl/admin_pc/page_table.vue +0 -0
  367. /package/{core/com → com}/nav/tpl/admin_pc/page_type.vue +0 -0
  368. /package/{core/com → com}/nav/tpl/dev_pc/page_channel.vue +0 -0
  369. /package/{core/com → com}/nav/tpl/dev_pc/page_config.vue +0 -0
  370. /package/{core/com → com}/nav/tpl/dev_pc/page_form.vue +0 -0
  371. /package/{core/com → com}/nav/tpl/dev_pc/page_nav.vue +0 -0
  372. /package/{core/com → com}/nav/tpl/dev_pc/page_table.vue +0 -0
  373. /package/{core/com → com}/nav/tpl/home_pc/page_channel.vue +0 -0
  374. /package/{core/com → com}/nav/tpl/home_phone/page_list.vue +0 -0
  375. /package/{core/com → com}/param/README.md +0 -0
  376. /package/{core/com/cmd → com/pendant}/README.md +0 -0
  377. /package/{core/com → com}/socket/README.md +0 -0
  378. /package/{core/com → com}/sql/README.md +0 -0
  379. /package/{core/com → com}/static/README.md +0 -0
  380. /package/{core/com → com}/task/README.md +0 -0
@@ -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
- }
@@ -1,269 +0,0 @@
1
- const mm_expand = require('mm_expand');
2
-
3
- /**
4
- * XSS攻击防护中间件
5
- */
6
- class Middleware {
7
- /**
8
- * 构造函数
9
- */
10
- constructor() {
11
- this.default = {
12
- // 过滤模式: sanitize(清理) | encode(编码) | both(同时进行)
13
- mode: 'both',
14
- // 是否过滤URL参数
15
- query: true,
16
- // 是否过滤表单数据
17
- body: true,
18
- // 是否过滤Cookie
19
- cookie: true,
20
- // 白名单标签
21
- allowedTags: ['p', 'span', 'b', 'i', 'u', 'strong', 'em', 'br'],
22
- // 白名单属性
23
- allowedAttributes: ['id', 'class', 'style'],
24
- // 是否记录XSS攻击尝试
25
- log: true,
26
- // 是否阻止恶意请求
27
- block: true
28
- };
29
- }
30
-
31
- /**
32
- * 初始化中间件
33
- * @param {Object} config 配置项
34
- */
35
- init(config) {
36
- config = Object.assign({}, this.default, config);
37
- this.config = config;
38
- return function() {
39
- // 返回中间件的run方法作为实际的处理函数
40
- return function(ctx, next) {
41
- return middleware.run(ctx, next);
42
- };
43
- };
44
- }
45
-
46
- /**
47
- * 获取客户端真实IP
48
- * 在代理环境中,优先从代理头获取真实IP
49
- * @param {Object} ctx Koa上下文
50
- * @returns {String} 客户端真实IP
51
- */
52
- getClientIp(ctx) {
53
- const headers = ctx.headers;
54
- // 优先检查常用代理头获取真实IP
55
- // 注意:X-Forwarded-For 可能包含多个IP,取第一个非未知IP的值
56
- const xForwardedFor = headers['x-forwarded-for'];
57
- if (xForwardedFor) {
58
- // X-Forwarded-For 格式通常为: client, proxy1, proxy2
59
- const ips = xForwardedFor.split(',').map(ip => ip.trim());
60
- for (let i = 0; i < ips.length; i++) {
61
- const ip = ips[i];
62
- if (ip && ip !== 'unknown' && ip !== '127.0.0.1' && ip !== '::1') {
63
- return ip;
64
- }
65
- }
66
- }
67
-
68
- // 检查其他常见的代理头
69
- return headers['x-real-ip'] ||
70
- headers['x-client-ip'] ||
71
- headers['cf-connecting-ip'] || // CloudFlare
72
- headers['fastly-client-ip'] || // Fastly
73
- headers['true-client-ip'] || // Akamai and Cloudflare
74
- ctx.ip; // 默认回退到ctx.ip
75
- }
76
-
77
- /**
78
- * 执行中间件
79
- * @param {Object} ctx Koa上下文
80
- * @param {Function} next 下一个中间件
81
- */
82
- async run(ctx, next) {
83
- const config = this.config;
84
- let hasXSS = false;
85
- let attackInfo = {};
86
-
87
- // 清理URL查询参数
88
- if (config.query && ctx.query) {
89
- for (let key in ctx.query) {
90
- const original = ctx.query[key];
91
- const sanitized = this.sanitizeInput(original, config);
92
- if (original !== sanitized) {
93
- ctx.query[key] = sanitized;
94
- hasXSS = true;
95
- attackInfo[`query.${key}`] = { original, sanitized };
96
- }
97
- }
98
- }
99
-
100
- // 清理请求体数据
101
- if (config.body && ctx.request.body) {
102
- this.cleanObject(ctx.request.body, config, attackInfo, 'body', hasXSS);
103
- }
104
-
105
- // 清理Cookie
106
- if (config.cookie && ctx.cookies) {
107
- const cookies = ctx.headers.cookie;
108
- if (cookies) {
109
- // 记录Cookie中的XSS尝试但不修改,因为修改Cookie需要重新设置
110
- const cookieArr = cookies.split(';');
111
- for (let cookie of cookieArr) {
112
- const [name, value] = cookie.split('=').map(item => item.trim());
113
- const sanitized = this.sanitizeInput(decodeURIComponent(value), config);
114
- if (value !== sanitized) {
115
- hasXSS = true;
116
- attackInfo[`cookie.${name}`] = { original: value, sanitized };
117
- }
118
- }
119
- }
120
- }
121
-
122
- // 记录XSS攻击尝试
123
- if (hasXSS && config.log && $.log) {
124
- $.log.warn('XSS Attack Attempt Detected:', {
125
- ip: this.getClientIp(ctx),
126
- path: ctx.path,
127
- method: ctx.method,
128
- attackInfo
129
- });
130
- }
131
-
132
- // 阻止恶意请求
133
- if (hasXSS && config.block) {
134
- ctx.status = 403;
135
- ctx.body = {
136
- code: 403,
137
- msg: 'Forbidden: Potential XSS attack detected'
138
- };
139
- return;
140
- }
141
-
142
- // 添加安全响应头
143
- this.addSecurityHeaders(ctx);
144
-
145
- await next();
146
- }
147
-
148
- /**
149
- * 递归清理对象中的XSS内容
150
- * @param {Object} obj 要清理的对象
151
- * @param {Object} config 配置项
152
- * @param {Object} attackInfo 攻击信息收集对象
153
- * @param {String} prefix 路径前缀
154
- * @param {Boolean} hasXSS 是否已发现XSS
155
- */
156
- cleanObject(obj, config, attackInfo, prefix, hasXSS) {
157
- if (!obj || typeof obj !== 'object') return;
158
-
159
- for (let key in obj) {
160
- const path = `${prefix}.${key}`;
161
- if (typeof obj[key] === 'string') {
162
- const original = obj[key];
163
- const sanitized = this.sanitizeInput(original, config);
164
- if (original !== sanitized) {
165
- obj[key] = sanitized;
166
- hasXSS = true;
167
- attackInfo[path] = { original, sanitized };
168
- }
169
- } else if (typeof obj[key] === 'object') {
170
- this.cleanObject(obj[key], config, attackInfo, path, hasXSS);
171
- }
172
- }
173
- }
174
-
175
- /**
176
- * 清理输入内容
177
- * @param {String} input 输入内容
178
- * @param {Object} config 配置项
179
- * @returns {String} 清理后的内容
180
- */
181
- sanitizeInput(input, config) {
182
- if (!input || typeof input !== 'string') return input;
183
-
184
- let output = input;
185
-
186
- // 根据模式选择清理方式
187
- if (config.mode === 'sanitize' || config.mode === 'both') {
188
- output = this.sanitizeHTML(output, config);
189
- }
190
-
191
- if (config.mode === 'encode' || config.mode === 'both') {
192
- output = this.encodeHTML(output);
193
- }
194
-
195
- return output;
196
- }
197
-
198
- /**
199
- * 清理HTML内容
200
- * @param {String} html HTML内容
201
- * @param {Object} config 配置项
202
- * @returns {String} 清理后的内容
203
- */
204
- sanitizeHTML(html, config) {
205
- // 简单的HTML标签清理实现
206
- // 在生产环境中,可以使用更强大的库如DOMPurify
207
- let clean = html;
208
-
209
- // 移除所有脚本标签
210
- clean = clean.replace(/<script[^>]*>.*?<\/script>/gi, '');
211
-
212
- // 移除所有事件处理器
213
- clean = clean.replace(/\s+on\w+\s*=\s*["\']?[^"\'>\s]+/gi, '');
214
-
215
- // 移除危险的URL协议
216
- clean = clean.replace(/(src|href|data|action)\s*=\s*["\']?(javascript|data|vbscript):/gi, '$1=');
217
-
218
- return clean;
219
- }
220
-
221
- /**
222
- * 编码HTML特殊字符
223
- * @param {String} html HTML内容
224
- * @returns {String} 编码后的内容
225
- */
226
- encodeHTML(html) {
227
- return String(html)
228
- .replace(/&/g, '&amp;')
229
- .replace(/</g, '&lt;')
230
- .replace(/>/g, '&gt;')
231
- .replace(/"/g, '&quot;')
232
- .replace(/'/g, '&#39;');
233
- }
234
-
235
- /**
236
- * 添加安全响应头
237
- * @param {Object} ctx Koa上下文
238
- */
239
- addSecurityHeaders(ctx) {
240
- // X-XSS-Protection 头
241
- ctx.set('X-XSS-Protection', '1; mode=block');
242
-
243
- // Content-Security-Policy 头
244
- ctx.set('Content-Security-Policy', "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;");
245
- }
246
- }
247
-
248
- // 创建中间件实例
249
- const middleware = new Middleware();
250
-
251
- // 导出符合系统期望的函数
252
- exports = module.exports = function(server, config) {
253
- // 初始化中间件
254
- const handlerFactory = middleware.init(config);
255
- const middlewareHandler = handlerFactory();
256
-
257
- // 直接使用server.use注册中间件
258
- server.use(middlewareHandler);
259
-
260
- // 记录中间件初始化信息
261
- if ($.log && $.log.info) {
262
- $.log.info(`XSS防护中间件已加载: 模式=${middleware.config.mode}, 过滤=${middleware.config.query ? 'query' : ''}${middleware.config.body ? ' body' : ''}${middleware.config.cookie ? ' cookie' : ''}`);
263
- }
264
-
265
- return server;
266
- };
267
-
268
- // 保留原始实例,以便其他方式调用
269
- exports.middleware = middleware;