Compare commits

..
286 Commits
Author SHA1 Message Date
Mr Chen 9b83a2ef79 Merge pull request #216 from midoks/dev
0.9.14
2022-10-23 01:12:02 +08:00
midoks 6aefa3b7dc Update config_api.py 2022-10-23 01:11:20 +08:00
midoks 566fabbf24 Update README.md 2022-10-23 01:08:41 +08:00
midoks ea8aa5102b Update common.lua 2022-10-23 00:41:39 +08:00
midoks b8421d36ae up 2022-10-23 00:37:42 +08:00
midoks 24bd8daca0 Update install.sh 2022-10-22 22:57:04 +08:00
midoks d8047b43fa Update install.sh 2022-10-22 22:49:32 +08:00
midoks 016dde04e7 Update my8.0.cnf 2022-10-22 22:36:33 +08:00
midoks df5d86a883 Update README.md 2022-10-22 22:26:55 +08:00
midoks 84077de5d1 Update common.lua 2022-10-22 22:22:53 +08:00
midoks 04ed4b180a up 2022-10-22 21:58:35 +08:00
midoks f980dba7ed up 2022-10-22 21:36:12 +08:00
midoks f702f70f89 up 2022-10-22 20:25:46 +08:00
midoks a8e6ee052c init 2022-10-22 18:32:11 +08:00
midoks b3d0a36dcd up 2022-10-22 16:29:11 +08:00
midoks 96275303c6 Update index.py 2022-10-22 13:30:08 +08:00
midoks 0337a1bded up 2022-10-22 13:19:35 +08:00
midoks 8bd985fca9 up 2022-10-21 19:53:36 +08:00
midoks b6ef8d1625 up 2022-10-21 19:16:07 +08:00
midoks 3dc695508f up 2022-10-21 19:09:34 +08:00
midoks 0c769b02e5 Update op_waf.js 2022-10-21 17:45:30 +08:00
midoks e289037598 up 2022-10-21 17:34:38 +08:00
midoks 63e6a95553 up 2022-10-21 12:08:43 +08:00
midoks 8e1d95bf82 up 2022-10-21 01:33:35 +08:00
midoks 24fe8b6f5f up 2022-10-21 01:25:57 +08:00
midoks 3d366ee774 up 2022-10-20 23:40:28 +08:00
midoks 0428956141 up 2022-10-20 20:59:15 +08:00
midoks 37747427be up 2022-10-20 17:59:16 +08:00
midoks fb94fb8304 up 2022-10-20 16:31:30 +08:00
midoks 65d07d3934 0.2.2 2022-10-20 14:52:51 +08:00
midoks 5e6ffafeb5 Update install.sh 2022-10-20 14:10:20 +08:00
midoks 572f231fae up 2022-10-20 14:03:17 +08:00
midoks 0328dd21e7 Update webstats_common.lua 2022-10-20 13:20:54 +08:00
midoks 597d171733 Update webstats_common.lua 2022-10-20 13:10:40 +08:00
midoks 745ab9dcd0 Update webstats_common.lua 2022-10-20 12:59:26 +08:00
midoks 30323b031c Update webstats_common.lua 2022-10-20 12:58:41 +08:00
midoks f47e6a47df Update webstats_common.lua 2022-10-20 12:57:20 +08:00
midoks 0eccebd9da Update webstats_common.lua 2022-10-20 12:45:24 +08:00
midoks 0ad5e74fae Update webstats_common.lua 2022-10-20 12:38:54 +08:00
midoks 2640ba97c5 Update webstats_common.lua 2022-10-18 18:03:35 +08:00
midoks e5f440ff02 up 2022-10-18 17:41:29 +08:00
midoks 7bc9c44ec1 Update webstats_log.lua 2022-10-18 16:38:18 +08:00
midoks 9cd74db011 Update webstats_common.lua 2022-10-18 03:14:00 +08:00
midoks 5da8e5a7f6 Update webstats_common.lua 2022-10-18 03:07:12 +08:00
midoks 4da895b8df Update webstats_common.lua 2022-10-18 02:54:31 +08:00
midoks 42eca14168 Update webstats_common.lua 2022-10-18 02:13:07 +08:00
midoks 43a3dfd9bd Update webstats_common.lua 2022-10-18 01:48:18 +08:00
midoks 794eba4186 Update webstats_common.lua 2022-10-18 01:41:26 +08:00
midoks a4f533acba Update webstats_common.lua 2022-10-18 01:20:08 +08:00
midoks adb3c5250c Update webstats_common.lua 2022-10-18 01:08:05 +08:00
midoks e4226fcdd4 Update webstats_log.lua 2022-10-18 00:58:08 +08:00
midoks d3e9353589 up 2022-10-18 00:56:31 +08:00
midoks 757284cdf1 up 2022-10-17 23:48:20 +08:00
midoks 58232e10ab Update index.py 2022-10-17 23:40:44 +08:00
midoks fde211e026 Update webstats_log.lua 2022-10-17 23:30:34 +08:00
midoks c9a527e487 up 2022-10-17 23:29:57 +08:00
midoks c501efdfac up 2022-10-17 21:12:42 +08:00
midoks 80c0bbed71 Update webstats_log.lua 2022-10-17 14:54:53 +08:00
midoks 1fb3c30775 Update webstats_log.lua 2022-10-17 14:29:52 +08:00
midoks 24ab203770 Update webstats_log.lua 2022-10-17 14:08:00 +08:00
midoks bd0242db2f Update webstats_common.lua 2022-10-17 14:03:35 +08:00
midoks 42bf5edd1f Update webstats_common.lua 2022-10-17 13:45:21 +08:00
midoks 7b2a011b6a Update webstats_common.lua 2022-10-17 13:44:35 +08:00
midoks 76e01201a2 Update webstats_common.lua 2022-10-17 13:31:36 +08:00
midoks 16e45cabfc Update webstats_common.lua 2022-10-17 13:30:30 +08:00
midoks c08542ff54 Update webstats_common.lua 2022-10-17 13:23:48 +08:00
midoks 5beb76d0b7 Update webstats_common.lua 2022-10-17 13:07:22 +08:00
midoks f16a7e016e up 2022-10-17 13:06:34 +08:00
midoks eb86ac3ee6 Update webstats_common.lua 2022-10-17 12:17:37 +08:00
midoks 14c2606532 Update webstats_common.lua 2022-10-17 12:12:17 +08:00
midoks 86b8939cb8 Update webstats_common.lua 2022-10-17 12:10:15 +08:00
midoks dd28c1ef56 Update webstats_common.lua 2022-10-17 11:43:37 +08:00
midoks 6b24dfc21e Update webstats_common.lua 2022-10-17 11:36:29 +08:00
midoks dc06573125 Update webstats_common.lua 2022-10-17 03:03:32 +08:00
midoks df35e5a780 Update webstats_common.lua 2022-10-17 02:56:28 +08:00
midoks a678d851a0 Update webstats_common.lua 2022-10-17 02:49:16 +08:00
midoks 6a706651e4 Update webstats_common.lua 2022-10-17 02:45:18 +08:00
midoks 1acdfe4368 Update webstats_common.lua 2022-10-17 02:30:36 +08:00
midoks cae245efca up 2022-10-17 02:04:01 +08:00
midoks 238f1e76d8 Update webstats.conf 2022-10-17 01:09:57 +08:00
midoks f3a754d1ae Update webstats_common.lua 2022-10-17 01:06:50 +08:00
midoks 21aab0573a Update webstats_common.lua 2022-10-17 00:58:20 +08:00
midoks 011949ba85 up 2022-10-17 00:44:04 +08:00
midoks f3e7dd1cc0 Update init_worker.lua 2022-10-15 23:44:53 +08:00
midoks b49d2025eb Update install.sh 2022-10-15 23:38:12 +08:00
midoks 556b0869f2 Update config.json 2022-10-15 23:34:20 +08:00
midoks aad6deeb78 Update init_worker.lua 2022-10-15 23:28:36 +08:00
midoks 64601e42c1 up 2022-10-15 23:16:25 +08:00
midoks 6555d927ea Update common.lua 2022-10-15 21:20:40 +08:00
midoks 444ff40570 up 2022-10-15 19:13:01 +08:00
midoks 7bdcd0ac2b up 2022-10-15 17:38:42 +08:00
midoks 6e6a41e6df Update ngx_demo.sh 2022-10-15 10:03:22 +08:00
midoks feca2a6d33 aa 2022-10-15 03:23:08 +08:00
midoks 5e382e7347 Update init.lua 2022-10-15 03:16:02 +08:00
midoks abc778fb52 up 2022-10-15 02:05:29 +08:00
midoks 6b42d35cd4 up 2022-10-15 00:34:14 +08:00
midoks c74a2c9655 Update common.lua 2022-10-14 23:46:10 +08:00
midoks 01543f951a Update init.lua 2022-10-14 23:45:57 +08:00
midoks d78a5d8f27 Update init.lua 2022-10-14 23:45:43 +08:00
midoks 2a1d759cd2 Update config.json 2022-10-14 23:23:08 +08:00
midoks 43889f83f7 up 2022-10-14 21:41:25 +08:00
midoks 79a0a93959 up 2022-10-14 17:50:26 +08:00
midoks 735cf9b872 up 2022-10-14 12:41:32 +08:00
midoks e7c318e560 Update info.json 2022-10-14 12:18:09 +08:00
midoks 78d03754f6 Update install.sh 2022-10-14 12:09:19 +08:00
midoks 67cc1cac86 Update install.sh 2022-10-14 12:08:14 +08:00
midoks 77ec90980a Update install.sh 2022-10-14 12:06:57 +08:00
midoks d07b2babfd up 2022-10-14 12:05:54 +08:00
midoks 4d9ee94038 up 2022-10-14 11:36:54 +08:00
midoks 61479d5db6 Update init.lua 2022-10-13 22:23:46 +08:00
midoks 897c28034d up 2022-10-13 22:18:57 +08:00
midoks b3fef4c104 up 2022-10-13 21:29:28 +08:00
midoks 48cec8ee47 up 2022-10-13 21:05:06 +08:00
midoks 7c369ef19f up 2022-10-13 21:03:26 +08:00
midoks 1411bb1639 up 2022-10-13 20:43:46 +08:00
midoks be875d9d8c Update soft.js 2022-10-13 17:39:41 +08:00
midoks 746dc7ee4d Update soft.js 2022-10-13 17:34:44 +08:00
midoks ea7ba7d461 软件界面优化 2022-10-13 17:29:41 +08:00
midoks 48ed4156b5 Update common.lua 2022-10-13 17:06:42 +08:00
midoks ca73d0e280 Update common.lua 2022-10-13 17:01:57 +08:00
midoks 8cef43d9a7 Update info.json 2022-10-13 16:51:13 +08:00
midoks 75445774a1 test & op 2022-10-13 16:46:44 +08:00
midoks 9b29f19b96 up 2022-10-13 14:59:49 +08:00
midoks 1e6655e7f9 Update readme.md 2022-10-13 14:46:48 +08:00
midoks 363656e06c up 2022-10-13 14:46:29 +08:00
midoks a1860bc4fc up 2022-10-13 14:21:39 +08:00
midoks f8ce39bc74 up 2022-10-13 11:46:03 +08:00
midoks 969d02ef93 Update ngx_debug.sh 2022-10-13 04:35:23 +08:00
midoks a54410df6e up 2022-10-13 04:18:47 +08:00
midoks 01e388ea45 up 2022-10-13 03:12:44 +08:00
midoks ef75f22a86 Update index.py 2022-10-13 01:38:20 +08:00
midoks 97f6b232fd Update ngx_debug.sh 2022-10-13 01:36:53 +08:00
midoks 2506f5e940 Update install.sh 2022-10-13 01:10:03 +08:00
midoks dcb23ada41 Update ngx_debug.sh 2022-10-13 01:06:32 +08:00
midoks 35e1bf048c Update ngx_debug.sh 2022-10-13 00:58:47 +08:00
midoks a9e24f8eaf Update ngx_debug.sh 2022-10-13 00:58:05 +08:00
midoks 2f4ac74f52 Create ngx_debug.sh 2022-10-13 00:42:51 +08:00
midoks 522122feb6 Update common.lua 2022-10-12 20:37:56 +08:00
midoks a3c677a926 Update common.lua 2022-10-12 19:41:35 +08:00
midoks fd1c52530e Update common.lua 2022-10-12 19:35:59 +08:00
midoks 071c690583 Update linux.conf 2022-10-12 18:04:20 +08:00
midoks 67c9cd0277 up 2022-10-12 17:51:50 +08:00
midoks 61292868ad 统计变为ngx.timer.every执行 2022-10-12 17:18:51 +08:00
midoks 54b2a00b23 Update safe_js.html 2022-10-12 16:56:36 +08:00
midoks af6d377664 Update safe_js.html 2022-10-12 16:47:29 +08:00
midoks 6d55e345b0 Update common.lua 2022-10-12 16:39:55 +08:00
midoks fab4e68d8d Update common.lua 2022-10-12 15:42:48 +08:00
midoks 8864e91f21 Update install.sh 2022-10-12 15:31:42 +08:00
midoks f14ce1b66c Update info.json 2022-10-12 15:29:03 +08:00
midoks 48098efd56 Update safe_js.html 2022-10-12 15:28:09 +08:00
midoks 04eba8e33f Update init.lua 2022-10-12 15:26:38 +08:00
midoks 89cf7ffafc Update init.lua 2022-10-12 15:19:08 +08:00
midoks 47544520e8 Update init.lua 2022-10-12 15:03:51 +08:00
midoks bc1fd9a8af Update init.lua 2022-10-12 14:51:46 +08:00
midoks 27efc7ef6e Update config_api.py 2022-10-12 14:38:45 +08:00
midoks 47ead816c0 Update init.lua 2022-10-12 14:37:43 +08:00
midoks 31d36182c3 Update init.lua 2022-10-12 14:37:11 +08:00
midoks c9a58c7ea5 Update init.lua 2022-10-12 14:36:57 +08:00
midoks a6e59ae37c Update init.lua 2022-10-12 14:36:42 +08:00
midoks 328e1b0ff1 up 2022-10-12 14:30:37 +08:00
midoks f76cc5ceb8 Update init.lua 2022-10-12 13:59:30 +08:00
midoks d6c74c3f7d waf demo 3 2022-10-12 13:49:57 +08:00
midoks 4f932c36e7 up 2022-10-12 10:11:55 +08:00
midoks 0d02d0ebea Update init.lua 2022-10-12 00:53:00 +08:00
midoks 9e207ad4d3 添加 强制安全验证 功能 2022-10-12 00:38:23 +08:00
midoks f6cfe29956 Update debian.sh 2022-10-11 18:03:36 +08:00
midoks e439111761 Update mw.py 2022-10-11 17:47:48 +08:00
midoks e576d0b443 listen.backlog = 4096 设置默认 2022-10-11 17:28:07 +08:00
midoks 02e2c42225 up 2022-10-11 17:10:13 +08:00
midoks 45dec0a3d6 ip 2022-10-11 16:35:44 +08:00
midoks 28e2abc829 demo 2022-10-11 16:26:15 +08:00
midoks d59c82b7c8 Update common.lua 2022-10-11 15:46:04 +08:00
midoks 32b2158795 Update common.lua 2022-10-11 15:45:49 +08:00
midoks 5a37305c73 Update common.lua 2022-10-11 15:45:08 +08:00
midoks c043963e8e Update common.lua 2022-10-11 15:43:10 +08:00
midoks 40d755b44e up 2022-10-11 15:39:13 +08:00
midoks 00aa791205 waf debug3 2022-10-11 15:34:02 +08:00
midoks 431b3646af waf debug2 2022-10-11 15:27:08 +08:00
midoks 910aaa81de waf debug1 2022-10-11 15:22:28 +08:00
Mr Chen c4a844cadb Merge pull request #209 from midoks/dev
0.9.13
2022-10-11 12:47:26 +08:00
midoks a88a281175 0.9.13
0.9.13
2022-10-11 12:46:35 +08:00
midoks f3f3b1c6bd Update init.lua 2022-10-11 12:35:59 +08:00
midoks 4259ac51cb up 2022-10-11 11:41:32 +08:00
midoks 4db1357d3d 更新mysql版本 2022-10-11 09:03:53 +08:00
midoks 15873e0824 Update op_waf.js 2022-10-11 00:40:21 +08:00
midoks dcdb07f76d up 2022-10-11 00:35:13 +08:00
midoks 8b70637479 Update index.py 2022-10-10 23:28:36 +08:00
midoks c77085fea4 Update index.py 2022-10-10 23:27:20 +08:00
midoks a265f3d0d5 Update index.py 2022-10-10 23:24:54 +08:00
midoks 7ea486cd1d Update index.py 2022-10-10 23:22:43 +08:00
midoks 0e31e87e28 Update index.py 2022-10-10 23:22:04 +08:00
midoks 8c621c892e Update index.py 2022-10-10 23:16:59 +08:00
midoks 32bcae603c Update index.py 2022-10-10 23:16:48 +08:00
midoks 98ec21446d Update index.py 2022-10-10 22:41:36 +08:00
midoks 0ee3682502 Update redis.service.tpl 2022-10-10 22:11:51 +08:00
midoks c609d1a012 Update redis.service.tpl 2022-10-10 22:05:55 +08:00
midoks 27b1a78879 up 2022-10-10 22:03:21 +08:00
midoks 773de840a5 Update redis.js 2022-10-10 21:55:00 +08:00
midoks 91d6ff3c54 Update index.py 2022-10-10 21:52:11 +08:00
midoks 03376bd42d Update redis.conf 2022-10-10 21:50:04 +08:00
midoks 036c5114c2 Update index.py 2022-10-10 21:35:51 +08:00
midoks a772e70fde Update index.py 2022-10-10 21:33:20 +08:00
midoks 53055bbdef Update index.py 2022-10-10 21:31:43 +08:00
midoks f81d598fcf Update index.py 2022-10-10 21:13:44 +08:00
midoks 3530e83bb9 up 2022-10-10 21:09:35 +08:00
midoks 1271b2f637 Update index.py 2022-10-10 21:00:30 +08:00
midoks 2dc6bc7753 Update index.py 2022-10-10 20:58:45 +08:00
midoks e52d9e3ea3 Update index.py 2022-10-10 20:55:45 +08:00
midoks d8a570e55e Update index.html 2022-10-10 20:46:07 +08:00
midoks f4ceaf667b php-yum更新 2022-10-10 20:43:48 +08:00
midoks 958ba16b85 Update index.html 2022-10-10 20:28:44 +08:00
midoks 73039777bb Update index.py 2022-10-10 20:06:00 +08:00
midoks 864e4c910c PHP添加会话管理功能 2022-10-10 19:54:23 +08:00
midoks 4da57405af Update init.lua 2022-10-10 13:01:27 +08:00
midoks dff638571a Update init.lua 2022-10-10 12:45:31 +08:00
midoks c7d9ec51cc up 2022-10-10 12:36:42 +08:00
midoks 501c575f73 up 2022-10-10 12:13:45 +08:00
midoks 0fd966ca65 up 2022-10-10 02:14:31 +08:00
midoks 172dde2794 Update mariadb.js 2022-10-09 23:26:50 +08:00
midoks 78fdc80652 优化mysql进入phpmyadmin 2022-10-09 23:24:47 +08:00
midoks 01b8c9b8ff Update init.lua 2022-10-09 22:47:28 +08:00
midoks b840086d4d op防火墙更新1 2022-10-09 21:29:40 +08:00
midoks 4c73f13f2d up 2022-10-09 11:36:57 +08:00
midoks f31c1aae96 up 2022-10-09 10:39:46 +08:00
midoks 5c24a831db Update index.py 2022-10-09 02:04:17 +08:00
midoks 91d07eebad Update install.sh 2022-10-09 01:59:17 +08:00
midoks 3b51ef2434 up 2022-10-09 01:49:17 +08:00
midoks 31c5e42b09 Update index.html 2022-10-09 01:38:15 +08:00
midoks b8b3a237ef up 2022-10-09 01:37:14 +08:00
midoks 5cb2aefbbc up 2022-10-09 01:25:53 +08:00
midoks 19173af3e2 Update logs_backup.py 2022-10-09 00:31:15 +08:00
midoks 3dc493108b Update mw.tpl 2022-10-09 00:30:03 +08:00
midoks 55af62000b Update logs_backup.py 2022-10-09 00:26:28 +08:00
midoks a1c8c48761 Update index.js 2022-10-08 22:45:44 +08:00
midoks 8c3ec0a103 Update index.js 2022-10-08 22:40:23 +08:00
midoks 5cbde31105 Update tool_task.py 2022-10-08 18:15:57 +08:00
midoks 04dd94032e Update tool_task.py 2022-10-08 18:12:45 +08:00
midoks 8a11195b0d Update tool_task.py 2022-10-08 18:08:38 +08:00
midoks 1eb76baae7 改变弹框方式 2022-10-08 16:05:24 +08:00
midoks 2669d6f021 Update init.lua 2022-10-08 15:21:17 +08:00
midoks 6f13a03a2c Update config_api.py 2022-10-08 14:24:58 +08:00
Mr Chen 9c97e1c41c Merge pull request #205 from midoks/dev
0.9.12
2022-10-08 14:21:46 +08:00
midoks 37245ca1e8 0.9.12
* 日志清理插件优化。
* 计划任务显示完整。
* 加入gitea插件。
* 融合mw-cli命令。
* 加快php编译速度。
* swap加上调整功能。
* 其他细节优化。
2022-10-08 14:20:47 +08:00
midoks f706a8a2ea up 2022-10-08 14:03:01 +08:00
midoks e6af6b2062 up 2022-10-07 21:29:00 +08:00
midoks f5b056c965 init 2022-10-07 01:00:02 +08:00
midoks 8c768e8a04 Create tool_task.py 2022-10-07 00:47:26 +08:00
midoks 1d6f4feccb Update soft.js 2022-10-07 00:46:32 +08:00
midoks 49c32dc9c1 Update index.py 2022-10-06 17:52:25 +08:00
midoks 17a865c45d Update install.sh 2022-10-06 17:28:37 +08:00
midoks 0090681ab2 Update index.py 2022-10-06 17:25:15 +08:00
midoks 4d3a6c27f7 up 2022-10-06 17:19:36 +08:00
midoks abf39428fc Update index.py 2022-10-06 17:08:46 +08:00
midoks ec11904959 up 2022-10-06 17:07:26 +08:00
midoks d18f16a2b8 up 2022-10-06 15:32:30 +08:00
midoks 7fbe421b0c 加快php编译速度 2022-10-06 14:16:46 +08:00
midoks 81c7929240 Update install.sh 2022-10-06 14:09:46 +08:00
midoks 76c655872b Update install.sh 2022-10-06 14:09:22 +08:00
midoks 7b09776392 Update install.sh 2022-10-06 14:08:52 +08:00
midoks 0b28077e08 up 2022-10-06 14:07:10 +08:00
midoks ccc00e8b5d 更新版本 2022-10-06 13:40:52 +08:00
midoks 202e04c62d Update install.sh 2022-10-06 13:30:50 +08:00
midoks 01cd35305e Update ubuntu.sh 2022-10-06 13:10:44 +08:00
midoks 2f0d7d1d07 融合mw-cli结束2 2022-10-06 11:22:42 +08:00
midoks 714af23627 融合mw-cli结束 2022-10-06 11:13:09 +08:00
midoks 0a9eb721c6 Delete mw-cli 2022-10-06 11:12:18 +08:00
midoks 5e71c20e2a up 2022-10-06 11:12:01 +08:00
midoks 3c24d9f9a9 Update mw.tpl 2022-10-06 09:32:46 +08:00
midoks 78bdcb79c8 Update index.py 2022-10-05 20:51:38 +08:00
midoks aaf3389460 Update index.py 2022-10-05 20:50:39 +08:00
midoks 9f2cb58812 Update index.py 2022-10-05 20:50:31 +08:00
midoks c6099fb7ce Update gitea.service.tpl 2022-10-05 20:45:01 +08:00
midoks 3fb4d88c4a Update gitea.service.tpl 2022-10-05 20:44:43 +08:00
midoks f90fec182c Update install.sh 2022-10-05 20:39:55 +08:00
midoks ba86217a1a Update mw.py 2022-10-05 20:37:02 +08:00
midoks 9a7bcdc1c4 up 2022-10-05 20:34:43 +08:00
midoks 43b1f5ed86 Update gitea.service.tpl 2022-10-05 20:08:41 +08:00
midoks 68ca194c2d Update gitea.service.tpl 2022-10-05 20:05:27 +08:00
midoks 061eaabe79 Update gitea.service.tpl 2022-10-05 19:50:08 +08:00
midoks 420e830ed9 Update crontab_api.py 2022-10-05 17:52:09 +08:00
midoks 8e9cba6646 Update phplib.conf 2022-10-05 14:06:20 +08:00
midoks e0c183c1ac 加入gitea 2022-10-03 12:27:44 +08:00
midoks 18c59da28d Update crontab.js 2022-10-02 15:33:14 +08:00
midoks 71f2d66966 计划任务 显示完整 2022-10-02 15:23:29 +08:00
midoks abd6cdd738 日志清理 插件优化 2022-10-02 15:05:13 +08:00
midoks dd7b1707c3 Update README.md 2022-10-02 09:33:21 +08:00
146 changed files with 7643 additions and 7428 deletions
+5
View File
@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: midoks
custom: https://afdian.net/a/mdserver-web
+7 -9
View File
@@ -65,6 +65,8 @@ phpMyAdmin[5.2.0]支持MySQL[8.0]
PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-81]支持phpMyAdmin[5.2.0]
```
# 特别赞助
@@ -78,7 +80,7 @@ PHP[72-81]支持phpMyAdmin[5.2.0]
| 服务商 | LOGO | 推广地址 | 优惠码 |
| ------------- |----------|-----------|-------|
| digitalvirt |[![digitalvirt](https://digitalvirt.com/templates/BlueWhite/img/logo-dark.svg)](https://digitalvirt.com/aff.php?aff=154) | https://digitalvirt.com/aff.php?aff=154 | 9SYDY7UH0U |
| 搬瓦工 |[![搬瓦工](https://bwh81.net/templates/organicbandwagon/images/logo.png)](https://bandwagonhost.com/aff.php?aff=54161) | https://bandwagonhost.com/aff.php?aff=54161 | BWH3HYATVBJW |
| 搬瓦工 |[![搬瓦工](https://bwh81.net/templates/organicbandwagon/images/logo.png)](https://bwh81.net/aff.php?aff=54161) | https://bwh81.net/aff.php?aff=54161 | BWH3HYATVBJW |
# Docker
@@ -90,15 +92,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.9.11
* 大文件解压优化。
* 防火墙api优化。
* mysql|mariadb安装删除冗余账户。
* imail插件添加。
* 安装面板初始化安装时不再固定端口[7200],优化为随机端口。
* redis添加性能调整功能。
### 版本更新 0.9.14
* 优化网站统计插件,提搞速度和并发数。
* mysql8安装地址更新。
* OP防火墙优化。
### JSDelivr安装地址
+1 -1
View File
@@ -15,7 +15,7 @@ from flask import request
class config_api:
__version = '0.9.11'
__version = '0.9.14'
def __init__(self):
pass
+4 -4
View File
@@ -414,10 +414,10 @@ class crontab_api:
script_dir = mw.getServerDir() + "/mdserver-web/scripts"
wheres = {
'path': head + "python " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']),
'site': head + "python " + script_dir + "/backup.py site " + param['sname'] + " " + str(param['save']),
'database': head + "python " + script_dir + "/backup.py database " + param['sname'] + " " + str(param['save']),
'logs': head + "python " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'path': head + "python3 " + script_dir + "/backup.py path " + param['sname'] + " " + str(param['save']),
'site': head + "python3 " + script_dir + "/backup.py site " + param['sname'] + " " + str(param['save']),
'database': head + "python3 " + script_dir + "/backup.py database " + param['sname'] + " " + str(param['save']),
'logs': head + "python3 " + script_dir + "/logs_backup.py " + param['sname'] + log + " " + str(param['save']),
'rememory': head + "/bin/bash " + script_dir + '/rememory.sh'
}
if param['backup_to'] != 'localhost':
+14 -7
View File
@@ -161,19 +161,24 @@ def isInstalledWeb():
def restartWeb():
return opWeb("reload")
def opWeb(method):
if not isInstalledWeb():
return False
# systemd
systemd = '/lib/systemd/system/openresty.service'
if os.path.exists(systemd):
execShell('systemctl reload openresty')
execShell('systemctl ' + method + ' openresty')
return True
# initd
initd = getServerDir() + '/openresty/init.d/openresty'
if os.path.exists(initd):
execShell(initd + ' ' + 'reload')
execShell(initd + ' ' + method)
return True
return False
@@ -552,7 +557,7 @@ def getSpeed():
return json.loads(data)
def getLastLine(inputfile, lineNum):
def getLastLineBk(inputfile, lineNum):
# 读文件指定倒数行数
try:
fp = open(inputfile, 'rb')
@@ -585,7 +590,7 @@ def getLastLine(inputfile, lineNum):
# return getMsg('TASK_SLEEP')
def getNumLines(path, num, p=1):
def getLastLine(path, num, p=1):
pyVersion = sys.version_info[0]
try:
import html
@@ -595,12 +600,14 @@ def getNumLines(path, num, p=1):
count = start_line + num
fp = open(path, 'rb')
buf = ""
fp.seek(-1, 2)
fp.seek(0, 2)
if fp.read(1) == "\n":
fp.seek(-1, 2)
fp.seek(0, 2)
data = []
b = True
n = 0
for i in range(count):
while True:
newline_pos = str.rfind(str(buf), "\n")
@@ -624,7 +631,7 @@ def getNumLines(path, num, p=1):
t_buf = fp.read(to_read)
if pyVersion == 3:
if type(t_buf) == bytes:
t_buf = t_buf.decode('utf-8')
t_buf = t_buf.decode("utf-8", "ignore").strip()
buf = t_buf + buf
fp.seek(-to_read, 1)
if pos - to_read == 0:
-86
View File
@@ -1,86 +0,0 @@
#!/www/server/mdserver-web/bin/python
# description: mdserver-web cli tools
# ln -s /www/server/mdserver-web/mw-cli /usr/bin/mw-cli
import os
import sys
def mw_start():
"""
Start mdserver-web
"""
os.system('systemctl start mw')
print("服务已启动")
def mw_stop():
"""
stop mdserver-web
"""
os.system('systemctl stop mw')
print("服务已停止")
def mw_restart():
"""
restart mdserver-web
"""
os.system('systemctl restart mw')
print("服务已重启")
def mw_reset_username():
"""
reset mdserver-web username
"""
from tools import set_panel_username
user_name = input("请输入新的用户名: ")
set_panel_username(user_name)
def mw_reset_pwd():
"""
reset mdserver-web password
"""
from tools import set_panel_pwd
pwd = input("请输入新的密码: ")
set_panel_pwd(pwd, True)
if __name__ == '__main__':
if os.geteuid() != 0:
print("请使用root账户执行该命令.")
sys.exit(1)
os.chdir("/www/server/mdserver-web")
sys.path.append(os.getcwd() + "/class/core")
try:
str = '''
==== mdserver-web cli tools ====
1. 启动服务 2. 停止服务
3. 重启服务 4. 修改用户名
5. 修改密码
=================================
'''
if len(sys.argv) == 2:
sw = sys.argv[1]
else:
print(str)
sw = input("请输入您要进行的操作: ")
if sw == '1':
mw_start()
elif sw == '2':
mw_stop()
elif sw == '3':
mw_restart()
elif sw == '4':
mw_reset_username()
elif sw == '5':
mw_reset_pwd()
else:
print("操作不存在")
except KeyboardInterrupt:
print("\n操作已终止")
+5 -1
View File
@@ -3,6 +3,7 @@
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('clean');">服务</p>
<p onclick="pluginConfig('clean');">配置修改</p>
<p onclick="pluginLogs('clean',null,'run_log');">运行日志</p>
<p onclick="pRead()">说明</p>
</div>
<div class="bt-w-con pd15">
@@ -16,7 +17,10 @@ pluginService('clean');
function pRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>cd /www/server/mdserver-web && python3 /www/server/mdserver-web/plugins/clean/index.py clean</li>';
readme += '<li>启动后,假如到计划中[2:30]执行。</li>';
readme += '<li>【*】代表要删除。</li>';
readme += '<li>添加/删除清除日志,可在`配置修改`中添加/删除。</li>';
readme += '<li>如果是目录,会寻找【.log】后缀的文件清空。</li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
+96 -70
View File
@@ -53,34 +53,95 @@ def getArgs():
return tmp
def getLockFile():
return getServerDir() + "/installed_lock.pl"
def runLog():
return getServerDir() + "/clean.log"
def status():
if os.path.exists(getConf()):
initConf()
if os.path.exists(getLockFile()):
return "start"
return 'stop'
def initConf():
conf = getConf()
if not os.path.exists(conf):
content = ""
clog = [
"/var/log/cron-*",
"/var/log/maillog-*",
"/var/log/secure-*",
"/var/log/spooler-*",
"/var/log/yum.log-*",
"/var/log/messages-*",
"/var/log/btmp-*",
"/var/log/audit/audit.log.*",
"/var/log/rhsm/rhsm.log-*",
"/var/log/rhsm/rhsmcertd.log-*",
"/tmp/yum_save_*",
"/tmp/tmp.*",
]
for i in clog:
content += i + "\n"
# 常用日志
clogcom = [
"/var/log/messages",
"/var/log/btmp",
"/var/log/wtmp",
"/var/log/secure",
"/var/log/lastlog",
"/var/log/cron",
"/www/server/cron"
]
for i in clogcom:
if os.path.exists(i):
content += i + "\n"
# 清理日志
rootDir = "/var/log"
l = os.listdir(rootDir)
for x in range(len(l)):
abspath = rootDir + "/" + l[x]
content += abspath + "\n"
mw.writeFile(conf, content)
def start():
file = initDreplace()
data = mw.execShell(file + ' start')
if data[1] == '':
initConf()
lock_file = getLockFile()
if not os.path.exists(lock_file):
mw.writeFile(lock_file, "")
import tool_task
tool_task.createBgTask()
return 'ok'
return 'fail'
def stop():
file = initDreplace()
data = mw.execShell(file + ' stop')
if data[1] == '':
initConf()
lock_file = getLockFile()
if os.path.exists(lock_file):
os.remove(lock_file)
import tool_task
tool_task.removeBgTask()
return 'ok'
return 'fail'
def reload():
file = initDreplace()
data = mw.execShell(file + ' reload')
if data[1] == '':
return 'ok'
return 'fail'
return 'ok'
def get_filePath_fileName_fileExt(filename):
@@ -93,15 +154,20 @@ def cleanFileLog(path):
filepath, shotname, extension = get_filePath_fileName_fileExt(path)
if extension == ".log":
cmd = "echo \"\" > " + path
tmp = mw.execShell(cmd)
if tmp[1] != "":
cmd += " | error:" + tmp[1].strip()
print(cmd)
print(mw.execShell(cmd))
def cleanSelfFileLog(path):
filepath, shotname, extension = get_filePath_fileName_fileExt(path)
cmd = "echo \"\" > " + path
print(cmd)
print(mw.execShell(cmd))
if extension == ".log":
cmd = "echo \"\" > " + path
tmp = mw.execShell(cmd)
if tmp[1] != "":
cmd += " | error:" + tmp[1].strip()
print(cmd)
def cleanDirLog(path):
@@ -115,70 +181,28 @@ def cleanDirLog(path):
def cleanLog():
# 清理日志
rootDir = "/var/log"
print("clean start")
clog = [
"rm -rf /var/log/cron-*",
"rm -rf /var/log/maillog-*",
"rm -rf /var/log/secure-*",
"rm -rf /var/log/spooler-*",
"rm -rf /var/log/yum.log-*",
"rm -rf /var/log/messages-*",
"rm -rf /var/log/btmp-*",
"rm -rf /var/log/audit/audit.log.*",
"rm -rf /var/log/rhsm/rhsm.log-*",
"rm -rf /var/log/rhsm/rhsmcertd.log-*",
"rm -rf /tmp/yum_save_*",
"rm -rf /tmp/tmp.*",
]
for i in clog:
print(i)
mw.execShell(i)
# 常用日志
clogcom = [
"/var/log/messages",
"/var/log/btmp",
"/var/log/wtmp",
"/var/log/secure",
"/var/log/lastlog",
"/var/log/cron",
]
for i in clogcom:
if os.path.exists(i):
mw.execShell("echo \"\" > " + i)
l = os.listdir(rootDir)
for x in range(len(l)):
abspath = rootDir + "/" + l[x]
if os.path.isfile(abspath):
cleanFileLog(abspath)
if os.path.isdir(abspath):
cleanDirLog(abspath)
print("conf clean")
confFile = getServerDir()
# mw.readFile()
confFile = confFile + "/clean.conf"
clist = mw.readFile(confFile).strip()
conf = getConf()
clist = mw.readFile(conf).strip()
clist = clist.split("\n")
for x in clist:
abspath = x.strip()
if abspath.find('*') > 1:
cmd = 'rm -rf ' + abspath
print(cmd)
data = mw.execShell(cmd)
# print(data)
continue
if os.path.exists(abspath):
if os.path.isfile(abspath):
cleanSelfFileLog(abspath)
continue
if os.path.isdir(abspath):
cleanDirLog(abspath)
print("conf clean end")
print("clean end")
continue
if __name__ == "__main__":
func = sys.argv[1]
@@ -194,6 +218,8 @@ if __name__ == "__main__":
print(reload())
elif func == 'conf':
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'clean':
cleanLog()
else:
+6 -2
View File
@@ -13,20 +13,24 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
VERSION=$2
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
Install_app()
{
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/clean
echo "" > $serverPath/clean/clean.conf
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py start
echo "${VERSION}" > $serverPath/clean/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_app()
{
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py stop
rm -rf $serverPath/clean
echo "Uninstall_clean" > $install_tmp
}
+156
View File
@@ -0,0 +1,156 @@
# coding:utf-8
import sys
import io
import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'clean'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
try:
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return []
def getConfigTpl():
tpl = {
"name": "",
"task_id": -1,
}
return tpl
def createBgTask():
removeBgTask()
args = {
"period": "day",
"hour": "2",
"minute": "30",
}
createBgTaskByName(getPluginName(), args)
def createBgTaskByName(name, args):
cfg = getConfigTpl()
_name = "[勿删]日志清理[" + name + "]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
api = crontab_api.crontab_api()
period = args['period']
_hour = ''
_minute = ''
_where1 = ''
_type_day = "day"
if period == 'day':
_type_day = 'day'
_hour = args['hour']
_minute = args['minute']
elif period == 'minute-n':
_type_day = 'minute-n'
_where1 = args['minute-n']
_minute = ''
mw_dir = mw.getRunDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
logs_file=$plugin_path/${rname}.log
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/index.py clean >> $logs_file 2>&1"' + "\n"
cmd += 'cd $mw_dir && python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
params = {
'name': _name,
'type': _type_day,
'week': "",
'where1': _where1,
'hour': _hour,
'minute': _minute,
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
}
task_id = api.add(params)
if task_id > 0:
cfg["task_id"] = task_id
cfg["name"] = name
_dd = getConfigData()
_dd.append(cfg)
mw.writeFile(getTaskConf(), json.dumps(_dd))
def removeBgTask():
cfg_list = getConfigData()
for x in range(len(cfg_list)):
cfg = cfg_list[x]
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
cfg_list[x] = cfg
mw.writeFile(getTaskConf(), '[]')
return True
return False
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
echo `date`
GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}.git"
GIT_SDIR="{$CODE_DIR}"
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
git config --global credential.helper store
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
git clone $GITADDR
fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
# cd $GIT_PROJECT_DIR && env -i git pull origin master
#更新的目的地址
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
sysName=`uname`
if [ $sysName == 'Darwin' ]; then
USER=$(who | sed -n "2,1p" |awk '{print $1}')
chown -R $USER:staff $WEB_PATH
else
chown -R www:www $WEB_PATH
fi
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
echo `date`
GITADDR="{$GITROOTURL}/{$USERNAME}/{$PROJECT}"
GIT_SDIR="{$CODE_DIR}"
GIT_USER_DIR="${GIT_SDIR}/{$USERNAME}"
GIT_PROJECT_DIR="${GIT_USER_DIR}/{$PROJECT}"
# echo $GIT_PROJECT_DIR
if [ ! -d $GIT_PROJECT_DIR ];then
mkdir -p $GIT_USER_DIR && cd $GIT_USER_DIR
git clone $GITADDR
fi
unset GIT_DIR
cd $GIT_PROJECT_DIR && git pull
# func 2
# cd $GIT_PROJECT_DIR && env -i git pull origin master
WEB_PATH={$WEB_ROOT}/{$USERNAME}/{$PROJECT}
mkdir -p $WEB_PATH
rsync -vauP --delete --exclude=".*" $GIT_PROJECT_DIR/ $WEB_PATH
sysName=`uname`
if [ $sysName == 'Darwin' ]; then
USER=$(who | sed -n "2,1p" |awk '{print $1}')
chown -R $USER:staff $WEB_PATH
else
chown -R www:www $WEB_PATH
fi
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
sh -x {$PATH}/commit 2>{$PATH}/sh.log
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+24
View File
@@ -0,0 +1,24 @@
<div class="bt-form">
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('gitea');">服务</p>
<p onclick="pluginInitD('gitea');">自启动</p>
<!-- <p onclick="pluginConfig('gitea',null, 'init_conf');">启动配置</p> -->
<p onclick="gogsEdit();">手动编辑</p>
<p onclick="pluginConfig('gitea',null, 'conf');">配置文件</p>
<p onclick="gogsSetConfig();">配置修改</p>
<p onclick="giteaUserList();">用户列表</p>
<p onclick="pluginLogs('gitea',null,'run_log');">运行日志</p>
<p onclick="pluginLogs('gitea',null,'post_receive_log');" title="提交post-receive日志">提交日志</p>
<p onclick="giteaRead();">使用说明</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=gitea&f=js/gitea.js",function(){
pluginService('gitea');
});
</script>
@@ -11,11 +11,10 @@ sys.path.append(os.getcwd() + "/class/core")
import mw
cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
info = mw.execShell(cmd)
p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
sys.path.append(p)
import psutil
# cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
# info = mw.execShell(cmd)
# p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
# sys.path.append(p)
app_debug = False
@@ -24,15 +23,12 @@ if mw.isAppleSystem():
def getPluginName():
return 'gogs'
return 'gitea'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
import mysqlDb
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
@@ -61,18 +57,28 @@ def getArgs():
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def getInitdConfTpl():
path = getPluginDir() + "/init.d/gogs.tpl"
path = getPluginDir() + "/init.d/gitea.tpl"
return path
def getInitdConf():
path = getServerDir() + "/init.d/gogs"
path = getServerDir() + "/init.d/gitea"
return path
def getConf():
path = getServerDir() + "/custom/conf/app.ini"
if not os.path.exists(path):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
return path
@@ -95,7 +101,7 @@ def getHomeDir():
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return '/Users/' + user
else:
return '/root'
return 'git'
def getRunUser():
@@ -104,7 +110,7 @@ def getRunUser():
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
return user
else:
return 'root'
return 'git'
__SR = '''#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
@@ -140,13 +146,16 @@ def initDreplace():
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
conf_bin = getConf()
if not os.path.exists(conf_bin):
mw.execShell('mkdir -p ' + getServerDir() + '/custom/conf')
conf_tpl = getConfTpl()
content = mw.readFile(conf_tpl)
content = contentReplace(content)
mw.writeFile(conf_bin, content)
# systemd
systemDir = mw.systemdCfgDir()
systemService = systemDir + '/gitea.service'
systemServiceTpl = getPluginDir() + '/init.d/gitea.service.tpl'
if os.path.exists(systemDir) and not os.path.exists(systemService):
service_path = mw.getServerDir()
se_content = mw.readFile(systemServiceTpl)
se_content = se_content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(systemService, se_content)
mw.execShell('systemctl daemon-reload')
log_path = getServerDir() + '/log'
if not os.path.exists(log_path):
@@ -159,9 +168,14 @@ def getRootUrl():
content = mw.readFile(getConf())
rep = 'ROOT_URL\s*=\s*(.*)'
tmp = re.search(rep, content)
if not tmp:
return ''
return tmp.groups()[0]
if tmp:
return tmp.groups()[0]
rep = 'EXTERNAL_URL\s*=\s*(.*)'
tmp = re.search(rep, content)
if tmp:
return tmp.groups()[0]
return ''
def getSshPort():
@@ -192,8 +206,11 @@ def getRootPath():
def getDbConfValue():
content = mw.readFile(getConf())
conf = getConf()
if not os.path.exists(conf):
return {}
content = mw.readFile(conf)
rep_scope = "\[database\](.*?)\["
tmp = re.findall(rep_scope, content, re.S)
@@ -207,18 +224,72 @@ def getDbConfValue():
return r
def pMysqlDb():
conf = getDbConfValue()
def pMysqlDb(conf):
host = conf['HOST'].split(':')
conn = mysqlDb.mysqlDb()
# pymysql
db = mw.getMyORM()
# MySQLdb |
# db = mw.getMyORMDb()
conn.setHost(host[0])
conn.setUser(conf['USER'])
conn.setPwd(conf['PASSWD'])
conn.setPort(int(host[1]))
conn.setDb(conf['NAME'])
return conn
db.setPort(int(host[1]))
db.setUser(conf['USER'])
if 'PASSWD' in conf:
db.setPwd(conf['PASSWD'])
else:
db.setPwd(conf['PASSWORD'])
db.setDbName(conf['NAME'])
# db.setSocket(getSocketFile())
db.setCharset("utf8")
return db
def pSqliteDb(conf):
# print(conf)
import db
psDb = db.Sql()
# 默认
gsdir = getServerDir() + '/data'
dbname = 'gitea'
if conf['PATH'][0] == '/':
# 绝对路径
pass
else:
path = conf['PATH'].split('/')
gsdir = getServerDir() + '/' + path[0]
dbname = path[1].split('.')[0]
# print(gsdir, dbname)
psDb.dbPos(gsdir, dbname)
return psDb
def getGiteaDbType(conf):
if 'DB_TYPE' in conf:
return conf['DB_TYPE']
if 'TYPE' in conf:
return conf['TYPE']
return 'NONE'
def pQuery(sql):
conf = getDbConfValue()
gtype = getGiteaDbType(conf)
if gtype == 'sqlite3':
db = pSqliteDb(conf)
data = db.query(sql, []).fetchall()
return data
elif gtype == 'mysql':
db = pMysqlDb(conf)
return db.query(sql)
print("仅支持mysql|sqlite3配置")
exit(0)
def isSqlError(mysqlMsg):
@@ -244,93 +315,66 @@ def isSqlError(mysqlMsg):
return mw.returnData(True, 'OK')
def start():
is_frist = True
conf_bin = getConf()
if os.path.exists(conf_bin):
is_frist = False
def appOp(method):
file = initDreplace()
if is_frist:
return "第一次启动Gogs,默认使用MySQL连接!<br>可以在配置文件中重新设置,再启动!"
if not mw.isAppleSystem():
data = mw.execShell('systemctl ' + method + ' ' + getPluginName())
if data[1] == '':
return 'ok'
return 'fail'
conn = pMysqlDb()
list_table = conn.query('show tables')
data = isSqlError(list_table)
if not data['status']:
return data['msg']
data = mw.execShell(__SR + file + ' start')
data = mw.execShell(__SR + file + ' ' + method)
if data[1] == '':
return 'ok'
return data[0]
def start():
return appOp('start')
def stop():
file = initDreplace()
data = mw.execShell(__SR + file + ' stop')
if data[1] == '':
return 'ok'
return data[1]
return appOp('stop')
def restart():
file = initDreplace()
data = mw.execShell(__SR + file + ' restart')
if data[1] == '':
return 'ok'
return data[1]
return appOp('restart')
def reload():
file = initDreplace()
data = mw.execShell(__SR + file + ' reload')
if data[1] == '':
return 'ok'
return data[1]
return appOp('reload')
def initdStatus():
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
if mw.isAppleSystem():
return "Apple Computer does not support"
shell_cmd = 'systemctl status gitea | grep loaded | grep "enabled;"'
data = mw.execShell(shell_cmd)
if data[0] == '':
return 'fail'
return 'ok'
def initdInstall():
import shutil
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
if mw.isAppleSystem():
return "Apple Computer does not support"
mem_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(mem_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName())
mw.execShell('systemctl enable gitea')
return 'ok'
def initdUinstall():
if not app_debug:
os_name = mw.getOs()
if os_name == 'darwin':
return "Apple Computer does not support"
initd_bin = getInitDFile()
os.remove(initd_bin)
mw.execShell('chkconfig --del ' + getPluginName())
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('systemctl disable gitea')
return 'ok'
def runLog():
log_path = getServerDir() + '/log/gogs.log'
log_path = getServerDir() + '/log/gitea.log'
return log_path
@@ -340,6 +384,10 @@ def postReceiveLog():
def getGogsConf():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
gets = [
{'name': 'DOMAIN', 'type': -1, 'ps': '服务器域名'},
{'name': 'ROOT_URL', 'type': -1, 'ps': '公开的完整URL路径'},
@@ -360,7 +408,7 @@ def getGogsConf():
{'name': 'SHOW_FOOTER_VERSION', 'type': 2, 'ps': 'Gogs版本信息'},
{'name': 'SHOW_FOOTER_TEMPLATE_LOAD_TIME', 'type': 2, 'ps': 'Gogs模板加载时间'},
]
conf = mw.readFile(getConf())
conf = mw.readFile(conf)
result = []
for g in gets:
@@ -370,7 +418,7 @@ def getGogsConf():
continue
g['value'] = tmp.groups()[0]
result.append(g)
return mw.getJson(result)
return mw.returnJson(True, 'OK', result)
def submitGogsConf():
@@ -402,18 +450,27 @@ def submitGogsConf():
def userList():
conf = getConf()
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGiteaDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
page = 1
page_size = 10
data = checkArgs(args, ['page', 'page_size'])
if not data[0]:
return data[1]
page = int(args['page'])
page_size = int(args['page_size'])
tojs = args['tojs']
search = ''
if 'page' in args:
page = int(args['page'])
if 'page_size' in args:
page_size = int(args['page_size'])
if 'search' in args:
search = args['search']
@@ -421,17 +478,14 @@ def userList():
data['root_url'] = getRootUrl()
pm = pMysqlDb()
start = (page - 1) * page_size
list_count = pm.query('select count(id) as num from user')
count = list_count[0][0]
list_count = pQuery('select count(id) as num from user')
list_data = pm.query(
count = list_count[0]["num"]
list_data = pQuery(
'select id,name,email from user order by id desc limit ' + str(start) + ',' + str(page_size))
page_info = {'count': count, 'p': page,
'row': page_size, 'tojs': 'gogsUserList'}
data['list'] = mw.getPage(page_info)
data['list'] = mw.getPage(
{'count': count, 'p': page, 'row': page_size, 'tojs': tojs})
data['page'] = page
data['page_size'] = page_size
data['page_count'] = int(math.ceil(count / page_size))
@@ -556,8 +610,8 @@ def projectScriptLoad():
cc_content = mw.readFile(commit_tpl)
sshUrl = 'http://127.0.0.1:' + getHttpPort()
cc_content = cc_content.replace('{$GITROOTURL}', sshUrl)
gitPath = getRootPath()
cc_content = cc_content.replace('{$GITROOTURL}', gitPath)
cc_content = cc_content.replace('{$CODE_DIR}', codeDir)
cc_content = cc_content.replace('{$USERNAME}', user)
cc_content = cc_content.replace('{$PROJECT}', args['name'])
@@ -570,11 +624,9 @@ def projectScriptLoad():
def projectScriptUnload():
args = getArgs()
if not 'user' in args:
return mw.returnJson(True, 'username missing')
if not 'name' in args:
return mw.returnJson(True, 'project name missing')
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
user = args['user']
name = args['name'] + '.git'
@@ -591,11 +643,10 @@ def projectScriptUnload():
def projectScriptDebug():
args = getArgs()
if not 'user' in args:
return mw.returnJson(True, 'username missing')
data = checkArgs(args, ['user', 'name'])
if not data[0]:
return data[1]
if not 'name' in args:
return mw.returnJson(True, 'project name missing')
user = args['user']
name = args['name'] + '.git'
commit_log = getRootPath() + '/' + user + '/' + name + \
@@ -634,14 +685,8 @@ def getTotalStatistics():
st = status()
data = {}
if st.strip() == 'start':
pm = pMysqlDb()
list_count = pm.query('select count(id) as num from repository')
if list_count.find("error") > -1:
data['status'] = False
data['count'] = 0
return mw.returnJson(False, 'fail', data)
list_count = pQuery('select count(id) as num from repository')
count = list_count[0]["num"]
data['status'] = True
data['count'] = count
data['ver'] = mw.readFile(getServerDir() + '/version.pl').strip()
+16
View File
@@ -0,0 +1,16 @@
{
"ps": "Gitea 是一个开源社区驱动的轻量级代码托管解决方案。",
"name": "gitea",
"title": "Gitea",
"versions": ["1.17.2"],
"tip": "soft",
"checks": "server/gitea",
"path":"server/gitea",
"author": "gitea",
"date": "2022-10-03",
"home": "https://dl.gitea.io/",
"type": "Git服务器",
"shell": "install.sh",
"pid": "3",
"sort": 7
}
+20
View File
@@ -0,0 +1,20 @@
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory={$SERVER_PATH}/gitea
ExecStart={$SERVER_PATH}/gitea/gitea web
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
RemainAfterExit=yes
#AmbientCapabilities=CAP_NET_BIND_SERVICE
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
+110
View File
@@ -0,0 +1,110 @@
#!/bin/sh
#
# /etc/rc.d/init.d/Gitea
#
# Runs the Gogs
#
#
# chkconfig: - 85 15
#
### BEGIN INIT INFO
# Provides: Gitea
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Should-Start: mysql postgresql
# Should-Stop: mysql postgresql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start Gitea at boot time.
# Description: Control Gitea.
### END INIT INFO
# Source function library.
if [ -f /etc/init.d/functions ];then
. /etc/init.d/functions
fi
if [ -f /etc/rc.d/init.d/functions ];then
. /etc/rc.d/init.d/functions
fi
# Default values
export HOME={$HOME_DIR}
export USER={$RUN_USER}
NAME=gitea
GOGS_HOME={$SERVER_PATH}/gitea
GOGS_PATH=${GOGS_HOME}/$NAME
GOGS_USER={$RUN_USER}
SERVICENAME="gitea"
LOCKFILE=/tmp/gitea.lock
LOGPATH=${GOGS_HOME}/log
LOGFILE=${LOGPATH}/gitea.log
RETVAL=0
[ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
DAEMON_OPTS="--check $NAME"
[ ! -z "$GOGS_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GOGS_USER}"
status(){
isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
if [ "$isStart" == '' ];then
echo -e "${SERVICENAME} not running"
else
echo -e "${SERVICENAME}(pid $(echo $isStart)) already running"
fi
}
start() {
isStart=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
if [ "$isStart" != '' ];then
echo "${SERVICENAME}(pid $(echo $isStart)) already running"
return $RETVAL
fi
cd ${GOGS_HOME}
echo -e "Starting ${SERVICENAME}: \c"
${GOGS_PATH} web > ${LOGFILE} 2>&1 &
RETVAL=$?
[ $RETVAL = 0 ] && touch ${LOCKFILE} && echo -e "\033[32mdone\033[0m"
return $RETVAL
}
stop() {
pids=`ps -ef|grep 'gitea web' |grep -v grep|awk '{print $2}'`
arr=($pids)
echo -e "Stopping gitea... \c"
for p in ${arr[@]}
do
kill -9 $p
done
echo -e "\033[32mdone\033[0m"
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
reload)
stop
start
;;
*)
echo "Usage: ${NAME} {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL
+111
View File
@@ -0,0 +1,111 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
URL_DOWNLOAD=https://dl.gitea.io/
getOs(){
os=`uname`
if [ "Darwin" == "$os" ];then
echo 'darwin'
else
echo 'linux'
fi
return 0
}
getBit(){
echo `getconf LONG_BIT`
}
Install_App()
{
mkdir -p $serverPath/source/gitea
if id git &> /dev/null ;then
echo "git UID is `id -u git`"
echo "git Shell is `grep "^git:" /etc/passwd |cut -d':' -f7 `"
else
groupadd git
useradd -g git git
fi
echo '正在安装脚本文件...' > $install_tmp
version=$1
os=`getOs`
git config --global push.default simple
if [ "darwin" == "$os" ];then
file=gitea-${version}-darwin-10.12-amd64
else
file=gitea-${version}-linux-amd64
fi
file_xz="${file}.xz"
echo "wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz}"
if [ ! -f $serverPath/source/gitea/$file_xz ];then
wget -O $serverPath/source/gitea/$file_xz ${URL_DOWNLOAD}/gitea/${version}/${file_xz}
fi
cd $serverPath/source/gitea && xz -k -d $file_xz
if [ -f $file ];then
mkdir -p $serverPath/gitea
mv $serverPath/source/gitea/$file $serverPath/gitea/gitea
chmod +x $serverPath/gitea/gitea
chown -R git:git $serverPath/gitea
fi
if [ -d $serverPath/gitea ];then
echo $version > $serverPath/gitea/version.pl
cd ${rootPath} && python3 plugins/gitea/index.py start
cd ${rootPath} && python3 plugins/gitea/index.py initd_install
fi
echo 'install success' > $install_tmp
}
Uninstall_App()
{
if [ -f /usr/lib/systemd/system/gitea.service ];then
systemctl stop gitea
systemctl disable gitea
rm -rf /usr/lib/systemd/system/gitea.service
systemctl daemon-reload
fi
if [ -f $serverPath/gitea/initd/gitea ];then
$serverPath/gitea/initd/gitea stop
fi
rm -rf $serverPath/gitea
echo 'uninstall success' > $install_tmp
}
action=$1
version=$2
if [ "${1}" == 'install' ];then
Install_App $version
else
Uninstall_App $version
fi
+353
View File
@@ -0,0 +1,353 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function gogsPost(method,args,callback, title){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args));
} else {
_args = JSON.stringify(args);
}
var _title = '正在获取...';
if (typeof(title) != 'undefined'){
_title = title;
}
var loadT = layer.msg(_title, { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'gitea', func:method, args:_args}, function(data) {
layer.close(loadT);
if (!data.status){
layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
if(typeof(callback) == 'function'){
callback(data);
}
},'json');
}
function gogsSetConfig(){
gogsPost('get_gogs_conf', '', function(data){
var rrdata = $.parseJSON(data.data);
if (!rrdata.status){
layer.msg(rrdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
var rdata = rrdata.data;
var mlist = '';
for (var i = 0; i < rdata.length; i++) {
var w = '140';
if (rdata[i].name == 'error_reporting') w = '250';
var ibody = '<input style="width: ' + w + 'px;" class="bt-input-text mr5" name="' + rdata[i].name + '" value="' + rdata[i].value + '" type="text" >';
switch (rdata[i].type) {
case 0:
var selected_1 = (rdata[i].value == 1) ? 'selected' : '';
var selected_0 = (rdata[i].value == 0) ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="1" ' + selected_1 + '>开启</option>\
<option value="0" ' + selected_0 + '>关闭</option>\
</select>';
break;
case 1:
var selected_1 = (rdata[i].value == 'On') ? 'selected' : '';
var selected_0 = (rdata[i].value == 'Off') ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="On" ' + selected_1 + '>开启</option>\
<option value="Off" ' + selected_0 + '>关闭</option></select>'
break;
case 2:
var selected_1 = (rdata[i].value == 'true') ? 'selected' : '';
var selected_0 = (rdata[i].value == 'false') ? 'selected' : '';
ibody = '<select class="bt-input-text mr5" name="' + rdata[i].name + '" style="width: ' + w + 'px;">\
<option value="true" ' + selected_1 + '>开启</option>\
<option value="false" ' + selected_0 + '>关闭</option></select>'
break;
}
mlist += '<p><span>' + rdata[i].name + '</span>' + ibody + ', <font>' + rdata[i].ps + '</font></p>'
}
var html = '<style>.conf_p p{margin-bottom: 2px}</style><div class="conf_p" style="margin-bottom:0">\
' + mlist + '\
<div style="margin-top:10px; padding-right:15px" class="text-right">\
<button class="btn btn-success btn-sm mr5" onclick="gogsSetConfig()">刷新</button>\
<button class="btn btn-success btn-sm" onclick="submitGogsConf()">保存</button></div>\
</div>';
$(".soft-man-con").html(html);
});
}
//提交PHP配置
function submitGogsConf() {
var data = {
DOMAIN: $("input[name='DOMAIN']").val(),
ROOT_URL: $("input[name='ROOT_URL']").val(),
HTTP_ADDR: $("select[name='HTTP_ADDR']").val(),
HTTP_PORT: $("input[name='HTTP_PORT']").val(),
START_SSH_SERVER: $("select[name='START_SSH_SERVER']").val() || 'false',
SSH_PORT: $("input[name='SSH_PORT']").val(),
REQUIRE_SIGNIN_VIEW: $("select[name='REQUIRE_SIGNIN_VIEW']").val() || 'false',
ENABLE_CAPTCHA: $("select[name='ENABLE_CAPTCHA']").val() || 'true',
DISABLE_REGISTRATION: $("select[name='DISABLE_REGISTRATION']").val() || 'false',
ENABLE_NOTIFY_MAIL: $("select[name='ENABLE_NOTIFY_MAIL']").val() || 'false',
FORCE_PRIVATE: $("select[name='FORCE_PRIVATE']").val() || 'false',
SHOW_FOOTER_BRANDING: $("select[name='SHOW_FOOTER_BRANDING']").val() || 'false',
SHOW_FOOTER_VERSION: $("select[name='SHOW_FOOTER_VERSION']").val() || 'false',
SHOW_FOOTER_TEMPLATE_LOAD_TIME: $("select[name='SHOW_FOOTER_TEMPLATE_LOAD_TIME']").val() || 'false',
};
gogsPost('submit_gogs_conf', data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
gogsSetConfig();
});
}
function gogsEdit(){
gogsPost('gogs_edit',{} , function(data){
// console.log(data);
var rdata = $.parseJSON(data.data);
var edit = '<p class="status">通用的手动编辑:</p>';
edit +='<div class="sfm-opt">\
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['post_receive']+'\');">post-receive.tpl</button>\
<button class="btn btn-default btn-sm" onclick="onlineEditFile(0,\''+rdata['commit']+'\');">commit.tpl</button>\
</div>';
$(".soft-man-con").html(edit);
});
}
function giteaUserList(page, search) {
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
_data['tojs'] = 'giteaUserList';
gogsPost('user_list', _data, function(data){
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
content = '<div class="finduser"><input class="bt-input-text mr5 outline_no" type="text" placeholder="查找用户名" id="find_user" style="height: 28px; border-radius: 3px;width: 435px;">';
content += '<button class="btn btn-success btn-sm" onclick="userFind();">查找</button></div>';
content += '<div class="divtable" style="margin-top:5px;"><table class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0">';
content += '<thead><tr>';
content += '<th>序号</th>';
content += '<th>用户或组织</th>';
content += '<th>邮件地址</th>';
content += '<th>操作(<a href="'+rdata['data']['root_url']+'" class="btlink" target="_blank">WEB管理</a>)</th>';
content += '</tr></thead>';
content += '<tbody>';
ulist = rdata['data']['data'];
for (i in ulist){
email = ulist[i]["email"] == '' ? '无' : ulist[i]["email"];
content += '<tr><td>'+ulist[i]["id"]+'</td>'+
'<td>'+ulist[i]["name"]+'</td>'+
'<td>'+email+'</td>'+
'<td><a class="btlink" onclick="userProjectList(\''+ulist[i]["name"]+'\')">项目管理</a></td>'+
'</tr>';
}
content += '</tbody>';
content += '</table></div>';
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
content += page;
$(".soft-man-con").html(content);
});
}
function userProjectList(user, search){
var req = {};
if (!isNaN(user)){
req['page'] = user;
req['name'] = user = getCookie('gogsUserSelected');
} else {
req['page'] = 1;
req['name'] = user;
setCookie('gogsUserSelected', user);
}
req['page_size'] = 5;
req['search'] = '';
if(typeof(search) != 'undefined'){
req['search'] = search;
}
$('.layui-layer-close1').click();
gogsPost('user_project_list', req, function(data){
var rdata = [];
try {
rdata = $.parseJSON(data.data);
} catch(e){}
if (!rdata['status']){
layer.msg(rdata['msg'], { icon: 2 });
return;
}
var list = '';
// console.log(rdata);
var project_list = rdata['data']['data'];
for (i in project_list) {
var name = project_list[i]['name'];
list += '<tr><td>'+name+'</td>\
<td>\
<a class="btlink" target="_blank" href="'+rdata['data']['root_url']+user+'/'+name+'">源码</a> | \
<a class="btlink" onclick="projectScript(\''+user+'\',\''+name+'\','+project_list[i]['has_hook']+');">脚本</a>\
</td>\
</tr>';
}
var page = '<div class="dataTables_paginate paging_bootstrap pagination" style="margin-top:0px;"><ul id="softPage" class="page"><div>';
page += rdata['data']['list'];
page += '</div></ul></div>';
var loadOpen = layer.open({
type: 1,
title: '用户('+user+')项目列表',
area: '500px',
content:"<div class='bt-form pd20 c6'>\
<div>\
<div class='divtable' style='margin-top:5px;'>\
<table class='table table-hover'>\
<thead><tr><th>项目</th><th>操作</th></tr></thead>\
<tbody>" + list + "</tbody>\
</table>" +
page +
"</div></div></div>"
});
});
}
function projectScript(user, name,has_hook){
// console.log(user,name,has_hook);
var html = '';
if (has_hook){
html += '<button onclick="projectScriptEdit(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">手动编辑</button>';
html += '<button onclick="projectScriptDebug(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">调试日志</button>';
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">重新加载</button>';
html += '<button onclick="projectScriptUnload(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">卸载脚本</button>';
} else {
html += '<button onclick="projectScriptLoad(\''+user+'\',\''+name+'\')" class="btn btn-default btn-sm">加载脚本</button>';
}
var loadOpen = layer.open({
type: 1,
title: '['+user+']['+name+']脚本设置',
area: '240px',
content:'<div class="change-default pd20">'+html+'</div>'
});
}
function projectScriptEdit(user,name){
gogsPost('project_script_edit', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['data']['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
}
function projectScriptLoad(user,name){
gogsPost('project_script_load', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('加载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
}, 2000);
});
}
function projectScriptUnload(user,name){
gogsPost('project_script_unload', {'user':user,'name':name}, function(data){
if (data.data != 'ok'){
layer.msg(data.data,{icon:0,time:2000,shade: [0.3, '#000']});
return;
}
layer.msg('卸载成功!',{icon:1,time:2000,shade: [0.3, '#000']});
setTimeout(function(){
userProjectList(1);
}, 2000);
});
}
function projectScriptDebug(user,name){
gogsPost('project_script_debug', {'user':user,'name':name}, function(data){
var rdata = $.parseJSON(data.data);
if (rdata['status']){
onlineEditFile(0, rdata['path']);
} else {
layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']});
}
});
}
function getRsaPublic(){
gogsPost('get_rsa_public', {}, function(data){
var rdata = $.parseJSON(data.data);
var con = '<div class="tab-con">\
<div class="myKeyCon ptb15">\
<textarea style="margin:0px;width:580px;height:110px;outline:none;" spellcheck="false">'+rdata.mw+'</textarea>\
</div>\
<ul class="help-info-text c7 pull-left"></ul>\
</div>'
layer.open({
type: 1,
area: "600px",
title: '本机公钥',
closeBtn: 2,
shift: 5,
shadeClose: false,
content:con
});
});
}
function giteaRead(){
var readme = '<ul class="help-info-text c7">';
readme += '<li>默认使用MySQL,第一个启动加载各种配置,并修改成正确的数据库配置</li>';
readme += '<li>邮件端口使用456,gogs仅支持使用STARTTLS的SMTP协议</li>';
readme += '<li>如果使用项目中脚本本地同步,<a target="_blank" href="https://github.com/midoks/mdserver-web/wiki/%E6%8F%92%E4%BB%B6%E7%AE%A1%E7%90%86%5Bgogs%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%5D#%E5%90%AF%E5%8A%A8gogs%E5%90%8E%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BD%BF%E7%94%A8hook%E8%84%9A%E6%9C%AC%E5%90%8C%E6%AD%A5%E4%BB%A3%E7%A0%81%E9%9C%80%E8%A6%81%E5%BC%80%E5%90%AFssh%E7%AB%AF%E5%8F%A3">点击查看</></li>';
readme += '<li><a href="#" onclick="getRsaPublic();">点击查看本机公钥</></li>';
readme += '</ul>';
$('.soft-man-con').html(readme);
}
+5
View File
@@ -462,6 +462,11 @@ def userList():
if not os.path.exists(conf):
return mw.returnJson(False, "请先安装初始化!<br/>默认地址:http://" + mw.getLocalIp() + ":3000")
conf = getDbConfValue()
gtype = getGogsDbType(conf)
if gtype != 'mysql':
return mw.returnJson(False, "仅支持mysql数据操作!")
import math
args = getArgs()
-1
View File
@@ -29,7 +29,6 @@ getBit(){
Install_gogs()
{
pip3 install mysqlclient
mkdir -p $serverPath/source/gogs
+5 -1
View File
@@ -817,6 +817,7 @@ function openPhpmyadmin(name,username,password){
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return;
}
var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data);
@@ -824,7 +825,10 @@ function openPhpmyadmin(name,username,password){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return;
}
$("#toPHPMyAdmin").attr('action',rdata.data);
var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@");
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -80,7 +80,8 @@ innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M
innodb_log_file_size = 5M
#innodb_log_file_size = 5M
innodb_redo_log_capacity=10485760
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 120
+1 -1
View File
@@ -11,7 +11,7 @@
"path": "server/mysql/VERSION",
"todo_versions":["5.6","5.7","8.0"],
"versions":["5.5", "5.6", "5.7","8.0"],
"updates":["5.5.62","5.6.50", "5.7.32","8.0.22"],
"updates":["5.5.62","5.6.50", "5.7.32","8.0.30"],
"shell":"install.sh",
"checks":"server/mysql",
"path":"server/mysql",
+27 -4
View File
@@ -68,6 +68,26 @@ function myAsyncPost(method,args){
return syncPost('/plugins/run', {name:'mysql', func:method, args:_args});
}
function vaildPhpmyadmin(url,username,password){
console.log("Authorization: Basic " + btoa(username + ":" + password));
$.ajax({
type: "GET",
url: url,
dataType: 'json',
async: false,
username:username,
password:password,
headers: {
"Authorization": "Basic " + btoa(username + ":" + password)
},
data: 'vaild',
success: function (){
alert('Thanks for your comment!');
}
});
}
function runInfo(){
myPost('run_info','',function(data){
@@ -818,16 +838,19 @@ function openPhpmyadmin(name,username,password){
layer.msg('当前为[mariadb]模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
return;
}
// console.log(data);
var phpmyadmin_cfg = rdata;
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
var rdata = $.parseJSON(data.data);
if (!rdata.status){
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
return;
}
$("#toPHPMyAdmin").attr('action',rdata.data);
var home_page = rdata.data;
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@")
$("#toPHPMyAdmin").attr('action',home_page);
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
setTimeout(function(){ window.location.href = '/soft'; },3000);
@@ -836,7 +859,7 @@ function openPhpmyadmin(name,username,password){
//检查版本
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'});
bigVer = data.data.split('.')[0]
bigVer = data.data.split('.')[0];
if (bigVer>=4.5){
setTimeout(function(){
+4 -4
View File
@@ -17,7 +17,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl
mysqlDir=${serverPath}/source/mysql
VERSION="5.7.37"
VERSION=5.7.39
Install_mysql()
@@ -64,11 +64,11 @@ Install_mysql()
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_mysql_ok=d0489fc3880248a58759c50bfb286dbb
md5_mysql_ok=d949b0ef81c3f52f7ef0874066244221
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -76,7 +76,7 @@ Install_mysql()
else
# 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION}
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
fi
fi
+4 -4
View File
@@ -57,7 +57,7 @@ fi
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
VERSION=8.0.28
VERSION=8.0.30
Install_mysql()
{
mkdir -p ${mysqlDir}
@@ -107,11 +107,11 @@ Install_mysql()
fi
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
fi
#检测文件是否损坏.
md5_mysql_ok=362b8141ecaf425b803fe55292e2df98
md5_mysql_ok=313d625fcaa932bd87b48f0cf9b40f1c
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -119,7 +119,7 @@ Install_mysql()
else
# 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION}
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
fi
fi
+61
View File
@@ -0,0 +1,61 @@
import sys
import os
class luamaker:
"""
lua 处理器
"""
@staticmethod
def makeLuaTable(table):
"""
table 转换为 lua table 字符串
"""
_tableMask = {}
_keyMask = {}
def analysisTable(_table, _indent, _parent):
if isinstance(_table, tuple):
_table = list(_table)
if isinstance(_table, list):
_table = dict(zip(range(1, len(_table) + 1), _table))
if isinstance(_table, dict):
_tableMask[id(_table)] = _parent
cell = []
thisIndent = _indent + " "
for k in _table:
if sys.version_info[0] == 2:
if type(k) not in [int, float, bool, list, dict, tuple]:
k = k.encode()
if not (isinstance(k, str) or isinstance(k, int) or isinstance(k, float)):
return
key = isinstance(
k, int) and "[" + str(k) + "]" or "[\"" + str(k) + "\"]"
if _parent + key in _keyMask.keys():
return
_keyMask[_parent + key] = True
var = None
v = _table[k]
if sys.version_info[0] == 2:
if type(v) not in [int, float, bool, list, dict, tuple]:
v = v.encode()
if isinstance(v, str):
# print("lua", var)
v = v.replace("\\", "\\\\")
v = v.replace("\"", "\\\"")
var = "\"" + v + "\""
elif isinstance(v, bool):
var = v and "true" or "false"
elif isinstance(v, int) or isinstance(v, float):
var = str(v)
else:
var = analysisTable(v, thisIndent, _parent + key)
cell.append(thisIndent + key + " = " + str(var))
lineJoin = ",\n"
return "{\n" + lineJoin.join(cell) + "\n" + _indent + "}"
else:
pass
return analysisTable(table, "", "root")
+17
View File
@@ -0,0 +1,17 @@
PRAGMA synchronous = 0;
PRAGMA page_size = 4096;
PRAGMA journal_mode = wal;
PRAGMA journal_size_limit = 1073741824;
CREATE TABLE IF NOT EXISTS `logs` (
`time` INTEGER,
`ip` TEXT,
`domain` TEXT,
`server_name` TEXT,
`method` TEXT,
`status_code` INTEGER,
`user_agent` TEXT,
`uri` TEXT,
`rule_name` TEXT,
`reason` TEXT
);
+8 -6
View File
@@ -1,8 +1,10 @@
lua_shared_dict limit 30m;
lua_shared_dict drop_ip 30m;
lua_shared_dict drop_sum 30m;
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
lua_shared_dict waf_limit 30m;
lua_shared_dict waf_drop_ip 10m;
lua_shared_dict waf_drop_sum 10m;
lua_package_path "{$WAF_PATH}/html/?.lua;{$WAF_PATH}/conf/?.lua;{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
lua_package_cpath "{$WAF_PATH}/conf/?.so;{$ROOT_PATH}/openresty/lualib/?.so;;";
init_worker_by_lua_file {$WAF_PATH}/lua/init_worker.lua;
access_by_lua_file {$WAF_PATH}/lua/init.lua;
#init_by_lua_file {$WAF_PATH}/lua/init.lua;
#access_by_lua_file {$WAF_PATH}/lua/waf.lua;
# init_by_lua_file {$WAF_PATH}/lua/init.lua;
+16 -2
View File
@@ -1,4 +1,18 @@
<style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.cur {
background-color: #20a53a;
color: #fff;
}
/*waf*/
.lib-con-title {
height: 26px;
@@ -231,8 +245,8 @@
<p onclick="wafScreen();">首页</p>
<p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p>
<!-- <p onclick="wafLogs();">操作日志</p> -->
<p onclick="wafLogs();">封锁历史</p>
<!-- <p onclick="wafOpLogs();">操作日志</p> -->
</div>
<!-- lib-con -->
<div class="bt-w-con pd15">
+295 -27
View File
@@ -52,11 +52,50 @@ def checkArgs(data, ck=[]):
return (True, mw.returnJson(True, 'ok'))
sys.path.append(getPluginDir() + "/class")
from luamaker import luamaker
def listToLuaFile(path, lists):
content = luamaker.makeLuaTable(lists)
content = "return " + content
mw.writeFile(path, content)
def htmlToLuaFile(path, content):
content = "return [[" + content + "]]"
mw.writeFile(path, content)
def getConf():
path = mw.getServerDir() + "/openresty/nginx/conf/nginx.conf"
return path
def pSqliteDb(dbname='logs'):
name = "waf"
db_dir = getServerDir() + '/logs/'
if not os.path.exists(db_dir):
mw.execShell('mkdir -p ' + db_dir)
file = db_dir + name + '.db'
if not os.path.exists(file):
conn = mw.M(dbname).dbPos(db_dir, name)
sql = mw.readFile(getPluginDir() + '/conf/init.sql')
sql_list = sql.split(';')
for index in range(len(sql_list)):
conn.execute(sql_list[index])
else:
conn = mw.M(dbname).dbPos(db_dir, name)
conn.execute("PRAGMA synchronous = 0")
conn.execute("PRAGMA page_size = 4096")
conn.execute("PRAGMA journal_mode = wal")
conn.execute("PRAGMA journal_size_limit = 1073741824")
return conn
def initDomainInfo():
data = []
path_domains = getJsonPath('domains')
@@ -111,7 +150,7 @@ def initSiteInfo():
tmp['log'] = True
tmp['get'] = True
tmp['post'] = True
tmp['open'] = False
tmp['open'] = True
tmp['cc'] = config_contents['cc']
tmp['retry'] = config_contents['retry']
@@ -120,9 +159,24 @@ def initSiteInfo():
tmp['user-agent'] = config_contents['user-agent']
tmp['cookie'] = config_contents['cookie']
tmp['scan'] = config_contents['scan']
tmp['safe_verify'] = config_contents['safe_verify']
cdn_header = ['x-forwarded-for',
'x-real-ip', 'HTTP_CF_CONNECTING_IP']
'x-real-ip',
'x-forwarded',
'forwarded-for',
'forwarded',
'true-client-ip',
'client-ip',
'ali-cdn-real-ip',
'cdn-src-ip',
'cdn-real-ip',
'cf-connecting-ip',
'x-cluster-client-ip',
'wl-proxy-client-ip',
'proxy-client-ip',
'true-client-ip',
'HTTP_CF_CONNECTING_IP']
tmp['cdn_header'] = cdn_header
disable_upload_ext = ["php", "jsp"]
@@ -163,6 +217,9 @@ def initTotalInfo():
tmp['get'] = 0
tmp['post'] = 0
tmp['total'] = 0
tmp['path'] = 0
tmp['php_path'] = 0
tmp['upload_ext'] = 0
_name = {}
_name[name] = tmp
total_contents['sites'] = _name
@@ -186,21 +243,109 @@ def status():
def contentReplace(content):
service_path = mw.getServerDir()
waf_path = getServerDir() + "/waf"
waf_root = getServerDir()
waf_path = waf_root + "/waf"
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$WAF_PATH}', waf_path)
content = content.replace('{$WAF_ROOT}', waf_root)
return content
def autoMakeLuaConfSingle(file):
path = getServerDir() + "/waf/rule/" + file + ".json"
to_path = getServerDir() + "/waf/conf/rule_" + file + ".lua"
content = mw.readFile(path)
# print(content)
content = json.loads(content)
listToLuaFile(to_path, content)
def autoMakeLuaImportSingle(file):
path = getServerDir() + "/waf/" + file + ".json"
to_path = getServerDir() + "/waf/conf/waf_" + file + ".lua"
content = mw.readFile(path)
# print(content)
content = json.loads(content)
listToLuaFile(to_path, content)
def autoMakeLuaHtmlSingle(file):
path = getServerDir() + "/waf/html/" + file + ".html"
to_path = getServerDir() + "/waf/html/html_" + file + ".lua"
content = mw.readFile(path)
htmlToLuaFile(to_path, content)
def autoMakeLuaConf():
conf_list = ['args', 'cookie', 'ip_black', 'ip_white',
'ipv6_black', 'post', 'scan_black', 'url',
'user_agent']
for x in conf_list:
autoMakeLuaConfSingle(x)
import_list = ['config', 'site', 'domains']
for x in import_list:
autoMakeLuaImportSingle(x)
html_list = ['get', 'post', 'safe_js', 'user_agent', 'cookie', 'other']
for x in html_list:
autoMakeLuaHtmlSingle(x)
def initDefaultInfo():
path = getServerDir()
djson = path + "/waf/domains.json"
default_json = path + "/waf/default.json"
if os.path.exists(djson):
content = mw.readFile(djson)
content = json.loads(content)
ddata = {}
dlist = []
for i in content:
dlist.append(i["name"])
dlist.append('unset')
ddata["list"] = dlist
if len(ddata["list"]) < 1:
ddata["default"] = "unset"
else:
ddata["default"] = dlist[0]
mw.writeFile(default_json, json.dumps(ddata))
def autoMakeConfig():
path = getServerDir()
initDomainInfo()
initSiteInfo()
initTotalInfo()
autoMakeLuaConf()
def restartWeb():
autoMakeConfig()
mw.restartWeb()
def initDreplace():
path = getServerDir()
if not os.path.exists(path + '/waf'):
if not os.path.exists(path + '/waf/lua'):
sdir = getPluginDir() + '/waf'
cmd = 'cp -rf ' + sdir + ' ' + path
mw.execShell(cmd)
logs_path = path + '/logs'
if not os.path.exists(logs_path):
mw.execShell('mkdir -p ' + logs_path)
debug_log = path + '/debug.log'
if not os.path.exists(debug_log):
mw.execShell('echo "" > ' + debug_log)
config = path + '/waf/config.json'
content = mw.readFile(config)
content = json.loads(content)
@@ -214,6 +359,16 @@ def initDreplace():
content = contentReplace(content)
mw.writeFile(config, content)
config_common = path + "/waf/lua/common.lua"
content = mw.readFile(config_common)
content = contentReplace(content)
mw.writeFile(config_common, content)
init_worker = path + "/waf/lua/init_worker.lua"
content = mw.readFile(init_worker)
content = contentReplace(content)
mw.writeFile(init_worker, content)
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl)
@@ -223,6 +378,13 @@ def initDreplace():
initDomainInfo()
initSiteInfo()
initTotalInfo()
autoMakeLuaConf()
initDefaultInfo()
pSqliteDb()
if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + path)
def start():
@@ -233,6 +395,9 @@ def start():
conf = conf.replace('#include luawaf.conf;', "include luawaf.conf;")
mw.writeFile(path, conf)
import tool_task
tool_task.createBgTask()
mw.restartWeb()
return 'ok'
@@ -243,6 +408,10 @@ def stop():
conf = conf.replace('include luawaf.conf;', "#include luawaf.conf;")
mw.writeFile(path, conf)
import tool_task
tool_task.removeBgTask()
mw.restartWeb()
return 'ok'
@@ -254,8 +423,10 @@ def restart():
def reload():
stop()
mw.execShell('rm -rf ' + mw.getServerDir() +
"/openresty/nginx/logs/error.log")
errlog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
mw.execShell('rm -rf ' + errlog)
start()
return 'ok'
@@ -306,7 +477,7 @@ def addRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -328,7 +499,7 @@ def removeRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -353,7 +524,7 @@ def setRuleState():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -384,7 +555,7 @@ def modifyRule():
cjson = mw.getJson(content)
mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content)
@@ -425,6 +596,7 @@ def addSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -460,6 +632,7 @@ def addIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -480,6 +653,8 @@ def removeIpWhite():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -515,6 +690,8 @@ def addIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -535,6 +712,8 @@ def removeIpBlack():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -553,6 +732,7 @@ def setIpv6Black():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -569,9 +749,10 @@ def delIpv6Black():
content = json.loads(content)
content.remove(addr)
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -594,6 +775,8 @@ def removeSiteRule():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -608,11 +791,13 @@ def setObjStatus():
cobj = json.loads(content)
o = args['obj']
status = args['statusCode']
status = int(args['statusCode'])
cobj[o]['status'] = status
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -632,6 +817,32 @@ def setRetry():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
def setSafeVerify():
args = getArgs()
data = checkArgs(args, ['auto', 'time', 'cpu'])
if not data[0]:
return data[1]
conf = getJsonPath('config')
content = mw.readFile(conf)
cobj = json.loads(content)
cobj['safe_verify']['time'] = args['time']
cobj['safe_verify']['cpu'] = args['cpu']
if args['auto'] == '0':
cobj['safe_verify']['auto'] = False
else:
cobj['safe_verify']['auto'] = True
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -642,7 +853,7 @@ def setSiteRetry():
def setCcConf():
args = getArgs()
data = checkArgs(args, ['siteName', 'cycle', 'limit',
'endtime', 'is_open_global', 'increase'])
'endtime', 'is_open_global'])
if not data[0]:
return data[1]
@@ -661,6 +872,8 @@ def setCcConf():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -677,6 +890,8 @@ def saveScanRule():
path = getRuleJsonPath('scan_black')
cjson = mw.getJson(args)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', [])
@@ -716,6 +931,26 @@ def getSiteConfig():
return mw.returnJson(True, 'ok!', content)
def getSiteListData():
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
return json.loads(data)
def setDefaultSite(name):
path = getServerDir() + "/waf/default.json"
data = mw.readFile(path)
data = json.loads(data)
data['default'] = name
mw.writeFile(path, json.dumps(data))
return mw.returnJson(True, 'OK')
def getDefaultSite():
data = getSiteListData()
return mw.returnJson(True, 'OK', data)
def getSiteConfigByName():
args = getArgs()
data = checkArgs(args, ['siteName'])
@@ -749,6 +984,8 @@ def addSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '添加成功!')
@@ -768,6 +1005,8 @@ def removeSiteCdnHeader():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '删除成功!')
@@ -790,29 +1029,44 @@ def importData():
path = getRuleJsonPath(args['s_Name'])
mw.writeFile(path, args['pdata'])
restartWeb()
return mw.returnJson(True, '设置成功!')
def getLogsList():
args = getArgs()
data = checkArgs(args, ['siteName'])
data = checkArgs(args, ['site', 'page', 'page_size', 'tojs'])
if not data[0]:
return data[1]
data = []
path = mw.getLogsDir() + '/waf'
page = int(args['page'])
page_size = int(args['page_size'])
domain = args['site']
tojs = args['tojs']
if not os.path.exists(path):
return mw.returnJson(False, '还未生成!', [])
conn = pSqliteDb('logs')
files = os.listdir(path)
for f in files:
if f == '.DS_Store':
continue
f = f.split('_')
if f[0] == args['siteName']:
fl = f[1].split('.')
data.append(fl[0])
field = 'time,ip,domain,server_name,method,uri,user_agent,rule_name,reason'
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
condition = ''
conn = conn.field(field)
conn = conn.where("1=1", ()).where("domain=?", (domain,))
clist = conn.limit(limit).order('time desc').inquiry()
count_key = "count(*) as num"
count = conn.field(count_key).limit('').order('').inquiry()
# print(count)
count = count[0][count_key]
data = {}
_page = {}
_page['count'] = count
_page['p'] = page
_page['row'] = page_size
_page['tojs'] = tojs
data['page'] = mw.getPage(_page)
data['data'] = clist
return mw.returnJson(True, 'ok!', data)
@@ -823,7 +1077,7 @@ def getSafeLogs():
if not data[0]:
return data[1]
path = mw.getLogsDir() + '/waf'
path = getServerDir() + '/logs'
file = path + '/' + args['siteName'] + '_' + args['toDate'] + '.log'
if not os.path.exists(file):
return mw.returnJson(False, "文件不存在!")
@@ -859,6 +1113,7 @@ def setObjOpen():
cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -888,6 +1143,7 @@ def setSiteObjOpen():
cjson = mw.getJson(content)
mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!')
@@ -908,6 +1164,12 @@ def installPreInspection():
return 'ok'
def cleanDropIp():
url = "http://127.0.0.1/clean_waf_drop_ip"
data = mw.httpGet(url)
return mw.returnJson(True, 'ok!', data)
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
@@ -964,12 +1226,16 @@ if __name__ == "__main__":
print(setSiteCcConf())
elif func == 'set_retry':
print(setRetry())
elif func == 'set_safe_verify':
print(setSafeVerify())
elif func == 'set_site_retry':
print(setSiteRetry())
elif func == 'save_scan_rule':
print(saveScanRule())
elif func == 'get_site_config':
print(getSiteConfig())
elif func == 'get_default_site':
print(getDefaultSite())
elif func == 'get_site_config_byname':
print(getSiteConfigByName())
elif func == 'add_site_cdn_header':
@@ -990,5 +1256,7 @@ if __name__ == "__main__":
print(getWafConf())
elif func == 'waf_site':
print(getWafSite())
elif func == 'clean_drop_ip':
print(cleanDropIp())
else:
print('error')
+1 -1
View File
@@ -11,5 +11,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21",
"pid": "1",
"versions": ["0.1"]
"versions": ["0.2.2"]
}
+76 -8
View File
@@ -7,31 +7,99 @@ rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl
action=$1
version=$2
sys_os=`uname`
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if [ "$sys_os" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
Install_of(){
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source/op_waf
mkdir -p $serverPath/op_waf
echo '0.1' > $serverPath/op_waf/version.pl
# luarocks
if [ ! -f $serverPath/source/op_waf/luarocks-3.5.0.tar.gz ];then
wget --no-check-certificate -O $serverPath/source/op_waf/luarocks-3.5.0.tar.gz http://luarocks.org/releases/luarocks-3.5.0.tar.gz
fi
# which luarocks
# if [ "$?" != "0" ];then
if [ ! -d $serverPath/op_waf/luarocks ];then
cd $serverPath/source/op_waf && tar xvf luarocks-3.5.0.tar.gz
# cd luarocks-3.9.1 && ./configure && make bootstrap
cd luarocks-3.5.0 && ./configure --prefix=$serverPath/op_waf/luarocks --with-lua-include=$serverPath/openresty/luajit/include/luajit-2.1 --with-lua-bin=$serverPath/openresty/luajit/bin
make -I${serverPath}/openresty/luajit/bin
make install
fi
if [ ! -f $serverPath/source/op_waf/lsqlite3_fsl09y.zip ];then
wget --no-check-certificate -O $serverPath/source/op_waf/lsqlite3_fsl09y.zip http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09y.zip?uuid=fsl_9y
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
fi
if [ ! -d $serverPath/source/op_waf/lsqlite3_fsl09y ];then
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
fi
PATH=${serverPath}/openresty/luajit:${serverPath}/openresty/luajit/include/luajit-2.1:$PATH
export PATH=$PATH:$serverPath/op_waf/luarocks/bin
if [ ! -f $serverPath/op_waf/waf/conf/lsqlite3.so ];then
if [ "${sys_os}" == "Darwin" ];then
cd $serverPath/source/op_waf/lsqlite3_fsl09y
find_cfg=`cat Makefile | grep 'SQLITE_DIR'`
if [ "$find_cfg" == "" ];then
LIB_SQLITE_DIR=`brew info sqlite | grep /usr/local/Cellar/sqlite | cut -d \ -f 1 | awk 'END {print}'`
echo $LIB_SQLITE_DIR
sed -i $BAK "s#\$(ROCKSPEC)#\$(ROCKSPEC) SQLITE_DIR=${LIB_SQLITE_DIR}#g" Makefile
fi
make
else
cd $serverPath/source/op_waf/lsqlite3_fsl09y && make
fi
fi
# copy to code path
DEFAULT_DIR=$serverPath/op_waf/luarocks/lib/lua/5.1
if [ -f ${DEFAULT_DIR}/lsqlite3.so ];then
mkdir -p $serverPath/op_waf/waf/conf
cp -rf ${DEFAULT_DIR}/lsqlite3.so $serverPath/op_waf/waf/conf/lsqlite3.so
fi
echo "${version}" > $serverPath/op_waf/version.pl
echo 'install ok' > $install_tmp
cd ${rootPath} && python3 plugins/op_waf/index.py start
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
# cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py restart
}
Uninstall_of(){
cd ${rootPath} && python3 plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
if [ "$?" == "0" ];then
rm -rf $serverPath/op_waf
fi
}
action=$1
type=$2
action=$1
if [ "${1}" == 'install' ];then
Install_of
+311 -211
View File
@@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){
title: "设置响应代码【" + ruleName + "】",
area: '300px',
shift: 5,
closeBtn: 2,
closeBtn: 1,
shadeClose: true,
content: '<div class="bt-form pd20 pb70">\
<div class="line">\
@@ -69,8 +69,10 @@ function setObjOpen(ruleName){
owPost('set_obj_open', {obj:ruleName},function(data){
var rdata = $.parseJSON(data.data);
if (rdata.status){
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
wafGloabl();
showMsg(rdata.msg, function(){
wafGloabl();
},{icon:1,time:2000,shade: [0.3, '#000']},2000);
} else {
layer.msg('设置失败!',{icon:0,time:2000,shade: [0.3, '#000']});
}
@@ -84,7 +86,7 @@ function saveCcRule(siteName,is_open_global, type) {
if(type == 2){
// set_aicc_open('start');
increase = "0";
}else{
} else {
// set_aicc_open('stop');
increase = type;
}
@@ -144,7 +146,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
type: 1,
title: "设置CC规则",
area: '540px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -164,7 +166,10 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
<li>请不要设置过于严格的CC规则,以免影响正常用户体验</li>\
<li><font style="color:red;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用:全局设置当前CC规则,且覆盖当前全部站点的CC规则</font></li>\
</ul>\
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button></div>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button>\
<button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button>\
</div>\
</form>',
success:function(layero,index){
$('.btn_cc_all').click(function(){
@@ -184,7 +189,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
type: 1,
title: "设置恶意容忍规则",
area: '500px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -201,9 +206,12 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
</div>\
<ul class="help-info-text c7 ptb10">\
<li><font style="color:red;">'+ retry_cycle + '</font> 秒内累计恶意请求超过 <font style="color:red;">' + retry + '</font> 次,封锁 <font style="color:red;">' + retry_time + '</font> 秒</li>\
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</li>\
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</font></li>\
</ul>\
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button></div>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button>\
<button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button>\
</div>\
</form>',
success:function(){
$('.btn_retry_all').click(function(){
@@ -217,6 +225,65 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
}
//设置safe_verify规则
function setSafeVerify(auto, cpu, time, siteName) {
var svlayer = layer.open({
type: 1,
title: "设置强制安全验证",
area: '500px',
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
<span class="tname">CPU</span>\
<div class="info-r"><input class="bt-input-text" name="cpu" type="number" max-number="100" value="'+ cpu + '" /> %</div>\
</div>\
<div class="line">\
<span class="tname">通行时间</span>\
<div class="info-r"><input class="bt-input-text" name="time" type="number" value="'+ time + '" /> 秒</div>\
</div>\
<div class="line">\
<span class="tname">开启自动</span>\
<div class="info-r">\
<select class="bt-input-text mr5" style="width:80px" name="auto">\
<option value="0" '+(auto==false?"selected=selected":"")+'>关闭</option>\
<option value="1" '+(auto==true?"selected=selected":"")+'>开启</option>\
</select>\
</div>\
</div>\
<ul class="help-info-text c7 ptb10">\
<li><font style="color:red;">全局设置强制安全验证</font></li>\
<li>开启自动后:cpu超过['+cpu+'%]后,强制验证。</li>\
</ul>\
<div class="bt-form-submit-btn">\
<button type="button" class="btn btn-success btn-sm btn_sv_present">应用</button>\
</div>\
</form>',
success:function(index){
$('.btn_sv_present').click(function(){
var pdata = {
siteName: siteName,
cpu: $("input[name='cpu']").val(),
auto: $("select[name='auto']").val(),
time: $("input[name='time']").val(),
}
var act = 'set_safe_verify';
owPost(act, pdata, function(data){
var rdata = $.parseJSON(data.data);
showMsg(rdata.msg, function() {
layer.close(svlayer);
wafGloabl();
},{ icon: rdata.status ? 1 : 2 },1000);
});
});
},
});
}
//保存retry规则
function saveRetry(siteName,type) {
var pdata = {
@@ -253,15 +320,6 @@ function addRule(ruleName) {
},1000);
}
});
// var loadT = layer.msg('正在添加,请稍候..', { icon: 16, time: 0 });
// $.post('/plugin?action=a&name=btwaf&s=add_rule', pdata, function (rdata) {
// layer.close(loadT);
// layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
// if (rdata.status) {
// set_obj_conf(ruleName, 1);
// }
// });
}
function modifyRule(index, ruleName) {
@@ -339,7 +397,7 @@ function setObjConf(ruleName, type) {
type: 1,
title: "编辑规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -405,7 +463,7 @@ function scanRule() {
type: 1,
title: "常用扫描器过滤规则",
area: '650px',
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<form class="bt-form pd20 pb70">\
<div class="line">\
@@ -571,7 +629,7 @@ function ipWhite(type) {
type: 1,
title: "管理IP白名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 ipv4_list">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -695,6 +753,23 @@ function addIpBlack() {
});
}
function addIpBlackArgs(ip) {
var pdata = {
start_ip: ip,
end_ip: ip,
}
if (pdata['start_ip'].split('.').length < 4 || pdata['end_ip'].split('.').length < 4) {
layer.msg('起始IP或结束IP格式不正确!');
return;
}
owPost('add_ip_black', pdata, function(data){
var rdata = $.parseJSON(data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//从IP黑名单删除IP段
function removeIpBlack(index) {
@@ -714,7 +789,7 @@ function ipBlack(type) {
type: 1,
title: "管理IP黑名单",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6黑名单</div></div>\
<div class="pd15 ipv4_block">\
@@ -820,17 +895,17 @@ function wafScreen(){
con += '<div class="screen">\
<div class="line"><span class="name">POST渗透</span><span class="val">'+rdata.rules.post+'</span></div>\
<div class="line"><span class="name">GET渗透</span><span class="val">0</span></div>\
<div class="line"><span class="name">GET渗透</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">0</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">0</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">0</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.url+'</span></div>\
<div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
<div class="line"><span class="name">恶意文件上传</span><span class="val">'+rdata.rules.upload_ext+'</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.path+'</span></div>\
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">'+rdata.rules.php_path+'</span></div>\
</div>';
con += '<div style="width:660px;"><ul class="help-info-text c7">\
@@ -878,6 +953,16 @@ function wafGloabl(){
<td style="text-align: center;">--</td>\
<td class="text-right"><a class="btlink" onclick="setRetry('+ rdata.retry.retry_cycle + ',' + rdata.retry.retry + ',' + rdata.retry.retry_time + ')">初始规则</a></td>\
</tr>\
<tr>\
<td>强制安全验证</td>\
<td>'+rdata.safe_verify.ps+'</td>\
<td>--</td>\
<td style="text-align: center;"><div class="ssh-item">\
<input class="btswitch btswitch-ios" id="close_safe_verify" type="checkbox" '+(rdata.safe_verify.open ? 'checked' : '')+'>\
<label class="btswitch-btn" for="close_safe_verify" onclick="setObjOpen(\'safe_verify\')"></label></div>\
</td>\
<td class="text-right"><a class="btlink" onclick="setSafeVerify('+ rdata.safe_verify.auto + ',' + rdata.safe_verify.cpu + ',' + rdata.safe_verify.time + ')">设置</a> | <a class="btlink" href="javascript:;" onclick="onlineEditFile(0,\''+rdata['reqfile_path']+'/safe_js.html\')">响应内容</a></td>\
</tr>\
<tr>\
<td>GET-URI过滤</td>\
<td>'+ rdata.get.ps + '</td>\
@@ -956,146 +1041,6 @@ function back_css(v) {
}
}
//查看网站日志
function siteWafLog(siteName) {
var loadT = layer.msg('正在处理,请稍候..', { icon: 16, time: 0 });
owPost('get_logs_list', { siteName: siteName } , function (data) {
var tmp = $.parseJSON(data.data);
var rdata = tmp.data;
var selectLogDay = "";
var day = rdata[0];
for (var i = 0; i < rdata.length; i++) {
selectLogDay += '<option value="' + rdata[i] + '">' + rdata[i] + '</option>';
}
if (rdata == "") {
layer.msg("暂无日志记录", { icon: 6, shade: 0.3, time: 1000 });
return
}
layer.open({
type: 1,
title: "日志【" + siteName + "】",
area: ['880px', '500px'],
closeBtn: 2,
shadeClose: false,
content: '<div class="lib-box pd15 lib-box-log">\
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
<div class="lib-con">\
<div class="divtable">\
<div id="site_waf_log" style="max-height:400px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover" style="border:none;">\
<thead><tr><th width="150">时间</th><th width="120">用户IP</th><th width="70">类型</th><th>URI地址</th><th class="tdhide">User-Agent</th><th width="60">状态</th><th width="100">过滤器</th><th class="tdhide">过滤规则</th><th width="100" class="text-right">操作</th></tr></thead>\
<tbody id="LogDayCon"></tbody>\
</table>\
</div>\
</div>\
<div class="page pull-right" id="size_log_page" style="margin-top:10px"></div>\
</div>\
</div>'
});
siteLogCon(siteName, day, 1);
tableFixed("site_waf_log");
});
}
//日志内容
function siteLogCon(siteName, day, page) {
if (!page) page = 1;
var last = page - 1;
var next = page + 1;
var pagehtml = '';
$("#site_waf_log").scrollTop(0);
owPost('get_safe_logs', { siteName: siteName, toDate: day, p: page }, function(data){
var tmp = $.parseJSON(data.data);
if (!tmp.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = tmp.data;
var con = '';
for (var i = 0; i < rdata.length; i++) {
con += '<tr>\
<td class="td0">'+ escapeHTML(rdata[i][0]) + '</td>\
<td class="td1"><a class="btlink" href="javascript:add_log_ip_black(\''+ escapeHTML(rdata[i][1]) + '\');" title="加入黑名单">' + escapeHTML(rdata[i][1]) + '</a></td>\
<td class="td2">'+ escapeHTML(rdata[i][2]) + '</td>\
<td class="td3"><span class="td3txt">'+ escapeHTML(rdata[i][3]) + '</span></td>\
<td class="tdhide td4">'+ escapeHTML(rdata[i][4]) + '</td><td>已拦截</td>\
<td class="td5"><span class="filtertext">'+ escapeHTML(rdata[i][5]) + '</span></td>\
<td class="tdhide td6">'+ escapeHTML(rdata[i][6]) + '</td>\
<td class="text-right"><a href="javascript:;" class="btlink submit_msg" data-index="'+ i +'">误报</a> | <a href="javascript:;" class="btlink btwaf_details" data-index="'+ i +'">详细</a></td>\
</tr>'
}
$("#LogDayCon").html(con);
pagehtml = '<a class="Pstart" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',1)">首页</a><a class="prevPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + last + ')">上一页</a><a class="nextPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + next + ')">下一页</a><a class="Pcount">第 ' + page + ' 页</a>';
$("#size_log_page").html(pagehtml);
if (rdata.length < 1) $(".nextPage").hide();
if (last < 1) $(".prevPage").hide();
// 发送误报请求
$(".submit_msg").click(function () {
var _this = $(this);
var res = rdata[$(this).attr('data-index')];
layer.confirm('是否确定提交误报反馈?', { title: '误报反馈',closeBtn:2,icon:3}, function () {
var url_address = res[3];
var rule_arry = res[6].split(" &gt;&gt; ");
var pdata = { url_rule: url_address };
var loadT = layer.msg('正在添加URL白名单..', { icon: 16, time: 0 });
$.post('/plugin?action=a&name=btwaf&s=add_url_white', pdata, function (rdata) {
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
layer.close(loadT);
if (rule_arry[1] != undefined){ $.get('https://www.bt.cn/Api/add_waf_logs?data=' + rule_arry[1],function(rdata){},'jsonp')}
});
});
})
// 详情
$(".btwaf_details").click(function () {
var res = rdata[$(this).attr('data-index')];
var time = res[0]; //时间
var ip_address = res[1]; //IP地址
var req_type = res[2]; // 请求类型
var url_address = res[3]; // 请求类型
var user_agent = res[4]; // 请求类型
var filters = res[5]; //过滤器
var filter_rule = ''; //过滤规则
var rule_arry = res[6].split(" &gt;&gt; ");
var incoming_value = '',risk_value = ''; //传入值,风险值
if(rule_arry.length == 0) filter_rule = rule_arry[0]
incoming_value = rule_arry[1] == undefined?'空':rule_arry[1];
risk_value = incoming_value.match(new RegExp(rule_arry[0].replace(/\//g,'\\/'),'i'));
risk_value = risk_value?risk_value[0]:'空';
layer.open({
type: 1,
title: time + "详情",
area: '600px',
closeBtn: 2,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>'+ escapeHTML(time) + '</td><th>用户IP</th><td><a class="btlink" href="javascript:add_log_ip_black(\'' + escapeHTML(ip_address) + '\')" title="加入黑名单">' + escapeHTML(ip_address) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(req_type) + '</td><th>过滤器</th><td>' + escapeHTML(filters) + '</td></tr></tbody></table>\
<div><b style="margin-left:10px">URI地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(url_address) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(user_agent) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(rule_arry[0]) + '</div></div>\
<div><b style="margin-left:10px">传入值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(incoming_value) + '</div></div>\
<div><b style="margin-left:10px">风险值</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(risk_value) + '</div></div>\
</div>'
})
})
$("#LogDayCon td").click(function () {
$(this).parents("tr").addClass("active").siblings().removeClass("active");
});
});
}
function html_encode(value) {
return $('<div></div>').html(value).text();
}
@@ -1190,7 +1135,7 @@ function siteRuleAdmin(siteName, ruleName, type) {
type: 1,
title: "管理网站过滤规则【" + title + "】",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -1237,7 +1182,7 @@ function cdnHeader(siteName, type) {
type: 1,
title: "管理网站【" + siteName + "】CDN-Headers",
area: ['500px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
@@ -1342,7 +1287,7 @@ function setSiteObjConf(siteName, ruleName, type) {
type: 1,
title: "编辑网站【" + siteName + "】规则【" + ruleName + "】",
area: ['700px', '530px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div class="divtable">\
@@ -1394,7 +1339,7 @@ function siteWafConfig(siteName, type) {
type: 1,
title: "网站配置【" + siteName + "】",
area: ['700px', '500px'],
closeBtn: 2,
closeBtn: 1,
shadeClose: false,
content: '<div id="s_w_c"></div>'
});
@@ -1543,7 +1488,6 @@ function siteWafConfig(siteName, type) {
function wafSite(){
owPost('get_site_config', {}, function(data){
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
@@ -1553,32 +1497,20 @@ function wafSite(){
i += 1;
tbody += '<tr>\
<td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '>\
</td>\
<td>\
<input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span>\
</td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '></td>\
<td><input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span></td>\
<td>\
<div class="ssh-item" style="margin-left:0">\
<input class="btswitch btswitch-ios" id="closeget_'+ i + '" type="checkbox" ' + (v.open ? 'checked' : '') + '>\
<label class="btswitch-btn" for="closeget_'+ i + '" onclick="setSiteObjState(\'' + k + '\',\'open\')"></label>\
</div>\
</td>\
<td class="text-right"><a onclick="siteWafLog(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
</tr>'
<td class="text-right"><a onclick="wafLogs(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
</tr>';
});
var con = '<div class="lib-box">\
@@ -1612,27 +1544,195 @@ function wafSite(){
function wafHistory(){
function wafLogRequest(page){
var args = {};
args['page'] = page;
args['page_size'] = 10;
args['site'] = $('select[name="site"]').val();
var query_date = 'today';
if ($('#time_choose').attr("data-name") != ''){
query_date = $('#time_choose').attr("data-name");
} else {
query_date = $('#search_time button.cur').attr("data-name");
}
args['query_date'] = query_date;
args['tojs'] = 'wafLogRequest';
owPost('get_logs_list', args, function(rdata){
var rdata = $.parseJSON(rdata.data);
var list = '';
var data = rdata.data.data;
if (data.length > 0){
for(i in data){
list += '<tr>';
list += '<td><span class="overflow_hide" style="width:112px;">' + getLocalTime(data[i]['time'])+'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['domain'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['ip'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['uri'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['rule_name'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:200px;">' + data[i]['reason'] +'</span></td>';
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
list += '</tr>';
}
} else{
list += '<tr><td colspan="8" style="text-align:center;">封锁日志为空</td></tr>';
}
var table = '<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead><tr>\
<th>时间</th>\
<th>域名</th>\
<th>IP</th>\
<th>URI</th>\
<th>规则名</th>\
<th>原因</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
'+ list +'\
</tbody></table>\
</div>\
<div id="wsPage" class="dataTables_paginate paging_bootstrap page"></div>';
$('#ws_table').html(table);
$('#wsPage').html(rdata.data.page);
$(".tablescroll .details").click(function(){
var index = $(this).attr('data-id');
var res = data[index];
var ip = res.ip;
var time = getLocalTime(res.time);
layer.open({
type: 1,
title: "【"+res.domain + "】详情",
area: '600px',
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15 lib-box">\
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
<tbody><tr><th>时间</th><td>'+ time + '</td><th>用户IP</th><td><a class="btlink" href="javascript:addIpBlackArgs(\'' + escapeHTML(ip) + '\')" title="加入黑名单">' + escapeHTML(ip) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(res.method) + '</td><th>过滤器</th><td>' + escapeHTML(res.rule_name) + '</td></tr></tbody></table>\
<div><b style="margin-left:10px">URI地址</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.uri) + '</div></div>\
<div><b style="margin-left:10px">User-Agent</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.user_agent) + '</div></div>\
<div><b style="margin-left:10px">过滤规则</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.rule_name) + '</div></div>\
<div><b style="margin-left:10px">Reason</b></div>\
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.reason) + '</div></div>\
</div>'
})
});
});
}
function wafLogs(){
var randstr = getRandomString(10);
var html = '<div>\
<div style="padding-bottom:10px;">\
<span>网站: </span>\
<select class="bt-input-text" name="site" style="margin-left:4px;width:100px;">\
<option value="unset">未设置</option>\
</select>\
<span style="margin-left:10px">时间: </span>\
<div class="input-group" style="margin-left:10px;width:350px;display: inline-table;vertical-align: top;">\
<div id="search_time" class="input-group-btn btn-group-sm">\
<button data-name="today" type="button" class="btn btn-default">今日</button>\
<button data-name="yesterday" type="button" class="btn btn-default">昨日</button>\
<button data-name="l7" type="button" class="btn btn-default">近7天</button>\
<button data-name="l30" type="button" class="btn btn-default">近30天</button>\
</div>\
<span class="last-span"><input data-name="" type="text" id="time_choose" lay-key="1000001_'+randstr+'" class="form-control btn-group-sm" autocomplete="off" placeholder="自定义时间" style="display: inline-block;font-size: 12px;padding: 0 10px;height:30px;width: 200px;"></span>\
</div>\
<div style="float:right;"><button id="UncoverAll" class="btn btn-success btn-sm">解封所有</button></div>\
</div>\
<div class="divtable mtb10" id="ws_table"></div>\
</div>';
$(".soft-man-con").html(html);
// wafLogRequest(1);
$("#UncoverAll").click(function(){
owPost('clean_drop_ip',{},function(data){
var rdata = $.parseJSON(data.data);
var ndata = $.parseJSON(rdata.data);
if (ndata.status == 0){
layer.msg("解封所有成功",{icon:1,time:2000,shade: [0.3, '#000']});
} else{
layer.msg("解封所有异常:"+ndata.msg,{icon:5,time:2000,shade: [0.3, '#000']});
}
});
});
//日期范围
laydate.render({
elem: '#time_choose',
value:'',
range:true,
done:function(value, startDate, endDate){
if(!value){
return false;
}
$('#search_time button').each(function(){
$(this).removeClass('cur');
});
var timeA = value.split('-');
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")
$('#time_choose').attr("data-name",query_txt);
$('#time_choose').addClass("cur");
wafLogRequest(1);
},
});
$('#search_time button:eq(0)').addClass('cur');
$('#search_time button').click(function(){
$('#search_time button').each(function(){
if ($(this).hasClass('cur')){
$(this).removeClass('cur');
}
});
$('#time_choose').attr("data-name",'');
$('#time_choose').removeClass("cur");
$(this).addClass('cur');
wafLogRequest(1);
});
owPost('get_default_site',{},function(rdata){
$('select[name="site"]').html('');
var rdata = $.parseJSON(rdata.data);
var rdata = rdata.data;
var default_site = rdata["default"];
var select = '';
for (var i = 0; i < rdata["list"].length; i++) {
if (default_site == rdata["list"][i]){
select += '<option value="'+rdata["list"][i]+'" selected>'+rdata["list"][i]+'</option>';
} else{
select += '<option value="'+rdata["list"][i]+'">'+rdata["list"][i]+'</option>';
}
}
$('select[name="site"]').html(select);
wafLogRequest(1);
$('select[name="site"]').change(function(){
wafLogRequest(1);
});
});
var con = '<button class="btn btn-success btn-sm" onclick="UncoverAll()">解封所有</button>';
con += '<div class="divtable mt10">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">开始时间</th>\
<th width="44%">IP</th>\
<th width="10%">站点</th>\
<th width="10%">封锁原因</th>\
<th width="10%">封锁时长</th>\
<th style="text-align: center;" width="10%">状态</th>\
</thead>\
</table>\
</div>';
$(".soft-man-con").html(con);
}
function wafLogs(){
function wafOpLogs(){
var con = '<div class="divtable">\
<table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">名称</th>\
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
# echo $rootPath
resty=$rootPath/openresty/bin/resty
RUN_CMD=$resty
if [ ! -f $resty ];then
RUN_CMD=/www/server/openresty/bin/resty
fi
# test
# $RUN_CMD simple.lua
# $RUN_CMD test_gsub.lua
# $RUN_CMD --shdict 'limit 10m' test_find_server_name.lua
# $RUN_CMD --stap --shdict 'limit 10m' test_find_server_name.lua
# $RUN_CMD test_rand.lua
$RUN_CMD test_ffi_time.lua
+18
View File
@@ -0,0 +1,18 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
collectgarbage()
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed: ", (ngx.now() - begin) / N)
+62
View File
@@ -0,0 +1,62 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local ffi = require("ffi")
ffi.cdef[[
struct timeval {
long int tv_sec;
long int tv_usec;
};
int gettimeofday(struct timeval *tv, void *tz);
]];
local tm = ffi.new("struct timeval");
-- 返回微秒级时间戳
local function current_time_millis()
ffi.C.gettimeofday(tm,nil);
local sec = tonumber(tm.tv_sec);
local usec = tonumber(tm.tv_usec);
return sec + usec * 10^-6;
end
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("elapsed[1]: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = current_time_millis()
local N = 1e7
for i = 1, N do
target()
end
ngx.update_time()
ngx.say("ffi elapsed: ", (current_time_millis() - begin) / N)
@@ -0,0 +1,75 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local config_domains = {
[1] = {
["name"] = "t1.cn",
["path"] = "/www/wwwroot/t1.cn",
["domains"] = {
[1] = "t1.cn",
[2] = "t3.cn"
}
}
}
local function get_server_name(request_name)
for _,v in ipairs(config_domains)
do
for _,cd_name in ipairs(v['domains'])
do
if request_name == cd_name then
return v['name']
end
end
end
return request_name
end
local function get_server_name_cache(request_name)
local cache_name = ngx.shared.limit:get(request_name)
if cache_name then return cache_name end
for _,v in ipairs(config_domains)
do
for _,cd_name in ipairs(v['domains'])
do
if request_name == cd_name then
ngx.shared.limit:set(cd_name,v['name'],3600)
return v['name']
end
end
end
return request_name
end
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
get_server_name("t3.cn")
end
ngx.update_time()
ngx.say("test get_server_name elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
get_server_name_cache("t3.cn")
end
ngx.update_time()
ngx.say("test get_server_name_cache elapsed: ", (ngx.now() - begin) / N)
+47
View File
@@ -0,0 +1,47 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function test_string_gsub(str,reps)
local resultStrList = {}
string.gsub(str,'[^'..reps..']+', function(w)
table.insert(resultStrList,w)
return w
end)
end
local function test_ngx_string_gsub(str,reps)
local resultStrList = {}
ngx.re.gsub(str,'[^'..reps..']+', function(w)
table.insert(resultStrList,w[0])
return w
end, "ijo")
end
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
test_string_gsub("2409:8a62:e20:95f0:45b7:233e:f003:c0ab",",")
end
ngx.update_time()
ngx.say("test_string_gsub elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
test_ngx_string_gsub("2409:8a62:e20:95f0:45b7:233e:f003:c0ab",",")
end
ngx.update_time()
ngx.say("test_ngx_string_gsub elapsed: ", (ngx.now() - begin) / N)
+72
View File
@@ -0,0 +1,72 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function get_random_t1(n)
math.randomseed(ngx.time())
local t = {
"0","1","2","3","4","5","6","7","8","9",
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
}
local s = ""
for i = 1, n do
s = s .. t[math.random(#t)]
end
return s
end
local function get_random_t2(n)
local t = {
"0","1","2","3","4","5","6","7","8","9",
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
}
local s = ""
for i = 1, n do
s = s .. t[math.random(#t)]
end
return s
end
ngx.update_time()
local begin = ngx.now()
local N = 1e5
for i = 1, N do
get_random_t1(16)
end
ngx.update_time()
ngx.say("test get_random_t1 elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e5
math.randomseed(ngx.time())
for i = 1, N do
get_random_t2(16)
end
ngx.update_time()
ngx.say("test get_random_t2 elapsed: ", (ngx.now() - begin) / N)
+327
View File
@@ -0,0 +1,327 @@
# coding:utf-8
import sys
import io
import os
import time
import json
import os
import sys
import time
import string
import json
import hashlib
import shlex
import datetime
import subprocess
import re
from random import Random
TEST_URL = "http://t1.cn/"
# TEST_URL = "https://www.zzzvps.com/"
def writeFile(filename, str):
# 写文件内容
try:
fp = open(filename, 'w+')
fp.write(str)
fp.close()
return True
except Exception as e:
return False
def httpGet(url, timeout=10):
import urllib.request
try:
req = urllib.request.urlopen(url, timeout=timeout)
result = req.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpGet__Header(url, headers, timeout=10):
import urllib.request
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpUpload(url, timeout=10):
try:
import requests
files = {
'file': open('/Users/midoks/Desktop/mwdev/server/op_waf/version.pl', 'rb')
}
res = requests.post(url=url, files=files)
return res
except Exception as e:
return "http.upload:" + str(e)
def httpUploadPhp(url, timeout=10):
try:
import requests
writeFile("/tmp/tmp.php", "")
files = {
'file': open('/tmp/tmp.php', 'rb')
}
res = requests.post(url=url, files=files)
return res
except Exception as e:
return "http.upload:" + str(e)
def httpUploadPhpData(url, timeout=10):
try:
import requests
writeFile("/tmp/tmp.py", "<?php echo '123123';?>")
files = {
'file': open('/tmp/tmp.py', 'rb')
}
res = requests.post(url=url, files=files)
return res
except Exception as e:
return "http.upload:" + str(e)
def httpGet__UA(url, ua, timeout=10):
import urllib.request
headers = {'user-agent': ua}
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpGet__cdn(url, ip, timeout=10):
import urllib.request
headers = {'x-forwarded-for': ip}
try:
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req)
result = response.read().decode('utf-8')
return result
except Exception as e:
return str(e)
def httpPost(url, data, timeout=10):
"""
发送POST请求
@url 被请求的URL地址(必需)
@data POST参数,可以是字符串或字典(必需)
@timeout 超时时间默认60秒
return string
"""
if sys.version_info[0] == 2:
try:
import urllib
import urllib2
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
data = urllib.urlencode(data)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req, timeout=timeout)
return response.read()
except Exception as ex:
return str(ex)
else:
try:
import urllib.request
import ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:
pass
data = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(url, data)
response = urllib.request.urlopen(req, timeout=timeout)
result = response.read()
if type(result) == bytes:
result = result.decode('utf-8')
return result
except Exception as ex:
return str(ex)
def test_Dir():
'''
目录保存
'''
url = TEST_URL + '?t=../etc/passwd'
print("args test start")
url_val = httpGet(url, 10)
print(url_val)
print("args test end")
def test_UA():
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
url_val = httpGet__UA(url, 'ApacheBench')
print(url_val)
print("user-agent test end")
def test_Header():
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
url_val = httpGet__Header(url, {'X-forwarded-For': '../etc/passwd'})
print(url_val)
print("user-agent test end")
def test_UA_for(num):
'''
user-agent 过滤
'''
url = TEST_URL
print("user-agent test start")
for x in range(num):
url_val = httpGet__UA(url, 'ApacheBench')
print(url_val)
print("user-agent test end")
def test_cdn():
'''
user-agent 过滤
'''
url = TEST_URL
print("cdn test start")
url_val = httpGet__cdn(url, '2409:8a62:e20:95f0:45b7:233e:f003:c0ab')
print(url_val)
url_val2 = httpGet__cdn(url, '91.245.227.173')
print(url_val2)
print("cdn test end")
def test_POST():
'''
user-agent 过滤
'''
url = TEST_URL
print("POST test start")
url_val = httpPost(url, {'data': "substr($mmsss,0,1)"})
# url_val = httpPost(url, {'data': "123123"})
print(url_val)
print("POST test end")
def test_scan():
'''
目录保存
'''
url = TEST_URL + 'acunetix_wvs_security_test?t=1'
print("scan test start")
url_val = httpGet(url, 10)
print(url_val)
print("scan test end")
def test_CC():
'''
目录保存
'''
url = TEST_URL + 'ok.txt'
print("CC test start")
for x in range(122):
url_val = httpGet(url, 10)
print(url_val)
print("CC test end")
def test_url_ext():
'''
目录保存
'''
url = TEST_URL + 't.sql'
print("url_ext start")
url_val = httpGet(url, 10)
print(url_val)
print("url_ext end")
def test_OK():
'''
目录保存
'''
url = TEST_URL
print("ok test start")
url_val = httpGet(url, 10)
print(url_val)
print("ok test end")
def test_Upload():
'''
上传文件
'''
url = TEST_URL
print("upload test start")
url_val = httpUpload(url, 10)
print(url_val)
print("upload test end")
print("upload php test start")
url_val = httpUploadPhp(url, 10)
print(url_val)
print("upload php test start")
print("upload php data test start")
url_val = httpUploadPhpData(url, 10)
print(url_val)
print("upload php data test start")
def test_start():
# test_OK()
# test_Dir()
# test_UA()
test_Header()
# test_UA_for(1000)
test_POST()
test_scan()
# test_CC()
# test_url_ext()
# test_cdn()
# test_Upload()
if __name__ == "__main__":
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.2.2 && sh install.sh install 0.2.2')
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start')
test_start()
+82
View File
@@ -0,0 +1,82 @@
#!/bin/sh
export PATH=$PATH:/opt/stap/bin:/opt/stapxx
# https://moonbingbing.gitbooks.io/openresty-best-practices/content/flame_graph/install.html
# apt install elfutils
# sudo apt-get install -y systemtap gcc
# sudo apt-get install linux-headers-generic gcc libcap-dev
# apt-get install -y libdw-dev
# apt-get install -y fakeroot build-essential crash kexec-tools makedumpfile kernel-wedge kernel-package
# apt-get install -y git-core libncurses5 libncurses5-dev libelf-dev asciidoc binutils-dev
# apt-get build-dep linux
# cat > /etc/apt/sources.list.d/ddebs.list << EOF
# deb http://ddebs.ubuntu.com/ precise main restricted universe multiverse
# EOF
#
# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
# apt-get update
if [ $# -ne 2 ]
then
echo "Usage: ./`basename $0` lua/c NAME"
exit
fi
pid=`ps -ef|grep openresty | grep -v grep | awk '{print $2}'`
name=$2
# /opt/openresty-systemtap-toolkit/ngx-active-reqs -p 496435
# /opt/openresty-systemtap-toolkit/sample-bt -p 496435 -t 5 -k > a.bt
# kernel-debuginfo-common kernel-debuginfo
# apt install -y kernel-debuginfo-common kernel-debuginfo
# apt install -y kernel-*
# /opt/stapxx/samples/lj-lua-stacks.sxx --arg time=5 --skip-badvars -x 45266 > tmp.bt
if [ ! -d /opt/openresty-systemtap-toolkit ];then
cd /opt && git clone https://github.com/openresty/openresty-systemtap-toolkit
fi
if [ ! -d /opt/stapxx ];then
cd /opt && git clone https://github.com/openresty/stapxx
fi
# stap++ -I ./tapset -x 45266 --arg limit=10 samples/ngx-upstream-post-conn.sxx
# dpkg -i --force-overwrite /var/cache/apt/archives/linux-tools-common_5.4.0-128.144_all.deb
# /opt/openresty-systemtap-toolkit/ngx-active-reqs -p 45266
# git clone git://sourceware.org/git/systemtap.git
# ./configure --prefix=/opt/stap --disable-docs --disable-publican --disable-refdocs CFLAGS="-g -O2"
if [ ! -d /opt/FlameGraph ];then
cd /opt && git clone https://github.com/brendangregg/FlameGraph
fi
if [ $1 == "lua" ]; then
# /opt/openresty-systemtap-toolkit/ngx-sample-lua-bt -p 377452 --luajit20 -t 30 >temp.bt
/opt/openresty-systemtap-toolkit/ngx-sample-lua-bt -p $pid --luajit20 -t 30 >temp.bt
# /opt/openresty-systemtap-toolkit/fix-lua-bt temp.bt >t1.bt
/opt/openresty-systemtap-toolkit/fix-lua-bt temp.bt >${name}.bt
elif [ $1 == "c" ]; then
# /opt/openresty-systemtap-toolkit/sample-bt -p 496435 -t 10 -u > t2.bt
/opt/openresty-systemtap-toolkit/sample-bt -p $pid -t 10 -u > ${name}.bt
else
echo "type is only lua/c"
exit
fi
# /opt/FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded
# /opt/FlameGraph/flamegraph.pl perf.folded > perf.svg
/opt/FlameGraph/stackcollapse-stap.pl ${name}.bt >${name}.cbt
/opt/FlameGraph/flamegraph.pl ${name}.cbt >${name}.svg
rm -f temp.bt ${name}.bt ${name}.cbt
+18
View File
@@ -0,0 +1,18 @@
#!/bin/sh
# cd /www/server/mdserver-web/plugins/op_waf/t && sh ngx_demo.sh
# cd /www/wwwroot/dev156.cachecha.com && sh ngx_demo.sh
# only openresty
# pid=`ps -ef|grep openresty | grep -v grep | awk '{print $2}'`
# perf record -F 99 -p $pid -g -- sleep 60
#全部
perf record -F 99 -g -a -- sleep 60
perf script -i perf.data &> perf.unfold
/opt/FlameGraph/stackcollapse-perf.pl perf.unfold &> perf.folded
/opt/FlameGraph/flamegraph.pl perf.folded > perf.svg
+29
View File
@@ -0,0 +1,29 @@
# 火焰图安装 [ubuntu 20.04]
```
sudo apt-get install -y linux-tools-common linux-tools-generic linux-tools-`uname -r`
apt-get update -y
sudo apt -y install elfutils
apt-get install -y systemtap gcc
sudo apt-get install -y linux-headers-generic gcc libcap-dev
apt install -y kernel-debuginfo-common kernel-debuginfo
```
# 测试有效性
```
stap -ve 'probe begin { log("hello systemtap!") exit() }'
stap -e 'probe kernel.function("sys_open") {log("hello world") exit()}'
stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'
```
# openresty 测试
```
cd /www/server/mdserver-web/plugins/op_waf/t && sh ngx_debug.sh lua t1
cd /www/server/mdserver-web/plugins/op_waf/t && sh ngx_debug.sh c t2
```
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# apt -y install apache2-utils
# yum -y install httpd-tools
# ab -c 3000 -n 10000000 http://www.zzzvps.com/
# /cc https://www.zzzvps.com/ 120
# ab -c 10 -n 1000 http://t1.cn/wp-admin/index.php
# ab -c 1000 -n 1000000 http://dev156.cachecha.com/
curPath=`pwd`
rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath")
rootPath=$(dirname "$rootPath")
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
python3 index.py
+167
View File
@@ -0,0 +1,167 @@
# coding:utf-8
import sys
import io
import os
import time
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'op_waf'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getTaskConf():
conf = getServerDir() + "/task_config.json"
return conf
def getConfigData():
try:
return json.loads(mw.readFile(getTaskConf()))
except:
pass
return []
def getConfigTpl():
tpl = {
"name": "",
"task_id": -1,
}
return tpl
def createBgTask():
removeBgTask()
args = {
"period": "minute-n",
"minute-n": "1",
}
createBgTaskByName(getPluginName(), args)
def createBgTaskByName(name, args):
cfg = getConfigTpl()
_name = "[勿删]OP防火墙后台任务[" + name + "]"
res = mw.M("crontab").field("id, name").where("name=?", (_name,)).find()
if res:
return True
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
print("计划任务已经存在!")
return True
import crontab_api
cron_api = crontab_api.crontab_api()
period = args['period']
_hour = ''
_minute = ''
_where1 = ''
_type_day = "day"
if period == 'day':
_type_day = 'day'
_hour = args['hour']
_minute = args['minute']
elif period == 'minute-n':
_type_day = 'minute-n'
_where1 = args['minute-n']
_minute = ''
mw_dir = mw.getRunDir()
cmd = '''
mw_dir=%s
rname=%s
plugin_path=%s
script_path=%s
logs_file=$plugin_path/${rname}.log
''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "cd $mw_dir && source bin/activate && python3 $script_path/tool_task.py run >> $logs_file 2>&1"' + "\n"
cmd += 'cd $mw_dir && source bin/activate && python3 $script_path/tool_task.py run >> $logs_file 2>&1' + "\n"
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
params = {
'name': _name,
'type': _type_day,
'week': "",
'where1': _where1,
'hour': _hour,
'minute': _minute,
'save': "",
'backup_to': "",
'stype': "toShell",
'sname': '',
'sbody': cmd,
'urladdress': '',
}
task_id = cron_api.add(params)
if task_id > 0:
cfg["task_id"] = task_id
cfg["name"] = name
_dd = getConfigData()
_dd.append(cfg)
mw.writeFile(getTaskConf(), json.dumps(_dd))
def removeBgTask():
cfg_list = getConfigData()
for x in range(len(cfg_list)):
cfg = cfg_list[x]
if "task_id" in cfg.keys() and cfg["task_id"] > 0:
res = mw.M("crontab").field("id, name").where(
"id=?", (cfg["task_id"],)).find()
if res and res["id"] == cfg["task_id"]:
import crontab_api
api = crontab_api.crontab_api()
data = api.delete(cfg["task_id"])
if data[0]:
cfg["task_id"] = -1
cfg_list[x] = cfg
mw.writeFile(getTaskConf(), '[]')
return True
return False
def getCpuUsed():
import psutil
used = psutil.cpu_percent(interval=1)
path = getServerDir() + "/cpu.info"
mw.writeFile(path, str(int(used)))
def run():
getCpuUsed()
if __name__ == "__main__":
if len(sys.argv) > 1:
action = sys.argv[1]
if action == "remove":
removeBgTask()
elif action == "add":
createBgTask()
elif action == "run":
run()
+1
View File
@@ -0,0 +1 @@
自动生成配置文件
+1 -1
View File
@@ -1 +1 @@
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/btwaf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true}
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "过滤常见扫描测试工具的渗透测试", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "过虑CC攻击", "limit": 120, "endtime": 300, "open": true,"cycle": 60}, "safe_verify":{"status": 200,"ps": "强制安全校验", "reqfile": "safe_js.html","open": false,"cpu":50,"auto":true,"time":86400 },"get": {"status": 200, "ps": "过滤uri、uri参数中常见sql注入、xss等攻击", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 200, "ps": "通常用于过滤浏览器、蜘蛛及一些自动扫描器", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 200, "ps": "其它非通用过滤", "reqfile": "other.html"}, "cookie": {"status": 200, "ps": "过滤利用Cookie发起的渗透攻击", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 200, "ps": "过滤POST参数中常见sql注入、xss等攻击", "open": true, "reqfile": "post.html"}, "open": true}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
+151
View File
@@ -0,0 +1,151 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>OP网站防火墙|安全校验</title>
<style>
*{margin:0;padding:0;color:#444}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
#change{
font-size: 200px;
text-align: center;
}
</style>
</head>
<body>
<div class="main">
<div class="title">OP网站防火墙|安全校验</div>
<div class="content">
<p id="change">5</p>
</div>
<div id="status" style="display: none;">false</div>
</div>
</body>
<script type="text/javascript">
function ajax(type,bool){
var xhr = {};
if(typeof(type)=='undefined'){
xhr.type='HTML';
}else{
xhr.type=type.toUpperCase();
}
if(typeof(bool)=='undefined'){
xhr.async=true;
}else{
xhr.async=bool;
}
xhr.url = '';
xhr.send = '';
xhr.result=null;
xhr.createXHR = function(){
try{
request = new XMLHttpRequest();
if(request.overrideMimeType){
request.overrideMimeType('text/html');
}
}catch(e){
var v = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP',
'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for(var i=0;i<v.length;i++){
try{
request = new ActiveXObject(v[i]);
if(request){return request;}
}catch(e){continue;
}
}
}
return request;
}
xhr.XHR = xhr.createXHR();
xhr.processHandle = function(){
if( xhr.XHR.readyState ==4 && xhr.XHR.status==200){
if(xhr.type=='HTML'){
xhr.result(xhr.XHR.responseText);
return xhr.XHR.responseText;
}else if(xhr.type=='JSON'){
xhr.result(eval('('+xhr.XHR.responseText+')'));
return eval('('+xhr.XHR.responseText+')');
}else{
xhr.result(xhr.XHR.responseXML);
return xhr.XHR.responseXML;
}
}
};
xhr.get = function(url,result){
//添加回调函数
var name ='PHPjs';
var r = name + '_' + Math.random().toString().substr(2);//随机
xhr.url = url+'&'+name+'='+r;
if(result!=null){
xhr.XHR.onreadystatechange = xhr.processHandle;
xhr.result = result;
}
if(window.XMLHttpRequest){
xhr.XHR.open('GET',xhr.url,xhr.async);
xhr.XHR.send(null);
}else{
xhr.XHR.open('GET',xhr.url,xhr.async);
xhr.XHR.send();
}
};
xhr.post = function(url,send,result){
xhr.url = url;
if(typeof(send) == 'object'){
var str = '';
for(var pro in send){
str +=pro +'='+send[pro]+'&';
}
xhr.send = str.substr(0,str.length-1);
}else{
xhr.send = send;
}
if(result!=null){
xhr.XHR.onreadystatechange = xhr.processHandle;
xhr.result = result;
}
xhr.XHR.open('POST',url,xhr.async);
xhr.XHR.setRequestHeader('request-type','ajax');
xhr.XHR.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.XHR.send(xhr.send);
}
return xhr;
}
ajax('JSON',true).post('{uri}',{'pass':"ok"}, function(data){
if (data['status'] == 0){
document.getElementById('status').innerHTML = 'ok';
location.reload();
}
});
var ok = setInterval(function(){
var id = document.getElementById('change').innerHTML;
id = id - 1;
if (id == 0){
document.getElementById('change').innerHTML = '稍等';
clearInterval(ok);
if (document.getElementById('status').innerHTML == 'ok'){
location.reload();
}
} else {
document.getElementById('change').innerHTML = id;
}
},1000);
</script>
</html>
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
+494 -182
View File
@@ -1,26 +1,255 @@
local setmetatable = setmetatable
local _M = { _VERSION = '0.01' }
local _M = { _VERSION = '0.02' }
local mt = { __index = _M }
local json = require "cjson"
local sqlite3 = require "lsqlite3"
local ngx_match = ngx.re.find
local debug_mode = false
local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/"
local log_dir = waf_root.."/logs/"
local rpath = cpath.."/rule/"
function _M.new(self, cpath, rpath, logdir)
-- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath)
local opt = {
cpath = cpath,
rpath = rpath,
logdir = logdir,
config = '',
site_config = '',
params = nil
function _M.new(self)
local self = {
waf_root = waf_root,
cpath = cpath,
rpath = rpath,
logdir = log_dir,
config = '',
site_config = '',
server_name = '',
global_tatal = nil,
params = nil,
}
local p = setmetatable(opt, mt)
return p
return setmetatable(self, mt)
end
function _M.getInstance(self)
if rawget(self, "instance") == nil then
rawset(self, "instance", self:new())
if 0 == ngx.worker.id() then
self:cron()
end
end
assert(self.instance ~= nil)
return self.instance
end
function _M.initDB(self)
local path = log_dir .. "/waf.db"
db, err = sqlite3.open(path)
if err then
self:D("initDB err:"..tostring(err))
return nil
end
db:exec([[PRAGMA synchronous = 0]])
db:exec([[PRAGMA cache_size = 8000]])
db:exec([[PRAGMA page_size = 32768]])
db:exec([[PRAGMA journal_mode = wal]])
db:exec([[PRAGMA journal_size_limit = 1073741824]])
return db
end
-- 后台任务
function _M.cron(self)
local timer_every_get_data = function (premature)
self.clean_log()
end
ngx.timer.every(10, timer_every_get_data)
local timer_every_import_data = function (premature)
local llen, _ = ngx.shared.waf_limit:llen('waf_limit_logs')
if llen == 0 then
return true
end
local db = self:initDB()
local stmt2 = db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
db:exec([[BEGIN TRANSACTION]])
for i=1,llen do
local data, _ = ngx.shared.waf_limit:lpop('waf_limit_logs')
-- self:D("waf_limit_logs:"..data)
if not data then
break
end
local info = json.decode(data)
stmt2:bind_names{
time=info["time"],
ip=info["ip"],
domain=info["server_name"],
server_name=info["server_name"],
method=info["method"],
status_code=info["status_code"],
user_agent=info["user_agent"],
uri=info["request_uri"],
rule_name=info['rule_name'],
reason=info['reason']
}
local res, err = stmt2:step()
if tostring(res) == "5" then
self.D("waf the step database connection is busy, so it will be stored later.")
return false
end
stmt2:reset()
end
local res, err = db:execute([[COMMIT]])
if db and db:isopen() then
db:close()
end
end
ngx.timer.every(0.5, timer_every_import_data)
end
function _M.clean_log(self)
local db = self:initDB()
local now_date = os.date("*t")
local save_day = 90
local save_date_timestamp = os.time{year=now_date.year,
month=now_date.month, day=now_date.day-save_day, hour=0}
-- delete expire data
db:exec("DELETE FROM web_logs WHERE time<"..tostring(save_date_timestamp))
end
function _M.log(self, args, rule_name, reason)
args["rule_name"] = rule_name
args["reason"] = reason
local push_data = json.encode(args)
ngx.shared.waf_limit:rpush("waf_limit_logs", push_data)
-- self:D("push_data:"..push_data)
-- local db = self:initDB()
-- local stmt2 = db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
-- VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
-- db:exec([[BEGIN TRANSACTION]])
-- stmt2:bind_names{
-- time=args["time"],
-- ip=args["ip"],
-- domain=args["server_name"],
-- server_name=args["server_name"],
-- method=args["method"],
-- status_code=args["status_code"],
-- user_agent=args["user_agent"],
-- uri=args["request_uri"],
-- rule_name=rule_name,
-- reason=reason
-- }
-- local res, err = stmt2:step()
-- -- self:D("LOG[1]:"..tostring(res)..":"..tostring(err))
-- if tostring(res) == "5" then
-- self.D("waf the step database connection is busy, so it will be stored later.")
-- return false
-- end
-- stmt2:reset()
-- local res, err = db:execute([[COMMIT]])
-- -- self:D("LOG[2]:"..tostring(res)..":"..tostring(err))
-- if db and db:isopen() then
-- db:close()
-- end
-- return true
end
function _M.setDebug(self, mode)
debug_mode = mode
end
-- 调试方式
function _M.D(self, msg)
if not debug_mode then return true end
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = tostring( key)..':'.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
local fp = io.open(waf_root.."/debug.log", "ab")
if fp == nil then
return nil
end
-- local localtime = os.date("%Y-%m-%d %H:%M:%S")
local localtime = ngx.localtime()
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
function _M.is_working(self,sign)
local work_status = ngx.shared.waf_limit:get(sign.."_working")
if work_status ~= nil and work_status == true then
return true
end
return false
end
function _M.lock_working(self, sign)
local working_key = sign.."_working"
ngx.shared.waf_limit:set(working_key, true, 60)
end
function _M.unlock_working(self, sign)
local working_key = sign.."_working"
ngx.shared.waf_limit:set(working_key, false)
end
local function write_file_clear(filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
end
function _M.setConfData( self, config, site_config )
self.config = config
self.site_config = site_config
@@ -64,11 +293,11 @@ function _M.is_max(self,ip1,ip2)
end
function _M.split(self, str,reps )
local resultStrList = {}
local rsList = {}
string.gsub(str,'[^'..reps..']+',function(w)
table.insert(resultStrList,w)
table.insert(rsList,w)
end)
return resultStrList
return rsList
end
function _M.arrip(self, ipstr)
@@ -94,28 +323,41 @@ function _M.compare_ip(self,ips)
end
function _M.return_message(self, status, msg)
ngx.header.content_type = "application/json;"
ngx.status = status
ngx.say(json.encode(msg))
ngx.exit(status)
function _M.to_json(self, msg)
return json.encode(msg)
end
function _M.return_state(status,msg)
result = {}
result['status'] = status
result['msg'] = msg
return result
end
function _M.return_html(self,status,html)
function _M.return_message(self, status, msg)
ngx.header.content_type = "application/json"
local data = self:return_state(status, msg)
ngx.say(json.encode(data))
ngx.exit(200)
end
function _M.return_html(self, status, html)
ngx.header.content_type = "text/html"
ngx.status = status
ngx.say(html)
status = tonumber(status)
-- self:D("return_html:"..tostring(status))
if status == 200 then
ngx.say(html)
end
ngx.exit(status)
end
function _M.read_file_body(self, filename)
-- ngx.log(ngx.ERR,"read_file_body:"..filename)
fp = io.open(filename, 'r')
if fp == nil then
return nil
end
fbody = fp:read("*a")
local fbody = fp:read("*a")
fp:close()
if fbody == '' then
return nil
@@ -123,7 +365,38 @@ function _M.read_file_body(self, filename)
return fbody
end
function _M.read_file(self, name)
f = self.rpath .. name .. '.json'
local fbody = self:read_file_body(f)
if fbody == nil then
return {}
end
local data = json.decode(fbody)
return data
end
function _M.select_rule(self, rules)
if not rules then return {} end
new_rules = {}
for i,v in ipairs(rules)
do
if v[1] == 1 then
table.insert(new_rules,v[2])
end
end
return new_rules
end
function _M.read_file_table( self, name )
return self:select_rule(self:read_file(name))
end
function _M.read_file_body_decode(self, name)
return json.decode(self:read_file_body(name))
end
function _M.write_file(self, filename, body)
fp = io.open(filename,'ab')
@@ -137,34 +410,9 @@ function _M.write_file(self, filename, body)
end
function _M.write_file_clear(self, filename, body)
fp = io.open(filename,'w')
if fp == nil then
return nil
end
fp:write(body)
fp:flush()
fp:close()
return true
return write_file_clear(filename, body)
end
function _M.write_drop_ip(self, is_drop, drop_time)
local filename = self.cpath .. 'drop_ip.log'
local fp = io.open(filename,'ab')
local server_name = self.params["server_name"]
local ip = self.params["server_name"]
local request_uri = self.params["request_uri"]
if fp == nil then return false end
local logtmp = {os.time(),ip,server_name,request_uri,drop_time,is_drop}
local logstr = json.encode(logtmp) .. "\n"
fp:write(logstr)
fp:flush()
fp:close()
return true
end
function _M.write_to_file(self, logstr)
local server_name = self.params['server_name']
local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
@@ -172,10 +420,19 @@ function _M.write_to_file(self, logstr)
return true
end
-- 是否文件迁入数据库中
function _M.is_migrating(self)
local migrating = self.waf_root +"/migrating"
local file = io.open(migrating, "rb")
if file then return true end
return false
end
function _M.continue_key(self,key)
key = tostring(key)
if string.len(key) > 64 then return false end;
local keys = {"content","contents","body","msg","file","files","img","newcontent"}
local keys = { "content", "contents", "body", "msg", "file", "files", "img", "newcontent" }
for _,k in ipairs(keys)
do
if k == key then return false end;
@@ -195,7 +452,7 @@ function _M.array_len(self, arr)
end
function _M.is_ipaddr(self, client_ip)
local cipn = split(client_ip,'.')
local cipn = self:split(client_ip,'.')
if self:array_len(cipn) < 4 then return false end
for _,v in ipairs({1,2,3,4})
do
@@ -206,47 +463,31 @@ function _M.is_ipaddr(self, client_ip)
return true
end
function _M.read_file_body_decode(self, filename)
return json.decode(self:read_file_body(filename))
end
function _M.select_rule(self, rules)
if not rules then return {} end
new_rules = {}
for i,v in ipairs(rules)
do
if v[1] == 1 then
table.insert(new_rules,v[2])
end
end
return new_rules
end
function _M.read_file(self, name)
f = self.rpath .. name .. '.json'
fbody = self:read_file_body(f)
if fbody == nil then
return {}
end
return json.decode(fbody)
end
function _M.read_file_table( self, name )
return self:select_rule(self:read_file('args'))
end
function _M.inc_log(self, name, rule)
local server_name = self.params['server_name']
-- 定时异步同步统计信息
function _M.timer_stats_total(self)
local total_path = self.cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
if not tbody then
tbody = self:read_file_body(total_path)
if not tbody then return false end
local total = ngx.shared.waf_limit:get(total_path)
if not total then
return false
end
local total = json.decode(tbody)
return self:write_file_clear(total_path,total)
end
function _M.stats_total(self, name, rule)
local server_name = self.params['server_name']
local total_path = cpath .. 'total.json'
local total = ngx.shared.waf_limit:get(total_path)
if not total then
local tbody = self:read_file_body(total_path)
total = json.decode(tbody)
else
total = json.decode(total)
end
if not total then return false end
-- 开始计算
if not total['sites'] then total['sites'] = {} end
if not total['sites'][server_name] then total['sites'][server_name] = {} end
if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end
@@ -256,84 +497,124 @@ function _M.inc_log(self, name, rule)
total['total'] = total['total'] + 1
total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total)
if not total_log then return false end
ngx.shared.limit:set(total_path,total_log)
if not ngx.shared.limit:get('mw_waf_timeout') then
self:write_file_clear(total_path,total_log)
ngx.shared.limit:set('mw_waf_timeout',1,5)
end
ngx.shared.waf_limit:set(total_path,json.encode(total))
-- 异步执行
-- 现在改再init_workder.lua 定时执行
-- ngx.timer.every(3, timer_stats_total_log)
end
---------------------------------------------------
-- 获取配置域名
function _M.get_sn(self, config_domains)
local request_name = ngx.var.server_name
local cache_name = ngx.shared.waf_limit:get(request_name)
if cache_name then return cache_name end
function _M.get_server_name(self)
local c_name = ngx.var.server_name
local my_name = ngx.shared.limit:get(c_name)
if my_name then return my_name end
local tmp = self:read_file_body(self.cpath .. 'domains.json')
if not tmp then return c_name end
local domains = json.decode(tmp)
for _,v in ipairs(domains)
for _,v in ipairs(config_domains)
do
for _,d_name in ipairs(v['domains'])
for _,cd_name in ipairs(v['domains'])
do
if c_name == d_name then
ngx.shared.limit:set(c_name,v['name'],3600)
if request_name == cd_name then
ngx.shared.waf_limit:set(request_name,v['name'],86400)
return v['name']
end
end
end
return c_name
return request_name
end
function _M.get_random(self,n)
math.randomseed(ngx.time())
local t = {
"0","1","2","3","4","5","6","7","8","9",
"a","b","c","d","e","f","g","h","i","j",
"k","l","m","n","o","p","q","r","s","t",
"u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z",
}
local s = ""
for i =1, n do
s = s .. t[math.random(#t)]
end
return s
end
-- function _M.get_sn(self)
-- retun string.gsub(self:get_server_name(),'_','.')
-- end
function _M.is_ngx_match(self, rules, sbody, rule_name)
if rules == nil or sbody == nil then return false end
if type(sbody) == "string" then
sbody = {sbody}
end
if type(rules) == "string" then
rules = {rules}
function _M.is_ngx_match_orgin(self,rule, match, sign)
if ngx_match(ngx.unescape_uri(match), rule, "isjo") then
error_rule = rule .. ' >> ' .. sign .. ':' .. match
return true
end
return false
end
for k,body in pairs(sbody)
function _M.ngx_match_string(self, rule, content,sign)
local t = self:is_ngx_match_orgin(rule, content, sign)
if t then
return true
end
return false
end
function _M.ngx_match_list(self, rules, content)
local args_type = type(content)
for i,rule in ipairs(rules)
do
if self:continue_key(k) then
for i,rule in ipairs(rules)
do
if self.site_config[server_name] and rule_name then
local n = i - 1
for _,j in ipairs(self.site_config[server_name]['disable_rule'][rule_name])
do
if n == j then
rule = ""
end
end
end
if body and rule ~="" then
if type(body) == "string" then
if ngx_match(ngx.unescape_uri(body),rule,"isjo") then
error_rule = rule .. ' >> ' .. k .. ':' .. body
return true
end
end
if type(k) == "string" then
if ngx_match(ngx.unescape_uri(k),rule,"isjo") then
error_rule = rule .. ' >> ' .. k
return true
end
if rule[1] == 1 then
if args_type == 'string' then
-- self:D("string: "..tostring(rule[2])..":".. tostring(content)..":"..tostring(rule[3]))
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
if args_type == 'table' then
for _,arg_v in pairs(content) do
-- self:D("table : "..tostring(rule[2])..":".. tostring(arg_v)..":"..tostring(rule[3]))
local t = self:is_ngx_match_orgin(rule[2], arg_v, rule[3])
if t then
return true
end
end
end
end
end
return false
end
function _M.is_ngx_match_ua(self, rules, content)
-- ngx.header.content_type = "text/html"
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
end
end
return false
end
function _M.is_ngx_match_post(self, rules, content)
for i,rule in ipairs(rules)
do
-- 开启的规则,才匹配。
if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2],content, rule[3])
if t then
return true
end
end
end
return false
@@ -341,63 +622,84 @@ end
function _M.write_log(self, name, rule)
local ip = self.params['ip']
local retry = self.config['retry']['retry']
local retry_time = self.config['retry']['retry_time']
local retry_cycle = self.config['retry']['retry_cycle']
local config = self.config
local params = self.params
local ip = params['ip']
local ngx_time = ngx.time()
local count, _ = ngx.shared.drop_ip:get(ip)
local retry = config['retry']['retry']
local retry_time = config['retry']['retry_time']
local retry_cycle = config['retry']['retry_cycle']
local count = ngx.shared.waf_drop_ip:get(ip)
if count then
ngx.shared.drop_ip:incr(ip,1)
ngx.shared.waf_drop_ip:incr(ip, 1)
else
ngx.shared.drop_ip:set(ip,1,retry_cycle)
ngx.shared.waf_drop_ip:set(ip, 1, retry_cycle)
end
if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end
local method = ngx.req.get_method()
if config['log'] ~= true or self:is_site_config('log') ~= true then return false end
local method = params['method']
if error_rule then
rule = error_rule
error_rule = nil
end
local logtmp = {ngx.localtime(), ip, method, ngx.var.request_uri, ngx.var.http_user_agent, name, rule}
local logstr = json.encode(logtmp) .. "\n"
local count,_ = ngx.shared.drop_ip:get(ip)
if count > retry and name ~= 'cc' then
local safe_count,_ = ngx.shared.drop_sum:get(ip)
local count = ngx.shared.waf_drop_ip:get(ip)
-- self:D("write_log; count:" ..tostring(count).. ",retry:" .. tostring(retry) )
if (count > retry and name ~= 'cc') then
local safe_count,_ = ngx.shared.waf_drop_sum:get(ip)
if not safe_count then
ngx.shared.drop_sum:set(ip,1,86400)
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
safe_count = 1
else
ngx.shared.drop_sum:incr(ip,1)
ngx.shared.waf_drop_sum:incr(ip, 1)
end
local lock_time = retry_time * safe_count
if lock_time > 86400 then lock_time = 86400 end
logtmp = {ngx.localtime(),ip,method,ngx.var.request_uri, ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'}
logstr = logstr .. json.encode(logtmp) .. "\n"
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
self:write_drop_ip('inc',lock_time)
retry_times = retry + 1
ngx.shared.waf_drop_ip:set(ip, retry_times, lock_time)
local reason = retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'
self:log(params, name, reason)
elseif name ~= 'cc' then
self:log(params, name, rule)
end
self:write_to_file(logstr)
self:inc_log(name,rule)
self:stats_total(name, rule)
end
function _M.get_client_ip(self)
function _M.get_real_ip(self, server_name)
local client_ip = "unknown"
if self.site_config[server_name] then
if self.site_config[server_name]['cdn'] then
for _,v in ipairs(self.site_config[server_name]['cdn_header'])
local site_config = self.site_config
if site_config[server_name] then
if site_config[server_name]['cdn'] then
local request_header = ngx.req.get_headers()
for _,v in ipairs(site_config[server_name]['cdn_header'])
do
if request_header[v] ~= nil and request_header[v] ~= "" then
local header_tmp = request_header[v]
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end
client_ip = split(header_tmp,',')[1]
client_ip = self:split(header_tmp,',')[1]
-- return client_ip
break;
end
end
end
end
if string.match(client_ip,"%d+%.%d+%.%d+%.%d+") == nil or not self:is_ipaddr(client_ip) then
-- ipv6
if type(client_ip) == 'table' then client_ip = "" end
if client_ip ~= "unknown" and ngx.re.match(client_ip,"^([a-fA-F0-9]*):") then
return client_ip
end
-- ipv4
if not ngx.re.match(client_ip,"\\d+\\.\\d+\\.\\d+\\.\\d+") == nil or not self:is_ipaddr(client_ip) then
client_ip = ngx.var.remote_addr
if client_ip == nil then
client_ip = "unknown"
@@ -408,12 +710,12 @@ end
function _M.is_site_config(self,cname)
local server_name = self.params["server_name"]
if self.site_config[server_name] ~= nil then
local site_config = self.site_config
if site_config[server_name] ~= nil then
if cname == 'cc' then
return self.site_config[server_name][cname]['open']
return site_config[server_name][cname]['open']
else
return self.site_config[server_name][cname]
return site_config[server_name][cname]
end
end
return true
@@ -434,6 +736,16 @@ function _M.get_boundary(self)
end
function _M.is_key(self, arr, key)
for _,v in ipairs(arr) do
if v == key then
return true
end
end
return false
end
function _M.return_post_data(self)
if method ~= "POST" then return false end
content_length = tonumber(self.params["request_header"]['content-length'])
+322 -387
View File
@@ -1,171 +1,167 @@
local cpath = "{$WAF_PATH}/"
local rpath = "{$WAF_PATH}/rule/"
local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
local json = require "cjson"
local ngx_match = ngx.re.find
local _C = require "common"
local C = _C:new(cpath, rpath, logdir)
local __WAF = require "common"
-- print(json.encode(__C))
local C = __WAF:getInstance()
local config = require "waf_config"
local site_config = require "waf_site"
local config_domains = require "waf_domains"
-- C:D("config:"..C:to_json(config))
config = C:read_file_body_decode(cpath .. 'config.json')
local site_config = C:read_file_body_decode(cpath .. 'site.json')
C:setConfData(config, site_config)
C:setDebug(true)
-- D func
local function D(msg)
local _msg = ''
if type(msg) == 'table' then
for key, val in pairs(msg) do
_msg = key..':'..val.."\n"
end
elseif type(msg) == 'string' then
_msg = msg
elseif type(msg) == 'nil' then
_msg = 'nil'
else
_msg = msg
end
if not debug_mode then return true end
local fp = io.open(cpath..'debug.log', 'ab')
if fp == nil then
return nil
end
local localtime = os.date("%Y-%m-%d %H:%M:%S")
if server_name then
fp:write(tostring(_msg) .. "\n")
else
fp:write(localtime..":"..tostring(_msg) .. "\n")
end
fp:flush()
fp:close()
return true
end
local get_html = require "html_get"
local post_html = require "html_post"
local other_html = require "html_other"
local user_agent_html = require "html_user_agent"
local cc_safe_js_html = require "html_safe_js"
function initParams()
local args_rules = require "rule_args"
local ip_white_rules = require "rule_ip_white"
local ip_black_rules = require "rule_ip_black"
local ipv6_black_rules = require "rule_ipv6_black"
local scan_black_rules = require "rule_scan_black"
local user_agent_rules = require "rule_user_agent"
local post_rules = require "rule_post"
local cookie_rules = require "rule_cookie"
local url_rules = require "rule_url"
local server_name = string.gsub(C:get_sn(config_domains),'_','.')
local function initParams()
local data = {}
data['ip'] = C:get_client_ip()
data['server_name'] = server_name
data['ip'] = C:get_real_ip(server_name)
data['ipn'] = C:arrip(data['ip'])
data['request_header'] = ngx.req.get_headers()
data['uri'] = ngx.unescape_uri(ngx.var.uri)
data['server_name'] = string.gsub(C:get_server_name(),'_','.')
data['uri_request_args'] = ngx.req.get_uri_args()
data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri
data['status_code'] = ngx.status
data['user_agent'] = data['request_header']['user-agent']
data['cookie'] = ngx.var.http_cookie
data['time'] = ngx.time()
return data
end
local params = initParams()
C:setParams(params)
local cpu_percent = ngx.shared.waf_limit:get("cpu_usage")
if not cpu_percent then
cpu_percent = 0
end
function get_return_state(rstate,rmsg)
local function get_return_state(rstate,rmsg)
result = {}
result['status'] = rstate
result['msg'] = rmsg
return result
end
function get_waf_drop_ip()
local data = ngx.shared.drop_ip:get_keys(0)
local function get_waf_drop_ip()
local data = ngx.shared.waf_drop_ip:get_keys(0)
return data
end
local function return_json(status,msg)
ngx.header.content_type = "application/json"
result = {}
result['status'] = status
result['msg'] = msg
ngx.say(json.encode(data))
ngx.exit(200)
end
function is_chekc_table(data,strings)
local function is_chekc_table(data,strings)
if type(data) ~= 'table' then return 1 end
if not data then return 1 end
data=chekc_ip_timeout(data)
data = chekc_ip_timeout(data)
for k,v in pairs(data)
do
if strings ==v['ip'] then
if strings == v['ip'] then
return 3
end
end
return 2
end
function save_ip_on(data)
locak_file=read_file_body(cpath2 .. 'stop_ip.lock')
if not locak_file then
C:write_file(cpath2 .. 'stop_ip.lock','1')
local function remove_waf_drop_ip()
ngx.header.content_type = "application/json"
local ip = params['uri_request_args']['ip']
if not ip or not C:is_ipaddr(ip) then
local data = get_return_state(-1, "格式错误")
ngx.say(json.encode(data))
ngx.exit(200)
return true
end
name='stop_ip'
local extime=18000
data=json.encode(data)
ngx.shared.btwaf:set(cpath2 .. name,data,extime)
if not ngx.shared.btwaf:get(cpath2 .. name .. '_lock') then
ngx.shared.btwaf:set(cpath2 .. name .. '_lock',1,0.5)
C:write_file(cpath2 .. name .. '.json',data)
local sign = "remove_waf_drop_ip"
if C:is_working(sign) then
local data = get_return_state(-1, "fail")
ngx.say(json.encode(data))
ngx.exit(200)
return true
end
C:lock_working(sign)
ngx.shared.waf_drop_ip:delete(ip)
C:unlock_working(sign)
local data = get_return_state(0, "ok")
ngx.say(json.encode(data))
ngx.exit(200)
end
function remove_btwaf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data=json.decode(ret)
result=is_chekc_table(ip_data,uri_request_args['ip'])
os.execute("sleep " .. 0.6)
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2)
if result == 3 then
for k,v in pairs(ip_data2)
do
if uri_request_args['ip'] == v['ip'] then
v['time']=0
end
end
end
save_ip_on(ip_data2)
local function clean_waf_drop_ip()
ngx.header.content_type = "application/json"
local sign = "clean_waf_drop_ip"
if C:is_working(sign) then
local data = get_return_state(-1, "fail")
ngx.say(json.encode(data))
ngx.exit(200)
return true
end
ngx.shared.drop_ip:delete(uri_request_args['ip'])
return get_return_state(true,uri_request_args['ip'] .. '已解封')
C:lock_working(sign)
ngx.shared.waf_drop_ip:flush_all()
C:unlock_working(sign)
local data = get_return_state(0, "ok")
ngx.say(json.encode(data))
ngx.exit(200)
end
function clean_btwaf_drop_ip()
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
ip_data2=json.decode(ret2)
for k,v in pairs(ip_data2)
do
v['time']=0
end
save_ip_on(ip_data2)
os.execute("sleep " .. 2)
end
local data = get_btwaf_drop_ip()
for _,value in ipairs(data)
do
ngx.shared.drop_ip:delete(value)
end
return get_return_state(true,'已解封所有封锁IP')
end
function min_route()
local function min_route()
if ngx.var.remote_addr ~= '127.0.0.1' then return false end
local uri = params['uri']
if uri == '/get_waf_drop_ip' then
return_message(200,get_waf_drop_ip())
ngx.header.content_type = "application/json"
local data = get_return_state(0, get_waf_drop_ip())
ngx.say(json.encode(data))
ngx.exit(200)
elseif uri == '/remove_waf_drop_ip' then
return_message(200,remove_waf_drop_ip())
remove_waf_drop_ip()
elseif uri == '/clean_waf_drop_ip' then
return_message(200,clean_waf_drop_ip())
clean_waf_drop_ip()
end
end
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
local args_rules = C:read_file_table('args')
local ip_white_rules = C:read_file('ip_white')
local ip_black_rules = C:read_file('ip_black')
local scan_black_rules = C:read_file('scan_black')
function waf_args()
local function waf_get_args()
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then
-- C:D("waf_get_args:"..C:to_json(args_rules)..":"..json.encode(params['uri_request_args']))
if C:ngx_match_list(args_rules, params['uri_request_args']) then
C:write_log('args','regular')
C:return_html(config['get']['status'], get_html)
return true
@@ -174,7 +170,7 @@ function waf_args()
end
function waf_ip_white()
local function waf_ip_white()
for _,rule in ipairs(ip_white_rules)
do
if C:compare_ip(rule) then
@@ -184,7 +180,8 @@ function waf_ip_white()
return false
end
function waf_ip_black()
local function waf_ip_black()
-- ipv4 ip black
for _,rule in ipairs(ip_black_rules)
do
if C:compare_ip(rule) then
@@ -192,115 +189,198 @@ function waf_ip_black()
return true
end
end
-- ipv6 ip black
for _,rule in ipairs(ipv6_black_rules)
do
if rule == params['ip'] then
ngx.exit(config['cc']['status'])
return true
end
end
return false
end
function waf_drop()
local count,_ = ngx.shared.drop_ip:get(ip)
local function waf_user_agent()
-- user_agent 过滤
-- if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
-- C:D("waf_user_agent;user_agent_rules:"..json.encode(user_agent_rules)..",ua:"..tostring(params['request_header']['user-agent']))
if C:is_ngx_match_ua(user_agent_rules, params['request_header']['user-agent']) then
-- C:D("waf_user_agent........... true")
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'], user_agent_html)
return true
end
-- C:D("waf_user_agent........... false")
return false
end
local function waf_drop_ip()
local ip = params['ip']
local count = ngx.shared.waf_drop_ip:get(ip)
if not count then return false end
if count > config['retry'] then
local retry = config['retry']['retry']
-- C:D("waf_drop;count:"..tostring(count)..",retry:"..tostring(retry))
-- C:D("waf_drop;count > retry:"..tostring(count > retry))
if count > retry then
-- C:D("waf_drop_ip........... true")
ngx.exit(config['cc']['status'])
return true
end
-- C:D("waf_drop_ip........... false")
return false
end
local function waf_cc()
if not config['cc']['open'] or not C:is_site_config('cc') then return false end
function waf_user_agent()
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match(user_agent_rules,params['request_header']['user-agent'],'user_agent') then
C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html)
return true
end
return false
end
function cc()
local ip = params['ip']
local request_uri = params['request_uri']
local endtime = config['cc']['endtime']
if not config['cc']['open'] or not site_cc then return false end
-- 多次cc,才封禁。
-- local ip_lock = ngx.shared.waf_drop_ip:get(ip)
-- if ip_lock then
-- if ip_lock > 0 then
-- ngx.exit(config['cc']['status'])
-- return true
-- end
-- end
local request_uri = params['request_uri']
local token = ngx.md5(ip .. '_' .. request_uri)
local count,_ = ngx.shared.limit:get(token)
local count = ngx.shared.waf_limit:get(token)
local endtime = config['cc']['endtime']
local waf_limit = config['cc']['limit']
local cycle = config['cc']['cycle']
if count then
if count > limit then
local safe_count,_ = ngx.shared.drop_sum:get(ip)
if count > waf_limit then
local safe_count, _ = ngx.shared.waf_drop_sum:get(ip)
if not safe_count then
ngx.shared.drop_sum:set(ip,1,86400)
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
safe_count = 1
else
ngx.shared.drop_sum:incr(ip,1)
ngx.shared.waf_drop_sum:incr(ip, 1)
end
local lock_time = (endtime * safe_count)
if lock_time > 86400 then lock_time = 86400 end
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '秒')
C:write_drop_ip('cc',lock_time)
if not server_name then
insert_ip_list(ip,lock_time,os.time(),'1111')
else
insert_ip_list(ip,lock_time,os.time(),server_name)
end
ngx.shared.waf_drop_ip:set(ip, 1, lock_time)
local reason = cycle..'秒内累计超过'..waf_limit..'次请求,封锁' .. lock_time .. '秒'
C:write_log('cc', reason)
C:log(params, 'cc',reason)
ngx.exit(config['cc']['status'])
return true
else
ngx.shared.limit:incr(token,1)
ngx.shared.waf_limit:incr(token, 1)
end
else
ngx.shared.limit:set(token,1,cycle)
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
ngx.shared.waf_limit:set(token, 1, cycle)
end
return false
end
-- 是否符合开强制验证条件
local function is_open_waf_cc_increase()
if config['safe_verify']['open'] then
return true
end
if site_config[server_name]['safe_verify']['open'] then
return true
end
if cpu_percent >= config['safe_verify']['cpu'] then
return true
end
if cpu_percent >= site_config[server_name]['safe_verify']['cpu'] then
return true
end
return false
end
--强制验证是否使用正常浏览器访问网站
function waf_cc_increase()
if not config['cc']['open'] or not site_cc then return false end
if not site_config[server_name] then return false end
if not site_config[server_name]['cc']['increase'] then return false end
local function waf_cc_increase()
if not is_open_waf_cc_increase() then return false end
local ip = params['ip']
local uri = params['uri']
local cache_token = ngx.md5(ip .. '_' .. server_name)
--判断是否已经通过验证
if ngx.shared.btwaf:get(cache_token) then return false end
if cc_uri_white() then
ngx.shared.btwaf:delete(cache_token .. '_key')
ngx.shared.btwaf:set(cache_token,1,60)
return false
if ngx.shared.waf_limit:get(cache_token) then return false end
local cache_rand_key = ip..':rand'
local cache_rand = ngx.shared.waf_limit:get(cache_rand_key)
if not cache_rand then
cache_rand = C:get_random(8)
ngx.shared.waf_limit:set(cache_rand_key,cache_rand,30)
end
if security_verification() then return false end
send_check_heml(cache_token)
local make_token = "waf_unbind_"..cache_rand.."_"..cache_token
local make_uri_str = "?token="..make_token
local make_uri = "/"..make_uri_str
if params['uri_request_args']['token'] then
local args_token = params['uri_request_args']['token']
if args_token == make_token then
ngx.shared.waf_limit:set(cache_token, 1, config['safe_verify']['time'])
local data = get_return_state(0, "ok")
ngx.say(json.encode(data))
ngx.exit(200)
end
end
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
C:return_html(200, cc_html)
end
function waf_url()
local function waf_url()
if not config['get']['open'] or not C:is_site_config('get') then return false end
--正则--
if C:is_ngx_match(url_rules,params["uri"],'url') then
-- C:D("waf_url:"..json.encode(url_rules)..":uri:"..params["uri"])
if C:ngx_match_list(url_rules, params["uri"]) then
C:write_log('url','regular')
C:return_html(config['get']['status'],get_html)
C:return_html(config['get']['status'], get_html)
return true
end
return false
end
function waf_scan_black()
local function waf_scan_black()
-- 扫描软件禁止
if not config['scan']['open'] or not C:is_site_config('scan') then return false end
if C:is_ngx_match(scan_black_rules['cookie'],params["request_header"]["cookie"],false) then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
if C:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then
if not params["cookie"] then
if C:ngx_match_string(scan_black_rules['cookie'], tostring(params["cookie"]),'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
end
if C:ngx_match_string(scan_black_rules['args'], params["request_uri"], 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
end
for key,value in pairs(params["request_header"])
do
if C:is_ngx_match(scan_black_rules['header'], key, false) then
if C:ngx_match_string(scan_black_rules['header'], key, 'scan') then
C:write_log('scan','regular')
ngx.exit(config['scan']['status'])
return true
@@ -309,253 +389,120 @@ function waf_scan_black()
return false
end
function waf_post_referer()
if params['method'] ~= "POST" then return false end
if C:is_ngx_match(referer_local, params['request_header']['Referer'],'post') then
C:write_log('post_referer','regular')
C:return_html(config['post']['status'],post_html)
return true
end
return false
end
function waf_post()
local function waf_post()
if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end
if waf_post_referer() then return true end
content_length = tonumber(params["request_header"]['content-length'])
max_len = 640 * 1020000
local content_length = tonumber(params["request_header"]['content-length'])
local max_len = 640 * 1020000
if content_length > max_len then return false end
if C:get_boundary() then return false end
ngx.req.read_body()
request_args = ngx.req.get_post_args()
if not request_args then
return false
local request_args = params['uri_request_args']
if not request_args then return false end
for key, val in pairs(request_args) do
if type(val) == "table" then
if type(val[1]) == "boolean" then
return false
end
data = table.concat(val, ", ")
else
data = val
end
end
if C:is_ngx_match(post_rules,request_args,'post') then
-- C:D("post:"..json.encode(data))
if C:ngx_match_list(post_rules, data) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
C:return_html(config['post']['status'], post_html)
return true
end
return false
end
local function X_Forwarded()
function post_data_chekc()
if params['method'] =="POST" then
if C:return_post_data() then return false end
ngx.req.read_body()
request_args = ngx.req.get_post_args()
if not request_args then return false end
if request_header then
if not request_header['Content-Type'] then return false end
av = string.match(request_header['Content-Type'],"=.+")
end
if not av then return false end
ac = split(av,'=')
if not ac then return false end
list_list=nil
for i,v in ipairs(ac)
do
list_list='--'..v
end
if not list_list then return false end
aaa=nil
for k,v in pairs(request_args)
do
aaa=v
end
if not aaa then return false end
if tostring(aaa) == 'true' then return false end
if type(aaa) ~= "string" then return false end
data_len=split(aaa,list_list)
--return return_message(200,data_len)
if not data_len then return false end
if arrlen(data_len) ==0 then return false end
if C:is_ngx_match(post_rules,data_len,'post') then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
return true
end
end
end
function X_Forwarded()
if params['method'] ~= "GET" then return false end
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(args_rules,params["request_header"]['X-forwarded-For'],'args') then
if not params["request_header"]['X-forwarded-For'] then return false end
if C:ngx_match_list(args_rules, params["request_header"]['X-forwarded-For']) then
C:write_log('args','regular')
C:return_html(config['get']['status'],get_html)
C:return_html(config['get']['status'], get_html)
return true
end
return false
end
function post_X_Forwarded()
local function post_X_Forwarded()
if not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end
if C:is_ngx_match(post_rules,params["request_header"]['X-forwarded-For'],'post') then
if not params["request_header"]['X-forwarded-For'] then return false end
if C:is_ngx_match_list(post_rules, params["request_header"]['X-forwarded-For']) then
C:write_log('post','regular')
C:return_html(config['post']['status'],post_html)
C:return_html(config['post']['status'], post_html)
return true
end
return false
end
function php_path()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_php_path'])
do
if ngx_match(uri,rule .. "/?.*\\.php$","isjo") then
C:write_log('php_path','regular')
C:return_html(config['other']['status'],other_html)
return C:return_message(200,uri)
end
end
return false
end
function url_path()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_path'])
do
if ngx_match(uri,rule,"isjo") then
C:write_log('path','regular')
C:return_html(config['other']['status'],other_html)
return true
end
end
return false
end
function url_ext()
local function url_ext()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_ext'])
do
if ngx_match(uri,"\\."..rule.."$","isjo") then
C:write_log('url_ext','regular')
C:return_html(config['other']['status'],other_html)
if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then
if rule == "php" then
C:write_log('php_path','regular')
else
C:write_log('path','regular')
end
C:return_html(config['other']['status'], other_html)
return true
end
end
return false
end
function url_rule_ex()
if site_config[server_name] == nil then return false end
if method == "POST" and not request_args then
content_length=tonumber(request_header['content-length'])
max_len = 640 * 102400000
request_args = nil
if content_length < max_len then
ngx.req.read_body()
request_args = ngx.req.get_post_args()
end
end
for _,rule in ipairs(site_config[server_name]['url_rule'])
do
if ngx_match(uri,rule[1],"isjo") then
if C:is_ngx_match(rule[2],uri_request_args,false) then
C:write_log('url_rule','regular')
C:return_html(config['other']['status'],other_html)
return true
end
if params['method'] == "POST" and request_args ~= nil then
if C:is_ngx_match(rule[2],request_args,'post') then
C:write_log('post','regular')
C:return_html(config['other']['status'],other_html)
return true
end
end
end
end
return false
end
function url_tell()
if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['url_tell'])
do
if ngx_match(uri,rule[1],"isjo") then
if uri_request_args[rule[2]] ~= rule[3] then
C:write_log('url_tell','regular')
C:return_html(config['other']['status'],other_html)
return true
end
end
end
return false
end
function disable_upload_ext(ext)
local function disable_upload_ext(ext)
if not ext then return false end
ext = string.lower(ext)
if is_key(site_config[server_name]['disable_upload_ext'],ext) then
C:write_log('upload_ext','上传扩展名黑名单')
if C:is_key(site_config[server_name]['disable_upload_ext'], ext) then
C:write_log('upload_ext', '上传扩展名黑名单')
C:return_html(config['other']['status'],other_html)
return true
end
return false
end
function data_in_php(data)
if not data then
return false
else
if C:is_ngx_match('php',data,'post') then
C:write_log('upload_ext','上传扩展名黑名单')
C:return_html(config['other']['status'],other_html)
return true
else
return false
end
end
end
function post_data()
local function post_data()
if params["method"] ~= "POST" then return false end
content_length = tonumber(params["request_header"]['content-length'])
-- C:D("content-length:"..params["request_header"]['content-length'])
local content_length = tonumber(params["request_header"]['content-length'])
if not content_length then return false end
max_len = 2560 * 1024000
local max_len = 2560 * 1024000
if content_length > max_len then return false end
local boundary = C:get_boundary()
-- C:D("boundary:".. tostring( boundary) )
if boundary then
ngx.req.read_body()
local data = ngx.req.get_body_data()
if not data then return false end
local tmp = ngx.re.match(data,[[filename=\"(.+)\.(.*)\"]])
if not tmp then return false end
if not tmp[2] then return false end
local tmp2=ngx.re.match(ngx.req.get_body_data(),[[Content-Type:[^\+]{45}]])
--return return_message(200,tmp2[0])
if not tmp or not tmp[2] then return false end
-- C:D("upload_ext:".. tostring(tmp[2]) )
disable_upload_ext(tmp[2])
if tmp2 == nil then return false end
data_in_php(tmp2[0])
end
return false
end
function waf_cookie()
local function waf_cookie()
if not config['cookie']['open'] or not C:is_site_config('cookie') then return false end
if not params["request_header"]['cookie'] then return false end
if type(params["request_header"]['cookie']) ~= "string" then return false end
request_cookie = string.lower(params["request_header"]['cookie'])
if C:is_ngx_match(cookie_rules,request_cookie,'cookie') then
if C:ngx_match_list(cookie_rules,request_cookie,'cookie') then
C:write_log('cookie','regular')
C:return_html(config['cookie']['status'],cookie_html)
return true
@@ -563,55 +510,43 @@ function waf_cookie()
return false
end
function waf_referer()
if params["method"] ~= "GET" then return false end
if not config['get']['open'] or not C:is_site_config('get') then return false end
if C:is_ngx_match(referer_local,params["request_header"]['Referer'],'args') then
C:write_log('get_referer','regular')
C:return_html(config['get']['status'], get_html)
return true
end
return false
end
function waf()
min_route()
-- white ip
if waf_ip_white() then return true end
waf_ip_black()
-- black ip
if waf_ip_black() then return true end
waf_drop()
waf_user_agent()
-- 封禁ip返回
if waf_drop_ip() then return true end
waf_url()
-- ua check
if waf_user_agent() then return true end
if waf_url() then return true end
if params["method"] == "GET" then
waf_referer()
waf_cookie()
end
-- cc setting
if waf_cc_increase() then return true end
if waf_cc() then return true end
if params["method"] == "POST" then
waf_referer()
waf_cookie()
end
-- cookie检查
if waf_cookie() then return true end
-- args参数拦截
if waf_get_args() then return true end
waf_args()
waf_scan_black()
-- 扫描软件禁止
if waf_scan_black() then return true end
waf_post()
post_data_chekc()
local server_name = params["server_name"]
if site_config[server_name] then
X_Forwarded()
post_X_Forwarded()
php_path()
url_path()
url_ext()
url_rule_ex()
url_tell()
post_data()
if waf_post() then return true end
if site_config[server_name] and site_config[server_name]['open'] then
if X_Forwarded() then return true end
if post_X_Forwarded() then return true end
if url_ext() then return true end
if post_data() then return true end
end
end
+31
View File
@@ -0,0 +1,31 @@
local json = require "cjson"
local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/"
local __C = require "common"
local C = __C:getInstance()
local function timer_stats_total_log(premature)
C:timer_stats_total()
end
ngx.shared.waf_limit:set("cpu_usage", 0, 10)
function timer_every_get_cpu(premature)
local cpu_percent = C:read_file_body(waf_root.."/cpu.info")
if cpu_percent then
ngx.shared.waf_limit:set("cpu_usage", tonumber(cpu_percent), 10)
else
ngx.shared.waf_limit:set("cpu_usage", 0, 10)
end
end
if 0 == ngx.worker.id() then
ngx.timer.every(5, timer_every_get_cpu)
-- 异步执行
ngx.timer.every(3, timer_stats_total_log)
end
-1
View File
@@ -1 +0,0 @@
waf()
+1 -1
View File
@@ -1 +1 @@
[[1, "(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)", "\u5173\u952e\u8bcd\u8fc7\u6ee41", 0]]
[[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[1,"(ApacheBench)","AB测试",0]]
+1 -1
View File
@@ -1 +1 @@
{"rules":{"user_agent":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
{"rules":{"path":0,"php_path":0,"upload_ext":0,"user_agent":0,"scan":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
-24
View File
@@ -1,24 +0,0 @@
\.\./
\:\$
\$\{
/\*|--
\b(or|xor|and)\b.*(=|<|>|'|")
select.+(from|limit)
(?:(union(.*?)select))
having|load_file
sleep\((\s*)(\d*)(\s*)\)
benchmark\((.*)\,(.*)\)
base64_decode\(
(?:from\W+information_schema\W)
(?:(?:current_)user|database|schema|connection_id)\s*\(
(?:etc\/\W*passwd)
into(\s+)+(?:dump|out)file\s*
group\s+by.+\(
xwork.MethodAccessor
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(
xwork\.MethodAccessor
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/
java\.lang
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[
\<(iframe|script|body|img|layer|div|meta|style|base|object|input)
(onmouseover|onerror|onload)\=
-1
View File
@@ -1 +0,0 @@
10.0.68.75
-20
View File
@@ -1,20 +0,0 @@
\.\./
\:\$
\$\{
select.+(from|limit)
(?:(union(.*?)select))
having|rongjitest
sleep\((\s*)(\d*)(\s*)\)
benchmark\((.*)\,(.*)\)
base64_decode\(
(?:from\W+information_schema\W)
(?:(?:current_)user|database|schema|connection_id)\s*\(
(?:etc\/\W*passwd)
into(\s+)+(?:dump|out)file\s*
group\s+by.+\(
xwork.MethodAccessor
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(
xwork\.MethodAccessor
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/
java\.lang
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[
-7
View File
@@ -1,7 +0,0 @@
#ip 60/60 1800
#ip+uri 60/60 1800
#ip+domain+CookieParam:sessionid 60/60 1800
#ip+GetParam:userid 60/60 1800
#ip+PostParam:userid 60/60 1800
#$ip+header:imei 30/60 1800
ip+uri 60/60 3600
-18
View File
@@ -1,18 +0,0 @@
select.+(from|limit)
(?:(union(.*?)select))
\b(or|xor|and)\b.*(=|<|>|'|")
having|load_file
sleep\((\s*)(\d*)(\s*)\)
benchmark\((.*)\,(.*)\)
base64_decode\(
(?:from\W+information_schema\W)
into(\s+)+(?:dump|out)file\s*
group\s+by.+\(
xwork.MethodAccessor
(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(
xwork\.MethodAccessor
(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/
java\.lang
\$_(GET|post|cookie|files|session|env|phplib|GLOBALS|SERVER)\[
\<(iframe|script|body|img|layer|div|meta|style|base|object|input)
(onmouseover|onerror|onload)\=
-39
View File
@@ -1,39 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>网站防火墙</title>
<style>
*{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;}
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
.t2{margin-bottom:8px; font-weight:bold}
ol{margin:0 0 20px 22px;padding:0;}
ol li{line-height:30px}
</style>
</head>
<body>
<div class="main">
<div class="title">网站防火墙</div>
<div class="content">
<p class="t1">您的请求带有不合法参数,已被网站管理员设置拦截!</p>
<p class="t2">可能原因:</p>
<ol>
<li>您提交的内容包含危险的攻击请求</li>
</ol>
<p class="t2">如何解决:</p>
<ol>
<li>检查提交内容;</li>
<li>如网站托管,请联系空间提供商;</li>
<li>普通网站访客,请联系网站管理员;</li>
<li>这是误报,请联系网站管理员;</li>
</ol>
</div>
</div>
</body>
</html>
-9
View File
@@ -1,9 +0,0 @@
\.(svn|htaccess|mysql_history|bash_history|git|DS_Store|idea|user\.ini)
\.(bak|inc|old|mdb|sh|sql|php~|swp|java|class)$
(vhost|bbs|host|wwwroot|www|site|root|backup|data|ftp|db|admin|website|web).*\.(rar|sql|zip|tar\.gz|tar)
(elastic|jmx-console|jmxinvokerservlet)
java\.lang
/CSV/
/(hack|shell|spy|phpspy)\.php$
(manager|host-manager)/html$
/(attachments|upimg|images|css|uploadfiles|html|uploads|templets|static|template|data|forumdata|upload|includes|cache|avatar)/(\\w+).(php|jsp)
-1
View File
@@ -1 +0,0 @@
(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf|bench| SF/)
-2
View File
@@ -1,2 +0,0 @@
127.0.0.1
^192\.168\.
-309
View File
@@ -1,309 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import subprocess
sys.path.append(os.getcwd() + "/class/core")
import mw
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'openresty'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile():
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName()
def getArgs():
args = sys.argv[2:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def clearTemp():
path_bin = getServerDir() + "/nginx"
mw.execShell('rm -rf ' + path_bin + '/client_body_temp')
mw.execShell('rm -rf ' + path_bin + '/fastcgi_temp')
mw.execShell('rm -rf ' + path_bin + '/proxy_temp')
mw.execShell('rm -rf ' + path_bin + '/scgi_temp')
mw.execShell('rm -rf ' + path_bin + '/uwsgi_temp')
def getConf():
path = getServerDir() + "/nginx/conf/nginx.conf"
return path
def getConfTpl():
path = getPluginDir() + '/conf/nginx.conf'
return path
def getOs():
data = {}
data['os'] = mw.getOs()
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
if checkAuthEq(ng_exe_bin, 'root'):
data['auth'] = True
else:
data['auth'] = False
return mw.getJson(data)
def getInitDTpl():
path = getPluginDir() + "/init.d/nginx.tpl"
return path
def makeConf():
vhost = getServerDir() + '/nginx/conf/vhost'
if not os.path.exists(vhost):
os.mkdir(vhost)
php_status = getServerDir() + '/nginx/conf/php_status'
if not os.path.exists(php_status):
os.mkdir(php_status)
def getFileOwner(filename):
import pwd
stat = os.lstat(filename)
uid = stat.st_uid
pw = pwd.getpwuid(uid)
return pw.pw_name
def checkAuthEq(file, owner='root'):
fowner = getFileOwner(file)
if (fowner == owner):
return True
return False
def confReplace():
service_path = os.path.dirname(os.getcwd())
content = mw.readFile(getConfTpl())
content = content.replace('{$SERVER_PATH}', service_path)
user = 'www'
user_group = 'www'
if mw.getOs() == 'darwin':
# macosx do
user = mw.execShell(
"who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
# user = 'root'
user_group = 'staff'
content = content.replace('{$EVENT_MODEL}', 'kqueue')
else:
content = content.replace('{$EVENT_MODEL}', 'epoll')
content = content.replace('{$OS_USER}', user)
content = content.replace('{$OS_USER_GROUP}', user_group)
nconf = getServerDir() + '/nginx/conf/nginx.conf'
__content = mw.readFile(nconf)
if __content.find('#user'):
mw.writeFile(getServerDir() + '/nginx/conf/nginx.conf', content)
# give nginx root permission
ng_exe_bin = getServerDir() + "/nginx/sbin/nginx"
if not checkAuthEq(ng_exe_bin, 'root'):
args = getArgs()
sudoPwd = args['pwd']
cmd_own = 'chown -R ' + 'root:' + user_group + ' ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_own))
cmd_mod = 'chmod 755 ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_mod))
cmd_s = 'chmod u+s ' + ng_exe_bin
os.system('echo %s|sudo -S %s' % (sudoPwd, cmd_s))
def initDreplace():
file_tpl = getInitDTpl()
service_path = os.path.dirname(os.getcwd())
initD_path = getServerDir() + '/init.d'
# Openresty is not installed
if not os.path.exists(getServerDir()):
print("ok")
exit(0)
file_bin = initD_path + '/' + getPluginName()
if not os.path.exists(initD_path):
os.mkdir(initD_path)
# initd replace
content = mw.readFile(file_tpl)
content = content.replace('{$SERVER_PATH}', service_path)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
# config replace
confReplace()
# make nginx vhost or other
makeConf()
return file_bin
def status():
data = mw.execShell(
"ps -ef|grep nginx |grep -v grep | grep -v python | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
def start():
file = initDreplace()
data = mw.execShell(file + ' start')
if data[1] == '':
return 'ok'
return data[1]
def stop():
file = initDreplace()
data = mw.execShell(file + ' stop')
clearTemp()
if data[1] == '':
return 'ok'
return data[1]
def restart():
file = initDreplace()
data = mw.execShell(file + ' restart')
if data[1] == '':
return 'ok'
return data[1]
def reload():
file = initDreplace()
data = mw.execShell(file + ' reload')
if data[1] == '':
return 'ok'
return data[1]
def initdStatus():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
initd_bin = getInitDFile()
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
def initdInstall():
import shutil
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
source_bin = initDreplace()
initd_bin = getInitDFile()
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName())
return 'ok'
def initdUinstall():
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('chkconfig --del ' + getPluginName())
initd_bin = getInitDFile()
os.remove(initd_bin)
return 'ok'
def runInfo():
# 取Openresty负载状态
try:
result = mw.httpGet('http://127.0.0.1/nginx_status')
tmp = result.split()
data = {}
data['active'] = tmp[2]
data['accepts'] = tmp[9]
data['handled'] = tmp[7]
data['requests'] = tmp[8]
data['Reading'] = tmp[11]
data['Writing'] = tmp[13]
data['Waiting'] = tmp[15]
return mw.getJson(data)
except Exception as e:
return 'oprenresty not started'
def errorLogPath():
return getServerDir() + '/nginx/logs/error.log'
if __name__ == "__main__":
func = sys.argv[1]
if func == 'status':
print(status())
elif func == 'start':
print(start())
elif func == 'stop':
print(stop())
elif func == 'restart':
print(restart())
elif func == 'reload':
print(reload())
elif func == 'initd_status':
print(initdStatus())
elif func == 'initd_install':
print(initdInstall())
elif func == 'initd_uninstall':
print(initdUinstall())
elif func == 'conf':
print(getConf())
elif func == 'get_os':
print(getOs())
elif func == 'run_info':
print(runInfo())
elif func == 'error_log':
print(errorLogPath())
else:
print('error')
+3
View File
@@ -64,6 +64,9 @@ Install_openresty()
--with-http_slice_module \
--with-http_stub_status_module \
--with-http_realip_module
# --without-luajit-gc64
# --with-debug
# 用于调式
make -j${cpuCore} && make install && make clean
+1
View File
@@ -5,6 +5,7 @@ group = {$PHP_GROUP}
listen = /run/php/php{$PHP_VERSION}-fpm.sock
listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
+39
View File
@@ -1,3 +1,41 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
@@ -13,6 +51,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
+182
View File
@@ -490,6 +490,180 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
content = mw.execShell(
'cat /etc/php/' + version + '/fpm/conf.d/*' + " | grep -v '^;' |tr -s '\n'")
content = content[0]
if save_handler == "memcached":
if not re.search("memcached.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "memcache":
if not content.find('memcache') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "redis":
if not content.find('redis') > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = ["/tmp", "/var/lib/php/sessions", session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version):
filename = getConf(version)
if not os.path.exists(filename):
@@ -688,6 +862,14 @@ if __name__ == "__main__":
print(setFpmConfig(version))
elif func == 'get_fpm_status':
print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func':
print(getDisableFunc(version))
elif func == 'set_disable_func':
+145
View File
@@ -368,6 +368,151 @@ function disableFunc(version) {
$(".soft-man-con").html(con);
});
}
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//设置禁用函数
function setDisableFunc(version, act, fs) {
var fsArr = fs.split(',');
+2
View File
@@ -5,6 +5,8 @@ group = {$PHP_GROUP}
listen = /var/opt/remi/php{$PHP_VERSION}/run/php-fpm/www.sock
listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
+38
View File
@@ -1,3 +1,40 @@
<style type="text/css">
.bt-w-main{
height: 600px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
@@ -13,6 +50,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
+182
View File
@@ -492,6 +492,180 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
content = mw.execShell('cat /etc/opt/remi/php' +
version + "/php.d/* | grep -v '^;' |tr -s '\n'")
content = content[0]
if save_handler == "memcached":
if not content.find("memcached.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "memcache":
if not content.find("memcache.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "redis":
if not content.find("redis.so") > -1:
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini)
mw.writeFile(filename, phpini)
restart(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = ["/tmp", session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version):
filename = getConf(version)
if not os.path.exists(filename):
@@ -689,6 +863,14 @@ if __name__ == "__main__":
print(setFpmConfig(version))
elif func == 'get_fpm_status':
print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func':
print(getDisableFunc(version))
elif func == 'set_disable_func':
+141
View File
@@ -340,6 +340,147 @@ function getFpmStatus(version){
});
}
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//禁用函数
function disableFunc(version) {
phpPost('get_disable_func', version,'',function(data){
-725
View File
@@ -1,725 +0,0 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
import shutil
# reload(sys)
# sys.setdefaultencoding('utf8')
sys.path.append(os.getcwd() + "/class/core")
# sys.path.append("/usr/local/lib/python3.6/site-packages")
import mw
if mw.isAppleSystem():
cmd = 'ls /usr/local/lib/ | grep python | cut -d \\ -f 1 | awk \'END {print}\''
info = mw.execShell(cmd)
p = "/usr/local/lib/" + info[0].strip() + "/site-packages"
sys.path.append(p)
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'php'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
def getServerDir():
return mw.getServerDir() + '/' + getPluginName()
def getInitDFile(version):
if app_debug:
return '/tmp/' + getPluginName()
return '/etc/init.d/' + getPluginName() + version
def getArgs():
args = sys.argv[3:]
tmp = {}
args_len = len(args)
if args_len == 1:
t = args[0].strip('{').strip('}')
t = t.split(':')
tmp[t[0]] = t[1]
elif args_len > 1:
for i in range(len(args)):
t = args[i].split(':')
tmp[t[0]] = t[1]
return tmp
def checkArgs(data, ck=[]):
for i in range(len(ck)):
if not ck[i] in data:
return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!'))
return (True, mw.returnJson(True, 'ok'))
def getConf(version):
path = getServerDir() + '/' + version + '/etc/php.ini'
return path
def status(version):
cmd = "ps -ef|grep 'php/" + version + \
"' |grep -v grep | grep -v python | awk '{print $2}'"
data = mw.execShell(cmd)
if data[0] == '':
return 'stop'
return 'start'
def contentReplace(content, version):
service_path = mw.getServerDir()
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
content = content.replace('{$SERVER_PATH}', service_path)
content = content.replace('{$PHP_VERSION}', version)
content = content.replace('{$LOCAL_IP}', mw.getLocalIp())
if mw.isAppleSystem():
# user = mw.execShell(
# "who | sed -n '2, 1p' |awk '{print $1}'")[0].strip()
content = content.replace('{$PHP_USER}', 'nobody')
content = content.replace('{$PHP_GROUP}', 'nobody')
rep = 'listen.owner\s*=\s*(.+)\r?\n'
val = ';listen.owner = nobody\n'
content = re.sub(rep, val, content)
rep = 'listen.group\s*=\s*(.+)\r?\n'
val = ';listen.group = nobody\n'
content = re.sub(rep, val, content)
rep = 'user\s*=\s*(.+)\r?\n'
val = ';user = nobody\n'
content = re.sub(rep, val, content)
rep = r'[^\.]group\s*=\s*(.+)\r?\n'
val = ';group = nobody\n'
content = re.sub(rep, val, content)
else:
content = content.replace('{$PHP_USER}', 'www')
content = content.replace('{$PHP_GROUP}', 'www')
return content
def makeOpenrestyConf():
phpversions = ['00', '52', '53', '54', '55', '56',
'70', '71', '72', '73', '74', '80', '81']
if mw.isInstalledWeb():
sdir = mw.getServerDir()
d_pathinfo = sdir + '/openresty/nginx/conf/pathinfo.conf'
if not os.path.exists(d_pathinfo):
s_pathinfo = getPluginDir() + '/conf/pathinfo.conf'
shutil.copyfile(s_pathinfo, d_pathinfo)
info = getPluginDir() + '/info.json'
content = mw.readFile(info)
content = json.loads(content)
versions = content['versions']
tpl = getPluginDir() + '/conf/enable-php.conf'
tpl_content = mw.readFile(tpl)
for x in phpversions:
dfile = sdir + '/openresty/nginx/conf/enable-php-' + x + '.conf'
if not os.path.exists(dfile):
if x == '00':
mw.writeFile(dfile, '')
else:
w_content = contentReplace(tpl_content, x)
mw.writeFile(dfile, w_content)
# php-fpm status
for version in phpversions:
dfile = sdir + '/openresty/nginx/conf/php_status/phpfpm_status_' + version + '.conf'
tpl = getPluginDir() + '/conf/phpfpm_status.conf'
if not os.path.exists(dfile):
content = mw.readFile(tpl)
content = contentReplace(content, version)
mw.writeFile(dfile, content)
mw.restartWeb()
def phpPrependFile(version):
app_start = getServerDir() + '/app_start.php'
if not os.path.exists(app_start):
tpl = getPluginDir() + '/conf/app_start.php'
content = mw.readFile(tpl)
content = contentReplace(content, version)
mw.writeFile(app_start, content)
def phpFpmReplace(version):
desc_php_fpm = getServerDir() + '/' + version + '/etc/php-fpm.conf'
if not os.path.exists(desc_php_fpm):
tpl_php_fpm = getPluginDir() + '/conf/php-fpm.conf'
content = mw.readFile(tpl_php_fpm)
content = contentReplace(content, version)
mw.writeFile(desc_php_fpm, content)
else:
if version == '52':
tpl_php_fpm = tpl_php_fpm = getPluginDir() + '/conf/php-fpm-52.conf'
content = mw.readFile(tpl_php_fpm)
mw.writeFile(desc_php_fpm, content)
def phpFpmWwwReplace(version):
service_php_fpm_dir = getServerDir() + '/' + version + '/etc/php-fpm.d/'
if not os.path.exists(service_php_fpm_dir):
os.mkdir(service_php_fpm_dir)
service_php_fpmwww = service_php_fpm_dir + '/www.conf'
if not os.path.exists(service_php_fpmwww):
tpl_php_fpmwww = getPluginDir() + '/conf/www.conf'
content = mw.readFile(tpl_php_fpmwww)
content = contentReplace(content, version)
mw.writeFile(service_php_fpmwww, content)
def makePhpIni(version):
d_ini = mw.getServerDir() + '/php/' + version + '/etc/php.ini'
if not os.path.exists(d_ini):
s_ini = getPluginDir() + '/conf/php' + version[0:1] + '.ini'
# shutil.copyfile(s_ini, d_ini)
content = mw.readFile(s_ini)
if version == '52':
content = content + "auto_prepend_file=/www/server/php/app_start.php"
mw.writeFile(d_ini, content)
def initReplace(version):
makeOpenrestyConf()
makePhpIni(version)
initD_path = getServerDir() + '/init.d'
if not os.path.exists(initD_path):
os.mkdir(initD_path)
file_bin = initD_path + '/php' + version
if not os.path.exists(file_bin):
file_tpl = getPluginDir() + '/init.d/php.tpl'
if version == '52':
file_tpl = getPluginDir() + '/init.d/php52.tpl'
content = mw.readFile(file_tpl)
content = contentReplace(content, version)
mw.writeFile(file_bin, content)
mw.execShell('chmod +x ' + file_bin)
phpPrependFile(version)
phpFpmWwwReplace(version)
phpFpmReplace(version)
session_path = '/tmp/session'
if not os.path.exists(session_path):
os.mkdir(session_path)
if not mw.isAppleSystem():
mw.execShell('chown -R www:www ' + session_path)
upload_path = '/tmp/upload'
if not os.path.exists(upload_path):
os.mkdir(upload_path)
if not mw.isAppleSystem():
mw.execShell('chown -R www:www ' + upload_path)
return file_bin
def phpOp(version, method):
file = initReplace(version)
data = mw.execShell(file + ' ' + method)
if data[1] == '':
return 'ok'
return data[1]
def start(version):
return phpOp(version, 'start')
def stop(version):
return phpOp(version, 'stop')
def restart(version):
return phpOp(version, 'restart')
def reload(version):
return phpOp(version, 'reload')
def initdStatus(version):
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
initd_bin = getInitDFile(version)
if os.path.exists(initd_bin):
return 'ok'
return 'fail'
def initdInstall(version):
import shutil
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
source_bin = initReplace(version)
initd_bin = getInitDFile(version)
shutil.copyfile(source_bin, initd_bin)
mw.execShell('chmod +x ' + initd_bin)
mw.execShell('chkconfig --add ' + getPluginName() + version)
return 'ok'
def initdUinstall(version):
if not app_debug:
if mw.isAppleSystem():
return "Apple Computer does not support"
mw.execShell('chkconfig --del ' + getPluginName())
initd_bin = getInitDFile(version)
os.remove(initd_bin)
return 'ok'
def fpmLog(version):
return getServerDir() + '/' + version + '/var/log/php-fpm.log'
def fpmSlowLog(version):
return getServerDir() + '/' + version + '/var/log/www-slow.log'
def getPhpConf(version):
gets = [
{'name': 'short_open_tag', 'type': 1, 'ps': '短标签支持'},
{'name': 'asp_tags', 'type': 1, 'ps': 'ASP标签支持'},
{'name': 'max_execution_time', 'type': 2, 'ps': '最大脚本运行时间'},
{'name': 'max_input_time', 'type': 2, 'ps': '最大输入时间'},
{'name': 'max_input_var', 'type': 2, 'ps': '最大输入数量'},
{'name': 'memory_limit', 'type': 2, 'ps': '脚本内存限制'},
{'name': 'post_max_size', 'type': 2, 'ps': 'POST数据最大尺寸'},
{'name': 'file_uploads', 'type': 1, 'ps': '是否允许上传文件'},
{'name': 'upload_max_filesize', 'type': 2, 'ps': '允许上传文件的最大尺寸'},
{'name': 'max_file_uploads', 'type': 2, 'ps': '允许同时上传文件的最大数量'},
{'name': 'default_socket_timeout', 'type': 2, 'ps': 'Socket超时时间'},
{'name': 'error_reporting', 'type': 3, 'ps': '错误级别'},
{'name': 'display_errors', 'type': 1, 'ps': '是否输出详细错误信息'},
{'name': 'cgi.fix_pathinfo', 'type': 0, 'ps': '是否开启pathinfo'},
{'name': 'date.timezone', 'type': 3, 'ps': '时区'}
]
phpini = mw.readFile(getServerDir() + '/' + version + '/etc/php.ini')
result = []
for g in gets:
rep = g['name'] + '\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
tmp = re.search(rep, phpini)
if not tmp:
continue
g['value'] = tmp.groups()[0]
result.append(g)
return mw.getJson(result)
def submitPhpConf(version):
gets = ['display_errors', 'cgi.fix_pathinfo', 'date.timezone', 'short_open_tag',
'asp_tags', 'max_execution_time', 'max_input_time', 'memory_limit',
'post_max_size', 'file_uploads', 'upload_max_filesize', 'max_file_uploads',
'default_socket_timeout', 'error_reporting']
args = getArgs()
filename = getServerDir() + '/' + version + '/etc/php.ini'
phpini = mw.readFile(filename)
for g in gets:
if g in args:
rep = g + '\s*=\s*(.+)\r?\n'
val = g + ' = ' + args[g] + '\n'
phpini = re.sub(rep, val, phpini)
mw.writeFile(filename, phpini)
mw.execShell(getServerDir() + '/init.d/php' + version + ' reload')
return mw.returnJson(True, '设置成功')
def getLimitConf(version):
fileini = getServerDir() + "/" + version + "/etc/php.ini"
phpini = mw.readFile(fileini)
filefpm = getServerDir() + "/" + version + "/etc/php-fpm.conf"
phpfpm = mw.readFile(filefpm)
# print fileini, filefpm
data = {}
try:
rep = "upload_max_filesize\s*=\s*([0-9]+)M"
tmp = re.search(rep, phpini).groups()
data['max'] = tmp[0]
except:
data['max'] = '50'
try:
rep = "request_terminate_timeout\s*=\s*([0-9]+)\n"
tmp = re.search(rep, phpfpm).groups()
data['maxTime'] = tmp[0]
except:
data['maxTime'] = 0
try:
rep = r"\n;*\s*cgi\.fix_pathinfo\s*=\s*([0-9]+)\s*\n"
tmp = re.search(rep, phpini).groups()
if tmp[0] == '1':
data['pathinfo'] = True
else:
data['pathinfo'] = False
except:
data['pathinfo'] = False
return mw.getJson(data)
def setMaxTime(version):
args = getArgs()
data = checkArgs(args, ['time'])
if not data[0]:
return data[1]
time = args['time']
if int(time) < 30 or int(time) > 86400:
return mw.returnJson(False, '请填写30-86400间的值!')
filefpm = getServerDir() + "/" + version + "/etc/php-fpm.conf"
conf = mw.readFile(filefpm)
rep = "request_terminate_timeout\s*=\s*([0-9]+)\n"
conf = re.sub(rep, "request_terminate_timeout = " + time + "\n", conf)
mw.writeFile(filefpm, conf)
fileini = getServerDir() + "/" + version + "/etc/php.ini"
phpini = mw.readFile(fileini)
rep = "max_execution_time\s*=\s*([0-9]+)\r?\n"
phpini = re.sub(rep, "max_execution_time = " + time + "\n", phpini)
rep = "max_input_time\s*=\s*([0-9]+)\r?\n"
phpini = re.sub(rep, "max_input_time = " + time + "\n", phpini)
mw.writeFile(fileini, phpini)
return mw.returnJson(True, '设置成功!')
def setMaxSize(version):
args = getArgs()
if not 'max' in args:
return 'missing time args!'
max = args['max']
if int(max) < 2:
return mw.returnJson(False, '上传大小限制不能小于2MB!')
path = getServerDir() + '/' + version + '/etc/php.ini'
conf = mw.readFile(path)
rep = u"\nupload_max_filesize\s*=\s*[0-9]+M"
conf = re.sub(rep, u'\nupload_max_filesize = ' + max + 'M', conf)
rep = u"\npost_max_size\s*=\s*[0-9]+M"
conf = re.sub(rep, u'\npost_max_size = ' + max + 'M', conf)
mw.writeFile(path, conf)
msg = mw.getInfo('设置PHP-{1}最大上传大小为[{2}MB]!', (version, max,))
mw.writeLog('插件管理[PHP]', msg)
return mw.returnJson(True, '设置成功!')
def getFpmConfig(version):
filefpm = getServerDir() + '/' + version + '/etc/php-fpm.d/www.conf'
conf = mw.readFile(filefpm)
data = {}
rep = "\s*pm.max_children\s*=\s*([0-9]+)\s*"
tmp = re.search(rep, conf).groups()
data['max_children'] = tmp[0]
rep = "\s*pm.start_servers\s*=\s*([0-9]+)\s*"
tmp = re.search(rep, conf).groups()
data['start_servers'] = tmp[0]
rep = "\s*pm.min_spare_servers\s*=\s*([0-9]+)\s*"
tmp = re.search(rep, conf).groups()
data['min_spare_servers'] = tmp[0]
rep = "\s*pm.max_spare_servers \s*=\s*([0-9]+)\s*"
tmp = re.search(rep, conf).groups()
data['max_spare_servers'] = tmp[0]
rep = "\s*pm\s*=\s*(\w+)\s*"
tmp = re.search(rep, conf).groups()
data['pm'] = tmp[0]
return mw.getJson(data)
def setFpmConfig(version):
args = getArgs()
# if not 'max' in args:
# return 'missing time args!'
version = args['version']
max_children = args['max_children']
start_servers = args['start_servers']
min_spare_servers = args['min_spare_servers']
max_spare_servers = args['max_spare_servers']
pm = args['pm']
file = getServerDir() + '/' + version + '/etc/php-fpm.d/www.conf'
conf = mw.readFile(file)
rep = "\s*pm.max_children\s*=\s*([0-9]+)\s*"
conf = re.sub(rep, "\npm.max_children = " + max_children, conf)
rep = "\s*pm.start_servers\s*=\s*([0-9]+)\s*"
conf = re.sub(rep, "\npm.start_servers = " + start_servers, conf)
rep = "\s*pm.min_spare_servers\s*=\s*([0-9]+)\s*"
conf = re.sub(rep, "\npm.min_spare_servers = " +
min_spare_servers, conf)
rep = "\s*pm.max_spare_servers \s*=\s*([0-9]+)\s*"
conf = re.sub(rep, "\npm.max_spare_servers = " +
max_spare_servers + "\n", conf)
rep = "\s*pm\s*=\s*(\w+)\s*"
conf = re.sub(rep, "\npm = " + pm + "\n", conf)
mw.writeFile(file, conf)
reload(version)
msg = mw.getInfo('设置PHP-{1}并发设置,max_children={2},start_servers={3},min_spare_servers={4},max_spare_servers={5}', (version, max_children,
start_servers, min_spare_servers, max_spare_servers,))
mw.writeLog('插件管理[PHP]', msg)
return mw.returnJson(True, '设置成功!')
def checkFpmStatusFile(version):
if mw.isInstalledWeb():
sdir = mw.getServerDir()
dfile = sdir + '/openresty/nginx/conf/php_status/phpfpm_status_' + version + '.conf'
if not os.path.exists(dfile):
tpl = getPluginDir() + '/conf/phpfpm_status.conf'
content = mw.readFile(tpl)
content = contentReplace(content, version)
mw.writeFile(dfile, content)
mw.restartWeb()
def getFpmStatus(version):
checkFpmStatusFile(version)
result = mw.httpGet(
'http://127.0.0.1/phpfpm_status_' + version + '?json')
tmp = json.loads(result)
fTime = time.localtime(int(tmp['start time']))
tmp['start time'] = time.strftime('%Y-%m-%d %H:%M:%S', fTime)
return mw.getJson(tmp)
def getDisableFunc(version):
filename = mw.getServerDir() + '/php/' + version + '/etc/php.ini'
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
data = {}
rep = "disable_functions\s*=\s{0,1}(.*)\n"
tmp = re.search(rep, phpini).groups()
data['disable_functions'] = tmp[0]
return mw.getJson(data)
def setDisableFunc(version):
filename = mw.getServerDir() + '/php/' + version + '/etc/php.ini'
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
args = getArgs()
disable_functions = args['disable_functions']
phpini = mw.readFile(filename)
rep = "disable_functions\s*=\s*.*\n"
phpini = re.sub(rep, 'disable_functions = ' +
disable_functions + "\n", phpini)
msg = mw.getInfo('修改PHP-{1}的禁用函数为[{2}]', (version, disable_functions,))
mw.writeLog('插件管理[PHP]', msg)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def checkPhpinfoFile(v):
if mw.isInstalledWeb():
sdir = mw.getServerDir()
dfile = sdir + '/openresty/nginx/conf/php_status/phpinfo_' + v + '.conf'
if not os.path.exists(dfile):
tpl = getPluginDir() + '/conf/phpinfo.conf'
content = mw.readFile(tpl)
content = contentReplace(content, v)
mw.writeFile(dfile, content)
mw.restartWeb()
def getPhpinfo(v):
checkPhpinfoFile(v)
sPath = mw.getRootDir() + '/phpinfo/' + v
mw.execShell("rm -rf " + mw.getRootDir() + '/phpinfo')
mw.execShell("mkdir -p " + sPath)
mw.writeFile(sPath + '/phpinfo.php', '<?php phpinfo(); ?>')
url = 'http://127.0.0.1/' + v + '/phpinfo.php'
phpinfo = mw.httpGet(url)
os.system("rm -rf " + mw.getRootDir() + '/phpinfo')
return phpinfo
def get_php_info(args):
return getPhpinfo(args['version'])
def getLibConf(version):
fname = mw.getServerDir() + '/php/' + version + '/etc/php.ini'
if not os.path.exists(fname):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(fname)
libpath = getPluginDir() + '/versions/phplib.conf'
phplib = json.loads(mw.readFile(libpath))
libs = []
tasks = mw.M('tasks').where(
"status!=?", ('1',)).field('status,name').select()
for lib in phplib:
lib['task'] = '1'
for task in tasks:
tmp = mw.getStrBetween('[', ']', task['name'])
if not tmp:
continue
tmp1 = tmp.split('-')
if tmp1[0].lower() == lib['name'].lower():
lib['task'] = task['status']
lib['phpversions'] = []
lib['phpversions'].append(tmp1[1])
if phpini.find(lib['check']) == -1:
lib['status'] = False
else:
lib['status'] = True
libs.append(lib)
return mw.returnJson(True, 'OK!', libs)
def installLib(version):
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
execstr = "cd " + getPluginDir() + '/versions/' + version + " && /bin/bash " + \
name + '.sh' + ' install ' + version
rettime = time.strftime('%Y-%m-%d %H:%M:%S')
insert_info = (None, '安装[' + name + '-' + version + ']',
'execshell', '0', rettime, execstr)
mw.M('tasks').add('id,name,type,status,addtime,execstr', insert_info)
return mw.returnJson(True, '已将下载任务添加到队列!')
def uninstallLib(version):
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
execstr = "cd " + getPluginDir() + '/versions/' + version + " && /bin/bash " + \
name + '.sh' + ' uninstall ' + version
data = mw.execShell(execstr)
if data[0] == '' and data[1] == '':
return mw.returnJson(True, '已经卸载成功!')
else:
return mw.returnJson(False, '卸载信息![通道0]:' + data[0] + "[通道0]:" + data[1])
def getConfAppStart():
pstart = mw.getServerDir() + '/php/app_start.php'
return pstart
if __name__ == "__main__":
if len(sys.argv) < 3:
print('missing parameters')
exit(0)
func = sys.argv[1]
version = sys.argv[2]
if func == 'status':
print(status(version))
elif func == 'start':
print(start(version))
elif func == 'stop':
print(stop(version))
elif func == 'restart':
print(restart(version))
elif func == 'reload':
print(reload(version))
elif func == 'initd_status':
print(initdStatus(version))
elif func == 'initd_install':
print(initdInstall(version))
elif func == 'initd_uninstall':
print(initdUinstall(version))
elif func == 'fpm_log':
print(fpmLog(version))
elif func == 'fpm_slow_log':
print(fpmSlowLog(version))
elif func == 'conf':
print(getConf(version))
elif func == 'app_start':
print(getConfAppStart())
elif func == 'get_php_conf':
print(getPhpConf(version))
elif func == 'submit_php_conf':
print(submitPhpConf(version))
elif func == 'get_limit_conf':
print(getLimitConf(version))
elif func == 'set_max_time':
print(setMaxTime(version))
elif func == 'set_max_size':
print(setMaxSize(version))
elif func == 'get_fpm_conf':
print(getFpmConfig(version))
elif func == 'set_fpm_conf':
print(setFpmConfig(version))
elif func == 'get_fpm_status':
print(getFpmStatus(version))
elif func == 'get_disable_func':
print(getDisableFunc(version))
elif func == 'set_disable_func':
print(setDisableFunc(version))
elif func == 'get_phpinfo':
print(getPhpinfo(version))
elif func == 'get_lib_conf':
print(getLibConf(version))
elif func == 'install_lib':
print(installLib(version))
elif func == 'uninstall_lib':
print(uninstallLib(version))
else:
print("fail")
+3
View File
@@ -1,9 +1,12 @@
[www]
user = {$PHP_USER}
group = {$PHP_GROUP}
listen = /tmp/php-cgi-{$PHP_VERSION}.sock
listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
+40 -1
View File
@@ -1,6 +1,43 @@
<style type="text/css">
.bt-w-main{
height: 642px;
}
.session_clear_list {
border:1px solid #ececec;
margin-bottom: 15px;
width: 270px;
}
.session_clear_list .line {
padding: 0;
border-bottom: 1px solid #ececec;
width: 270px;
}
.session_clear_list .line:last-child {
border-bottom: 0px;
}
.session_clear_list .line span{
width: auto;
height: 35px;
line-height: 35px;
text-align: left;
padding: 0 5px;
}
.session_clear_list .line span:first-child {
width: 170px;
border-right: 1px solid #ececec;
background: #f7f7f7;
float: left;
}
</style>
<div class="bt-form">
<div class='plugin_version'></div>
<div class="bt-w-main">
<div class="bt-w-main" >
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('php', $('.plugin_version').attr('version'));">服务</p>
<p onclick="pluginInitD('php', $('.plugin_version').attr('version'));">自启动</p>
@@ -13,6 +50,7 @@
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
@@ -24,6 +62,7 @@
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=php&f=js/php.js", function(){
pluginService('php', $('.plugin_version').attr('version'));
+179
View File
@@ -632,6 +632,176 @@ def getFpmStatus(version):
return mw.returnJson(True, "OK", data)
def getSessionConf(version):
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
save_handler = re.search(rep, phpini)
if save_handler:
save_handler = save_handler.group(1)
else:
save_handler = "files"
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
save_path = re.search(reppath, phpini)
if not save_path:
save_path = re.search(memcached, phpini)
passwd = re.search(passrep, phpini)
port = ""
if passwd:
passwd = passwd.group(1)
else:
passwd = ""
if save_path:
port = save_path.group(2)
save_path = save_path.group(1)
else:
save_path = ""
data = {"save_handler": save_handler, "save_path": save_path,
"passwd": passwd, "port": port}
return mw.returnJson(True, 'ok', data)
def setSessionConf(version):
args = getArgs()
ip = args['ip']
port = args['port']
passwd = args['passwd']
save_handler = args['save_handler']
if save_handler != "file":
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址')
try:
port = int(port)
if port >= 65535 or port < 1:
return mw.returnJson(False, '请输入正确的端口号')
except:
return mw.returnJson(False, '请输入正确的端口号')
prep = r"[\~\`\/\=]"
if re.search(prep, passwd):
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
filename = getConf(version)
if not os.path.exists(filename):
return mw.returnJson(False, '指定PHP版本不存在!')
phpini = mw.readFile(filename)
session_tmp = getServerDir() + "/tmp/session"
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
val = r'session.save_handler = ' + save_handler + '\n'
phpini = re.sub(rep, val, phpini)
if save_handler == "memcached":
if not re.search("memcached.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "memcache":
if not re.search("memcache.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "redis":
if not re.search("redis.so", phpini):
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
if passwd:
passwd = "?auth=" + passwd
else:
passwd = ""
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
res = re.search(rep, phpini)
if res:
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "file":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini):
phpini = re.sub(rep, val, phpini)
else:
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
mw.writeFile(filename, phpini)
reload(version)
return mw.returnJson(True, '设置成功!')
def getSessionCount_Origin(version):
session_tmp = getServerDir() + "/tmp/session"
d = [session_tmp]
count = 0
for i in d:
if not os.path.exists(i):
mw.execShell('mkdir -p %s' % i)
list = os.listdir(i)
for l in list:
if os.path.isdir(i + "/" + l):
l1 = os.listdir(i + "/" + l)
for ll in l1:
if "sess_" in ll:
count += 1
continue
if "sess_" in l:
count += 1
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
old_file = int(mw.execShell(s)[0].split("\n")[0])
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
old_file += int(mw.execShell(s)[0].split("\n")[0])
return {"total": count, "oldfile": old_file}
def getSessionCount(version):
data = getSessionCount_Origin(version)
return mw.returnJson(True, 'ok!', data)
def cleanSessionOld(version):
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
mw.execShell(s)
session_tmp = getServerDir() + "/tmp/session"
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
mw.execShell(s)
old_file_conf = getSessionCount_Origin(version)["oldfile"]
if old_file_conf == 0:
return mw.returnJson(True, '清理成功')
else:
return mw.returnJson(True, '清理失败')
def getDisableFunc(version):
filename = getConf(version)
if not os.path.exists(filename):
@@ -794,6 +964,7 @@ def installPreInspection(version):
return 'fedora[{}]不可安装'.format(sysId)
return 'ok'
if __name__ == "__main__":
if len(sys.argv) < 3:
@@ -847,6 +1018,14 @@ if __name__ == "__main__":
print(setFpmConfig(version))
elif func == 'get_fpm_status':
print(getFpmStatus(version))
elif func == 'get_session_conf':
print(getSessionConf(version))
elif func == 'set_session_conf':
print(setSessionConf(version))
elif func == 'get_session_count':
print(getSessionCount(version))
elif func == 'clean_session_old':
print(cleanSessionOld(version))
elif func == 'get_disable_func':
print(getDisableFunc(version))
elif func == 'set_disable_func':
+146 -14
View File
@@ -1,14 +1,3 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function phpPost(method, version, args,callback){
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
@@ -18,7 +7,7 @@ function phpPost(method, version, args,callback){
req_data['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args));
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
@@ -46,7 +35,7 @@ function phpPostCallbak(method, version, args,callback){
args['version'] = version;
if (typeof(args) == 'string'){
req_data['args'] = JSON.stringify(str2Obj(args));
req_data['args'] = JSON.stringify(toArrayObject(args));
} else {
req_data['args'] = JSON.stringify(args);
}
@@ -194,7 +183,7 @@ function getFpmConfig(version){
"<option value='3' " + (rdata.max_children == 100 ? 'selected' : '') + ">100并发</option>" +
"<option value='4' " + (rdata.max_children == 200 ? 'selected' : '') + ">200并发</option>" +
"<option value='5' " + (rdata.max_children == 300 ? 'selected' : '') + ">300并发</option>" +
"<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>"
"<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>";
var pms = [{ 'name': 'static', 'title': '静态' }, { 'name': 'dynamic', 'title': '动态' }];
var pmList = '';
for (var i = 0; i < pms.length; i++) {
@@ -340,6 +329,149 @@ function getFpmStatus(version){
});
}
function getSessionConfig(version){
phpPost('get_session_conf', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
var info = rdata.save_path.split(":");
var con = "<div class='conf_p'>" +
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
"</div>\
<ul class='help-info-text c7'>\
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
</ul>\
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
</div>\
</div>";
$(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){
$('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
$('input[name="passwd"]').attr('disabled','disabled');
}
// change event
$("select[name='save_handler']").change(function() {
var type = $(this).val();
var passwd = $('input[name="passwd"]').val();
if (passwd == ""){
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
}
var ip = $('input[name="ip"]').val();
if (ip == ""){
$('input[name="ip"]').val('127.0.0.1');
}
switch (type) {
case 'redis':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('6379');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'file':
$('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled');
break;
case 'memcache':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
case 'memcached':
var port = $('input[name="port"]').val();
if (port == ""){
$('input[name="port"]').val('11211');
}
$('input[name="ip"]').removeAttr('disabled');
$('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled');
break;
}
});
//load session stats
phpPost('get_session_count', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
if(!rdata.status){
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
return;
}
var rdata = rdata.data;
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
<div class='clear_conter'>\
<div class='session_clear_list'>\
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
</div>\
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
$("#session_clear").html(html_var);
$('#clean_func').click(function(){
phpPost('clean_session_old', version, '', function(ret_data){
var rdata = $.parseJSON(ret_data.data);
showMsg(rdata.msg,function(){
getSessionConfig(version);
},{ icon: rdata.status ? 1 : 2 });
});
});
});
});
}
function setSessionConfig(version){
var ip = $('input[name="ip"]').val();
var port = $('input[name="port"]').val();
var passwd = $('input[name="passwd"]').val();
var save_handler = $("select[name='save_handler']").val();
var data = {
ip:ip,
port:port,
passwd:passwd,
save_handler:save_handler,
};
phpPost('set_session_conf', version, data, function(ret_data){
var rdata = $.parseJSON(ret_data.data);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
}
//禁用函数
function disableFunc(version) {
phpPost('get_disable_func', version,'',function(data){
+23 -1
View File
@@ -56,6 +56,28 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/53/bin ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
@@ -88,7 +110,7 @@ if [ ! -d $serverPath/php/53/bin ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
+24 -1
View File
@@ -48,6 +48,29 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/${PHP_VER} ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
@@ -73,7 +96,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
$OPTIONS \
--enable-fpm
make clean && make
make clean && make -j${cpuCore}
#debian11,没有生成php54 man
if [ ! -f sapi/cli/php.1 ];then
+24 -1
View File
@@ -47,6 +47,29 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/55 ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
--prefix=$serverPath/php/55 \
@@ -71,7 +94,7 @@ if [ ! -d $serverPath/php/55 ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
+24 -1
View File
@@ -47,6 +47,29 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/56 ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
@@ -74,7 +97,7 @@ if [ ! -d $serverPath/php/56 ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
+4
View File
@@ -64,6 +64,10 @@ if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/70 ];then
+24 -1
View File
@@ -44,6 +44,29 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/71 ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
--prefix=$serverPath/php/71 \
@@ -67,7 +90,7 @@ if [ ! -d $serverPath/php/71 ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
+24 -1
View File
@@ -46,6 +46,29 @@ if [ "$IS_64BIT" == "64" ];then
OPTIONS="${OPTIONS} --with-libdir=lib64"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/72 ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
--prefix=$serverPath/php/72 \
@@ -69,7 +92,7 @@ if [ ! -d $serverPath/php/72 ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
+24 -1
View File
@@ -60,6 +60,29 @@ if version_lt "$libzip_version" "0.11.0" ;then
ZIP_OPTION="--with-libzip=$serverPath/lib/libzip"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/73 ];then
cd $sourcePath/php/php${PHP_VER} && ./configure \
--prefix=$serverPath/php/73 \
@@ -83,7 +106,7 @@ if [ ! -d $serverPath/php/73 ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
+23 -1
View File
@@ -76,6 +76,28 @@ if version_lt "$libzip_version" "0.11.0" ;then
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
if [ ! -d $serverPath/php/${PHP_VER} ];then
cd $sourcePath/php/php${PHP_VER} && make clean
@@ -102,7 +124,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
}
+25 -2
View File
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.0.23
version=8.0.24
PHP_VER=80
Install_php()
{
@@ -67,6 +67,29 @@ if version_lt "$libzip_version" "0.11.0" ;then
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
echo "$sourcePath/php/php${PHP_VER}"
if [ ! -d $serverPath/php/${PHP_VER} ];then
@@ -94,7 +117,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
}
+24 -2
View File
@@ -16,7 +16,7 @@ function version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)"
function version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" == "$1"; }
version=8.1.10
version=8.1.11
PHP_VER=81
Install_php()
{
@@ -61,6 +61,28 @@ if version_lt "$libzip_version" "0.11.0" ;then
ZIP_OPTION="--with-zip=$serverPath/lib/libzip"
fi
# ----- cpu start ------
if [ -z "${cpuCore}" ]; then
cpuCore="1"
fi
if [ -f /proc/cpuinfo ];then
cpuCore=`cat /proc/cpuinfo | grep "processor" | wc -l`
fi
MEM_INFO=$(free -m|grep Mem|awk '{printf("%.f",($2)/1024)}')
if [ "${cpuCore}" != "1" ] && [ "${MEM_INFO}" != "0" ];then
if [ "${cpuCore}" -gt "${MEM_INFO}" ];then
cpuCore="${MEM_INFO}"
fi
else
cpuCore="1"
fi
if [ "$cpuCore" -gt "1" ];then
cpuCore=`echo "$cpuCore" | awk '{printf("%.f",($1)*0.8)}'`
fi
# ----- cpu end ------
echo "$sourcePath/php/php${PHP_VER}"
@@ -89,7 +111,7 @@ if [ ! -d $serverPath/php/${PHP_VER} ];then
--disable-fileinfo \
$OPTIONS \
--enable-fpm
make clean && make && make install && make clean
make clean && make -j${cpuCore} && make install && make clean
fi
#------------------------ install end ------------------------------------#
}

Some files were not shown because too many files have changed in this diff Show More